AT: Better failure handling and removed wrong unlock
[hayes-ril.git] / network.c
1 /*
2  * This file is part of hayes-ril.
3  *
4  * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
5  *
6  * Parts of this code are based on htcgeneric-ril, reference-ril:
7  * Copyright 2006-2011, htcgeneric-ril contributors
8  * Copyright 2006, The Android Open Source Project
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22
23 #define LOG_TAG "RIL-NET"
24 #include <utils/Log.h>
25 #include <telephony/ril.h>
26
27 #include <hayes-ril.h>
28
29 /*
30  * Signal Strength
31  */
32
33 void at2ril_signal_strength(RIL_SignalStrength *ss, int *values)
34 {
35         const int dbm_table[8] = {135,125,115,105,95,85,75,70};
36         const int edbm_table[8] = {120,110,100,90,80,75,70,65};
37         const int ecio_table[8] = {200,150,130,120,110,100,90,80};
38
39         memset(ss, 0, sizeof(RIL_SignalStrength));
40
41         if(ril_device->type == DEV_GSM) {
42                 ss->GW_SignalStrength.signalStrength = values[0];
43                 ss->GW_SignalStrength.bitErrorRate = values[1];
44         } else {
45                 /* 1st # is CDMA, 2nd is EVDO */
46                 ss->CDMA_SignalStrength.dbm = dbm_table[values[0]];
47                 ss->CDMA_SignalStrength.ecio = ecio_table[values[0]];
48                 ss->EVDO_SignalStrength.dbm = edbm_table[values[1]];
49                 ss->EVDO_SignalStrength.ecio = ecio_table[values[1]];
50                 ss->EVDO_SignalStrength.signalNoiseRatio = values[1];
51         }
52 }
53
54 int at_csq_expect(struct at_response *response, void *data, RIL_Token t)
55 {
56         struct at_response_data **response_data = NULL;
57         int response_data_count = 0;
58
59         RIL_SignalStrength ss;
60         int values[2] = { 0 };
61
62         if(response->status == AT_STATUS_UNDEF)
63                 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
64
65         if(response->data == NULL || response->data_count <= 0) {
66                 LOGE("No data given to AT+CSQ response!");
67                 return AT_RESPONSE_HANDLED_ERROR;
68         }
69
70         LOGE("Caught valid AT+CSQ response!");
71
72         response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
73         if(response_data_count < 2)
74                 goto error_data;
75
76         if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
77                 goto error_data;
78         values[0] = response_data[0]->value.n;
79
80         if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
81                 goto error_data;
82         values[1] = response_data[1]->value.n;
83
84         at2ril_signal_strength(&ss, values);
85
86         RIL_onRequestComplete(t, RIL_E_SUCCESS, &ss, sizeof(RIL_SignalStrength));
87
88         at_response_data_free(response_data, response_data_count);
89
90         return AT_RESPONSE_HANDLED_OK;
91
92 error_data:
93         LOGE("No valid data given to AT+CSQ response!");
94
95         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
96
97         at_response_data_free(response_data, response_data_count);
98         return AT_RESPONSE_HANDLED_ERROR;
99 }
100
101 void ril_request_signal_strength(RIL_Token t, void *data, size_t length)
102 {
103         at_send_expect_to_func("AT+CSQ", NULL, NULL, t, at_csq_expect);
104 }
105
106 /*
107  * Network registration
108  */
109
110 int at_creg_handle(char **registration_state, struct at_response_data **response_data, int response_data_count)
111 {
112         int state = 0;
113         char *lac = NULL;
114         char *cid = NULL;
115
116         if(registration_state == NULL || response_data == NULL || response_data_count <= 0)
117                 return -1;
118
119         /*
120          * Ok you have to be careful here
121          * The solicited version of the CREG response is
122          * +CREG: n, stat, [lac, cid]
123          * and the unsolicited version is
124          * +CREG: stat, [lac, cid]
125          * The <n> parameter is basically "is unsolicited creg on?"
126          * which it should always be
127          *
128          * Also since the LAC and CID are only reported when registered,
129          * we can have 1, 2, 3, or 4 arguments here
130          *
131          * finally, a +CGREG: answer may have a fifth value that corresponds
132          * to the network type, as in;
133          *
134          *   +CGREG: n, stat [,lac, cid [,networkType]]
135          */
136
137         // Only handle CREG responses
138         switch(response_data_count) {
139                 case 1: // UNSOL response, unregistered
140