2 * This file is part of hayes-ril.
4 * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
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
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #define LOG_TAG "RIL-NET"
24 #include <utils/Log.h>
25 #include <telephony/ril.h>
27 #include <hayes-ril.h>
33 void at2ril_signal_strength(RIL_SignalStrength *ss, int *values)
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};
39 memset(ss, 0, sizeof(RIL_SignalStrength));
41 if(ril_device->type == DEV_GSM) {
42 ss->GW_SignalStrength.signalStrength = values[0];
43 ss->GW_SignalStrength.bitErrorRate = values[1];
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];
54 int at_csq_expect(struct at_response *response, void *data, RIL_Token t)
56 struct at_response_data **response_data = NULL;
57 int response_data_count = 0;
59 RIL_SignalStrength ss;
60 int values[2] = { 0 };
62 if(response->status == AT_STATUS_UNDEF)
63 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
65 if(response->data == NULL || response->data_count <= 0) {
66 LOGE("No data given to AT+CSQ response!");
67 return AT_RESPONSE_HANDLED_ERROR;
70 LOGE("Caught valid AT+CSQ response!");
72 response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
73 if(response_data_count < 2)
76 if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
78 values[0] = response_data[0]->value.n;
80 if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
82 values[1] = response_data[1]->value.n;
84 at2ril_signal_strength(&ss, values);
86 RIL_onRequestComplete(t, RIL_E_SUCCESS, &ss, sizeof(RIL_SignalStrength));
88 at_response_data_free(response_data, response_data_count);
90 return AT_RESPONSE_HANDLED_OK;
93 LOGE("No valid data given to AT+CSQ response!");
95 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
97 at_response_data_free(response_data, response_data_count);
98 return AT_RESPONSE_HANDLED_ERROR;
101 void ril_request_signal_strength(RIL_Token t, void *data, size_t length)
103 at_send_expect_to_func("AT+CSQ", NULL, NULL, t, at_csq_expect);
107 * Network registration
110 int at_creg_handle(char **registration_state, struct at_response_data **response_data, int response_data_count)
116 if(registration_state == NULL || response_data == NULL || response_data_count <= 0)
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
128 * Also since the LAC and CID are only reported when registered,
129 * we can have 1, 2, 3, or 4 arguments here
131 * finally, a +CGREG: answer may have a fifth value that corresponds
132 * to the network type, as in;
134 * +CGREG: n, stat [,lac, cid [,networkType]]
137 // Only handle CREG responses
138 switch(response_data_count) {
139 case 1: // UNSOL response, unregistered
140 if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
142 state = response_data[0]->value.n;
145 case 2: // SOL response, unregistered
146 // Skip first argument
147 if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
149 state = response_data[1]->value.n;
152 case 3: // UNSOL response, registered
153 if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
155 state = response_data[0]->value.n;
157 if(response_data[1]->type != AT_RESPONSE_DATA_STRING)
159 lac = response_data[1]->value.s;
161 if(response_data[2]->type != AT_RESPONSE_DATA_STRING)
163 cid = response_data[2]->value.s;
166 case 4: // SOL response, registered
167 if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
169 state = response_data[1]->value.n;
171 if(response_data[2]->type != AT_RESPONSE_DATA_STRING)
173 lac = response_data[2]->value.s;
175 if(response_data[3]->type != AT_RESPONSE_DATA_STRING)
177 cid = response_data[3]->value.s;
184 asprintf(&(registration_state[0]), "%d", state);
185 registration_state[1] = strdup(lac);
186 registration_state[2] = strdup(cid);
191 void ril_registration_state_free(char **registration_state)
195 for(i=0 ; i < 14 ; i++) {
196 if(registration_state[i] != NULL)
197 free(registration_state[i]);
201 free(registration_state);
204 int at_creg_expect(struct at_response *response, void *data, RIL_Token t)
206 struct at_response_data **response_data = NULL;
207 int response_data_count = 0;
209 char **registration_state = NULL;
212 if(response->status == AT_STATUS_UNDEF)
213 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
215 if(response->data == NULL || response->data_count <= 0) {
216 LOGE("No data given to AT+CREG response!");
217 return AT_RESPONSE_HANDLED_ERROR;
220 LOGE("Caught valid AT+CREG response!");
222 response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
223 if(response_data_count <= 0)
226 registration_state = calloc(1, sizeof(char *) * 15);
227 rc = at_creg_handle(registration_state, response_data, response_data_count);
229 ril_registration_state_free(registration_state);
233 RIL_onRequestComplete(t, RIL_E_SUCCESS, registration_state, sizeof(char *) * 15);
235 ril_registration_state_free(registration_state);
236 at_response_data_free(response_data, response_data_count);
238 return AT_RESPONSE_HANDLED_OK;
241 LOGE("No valid data given to AT+CREG response!");
243 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
245 at_response_data_free(response_data, response_data_count);
247 return AT_RESPONSE_HANDLED_ERROR;
250 void at_creg_unexpect(struct at_response *response)
252 struct at_response_data **response_data = NULL;
253 int response_data_count = 0;
255 char **registration_state = NULL;
258 if(response->data == NULL || response->data_count <= 0) {
259 LOGE("No data given to AT+CREG unsol!");
263 LOGE("Caught valid AT+CREG unsol!");
265 response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
266 if(response_data_count <= 0)
269 registration_state = calloc(1, sizeof(char *) * 15);
270 rc = at_creg_handle(registration_state, response_data, response_data_count);
272 ril_registration_state_free(registration_state);
276 if(ril_globals.registration_state != NULL)
277 ril_registration_state_free(ril_globals.registration_state);
279 ril_globals.registration_state = registration_state;
281 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
284 LOGE("No valid data given to AT+CREG unsol!");
286 at_response_data_free(response_data, response_data_count);
289 void ril_request_registration_state(RIL_Token t, void *data, size_t length)
291 if(ril_globals.registration_state != NULL) {
292 // There is UNSOL data there
293 RIL_onRequestComplete(t, RIL_E_SUCCESS, ril_globals.registration_state, sizeof(char *) * 15);
295 ril_registration_state_free(ril_globals.registration_state);
296 ril_globals.registration_state = NULL;
298 at_send_expect_to_func("AT+CREG?", NULL, NULL, t, at_creg_expect);