1 /* //device/system/reference-ril/reference-ril.c
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include <telephony/ril_cdma_sms.h>
19 #include <telephony/librilutils.h>
20 #include <stdio.h>
21 #include <assert.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <pthread.h>
29 #include <alloca.h>
30 #include "atchannel.h"
31 #include "at_tok.h"
32 #include "misc.h"
33 #include <getopt.h>
34 #include <sys/socket.h>
35 #include <cutils/sockets.h>
36 #include <termios.h>
37 #include <sys/system_properties.h>
38
39 #include "ril.h"
40 #include "hardware/qemu_pipe.h"
41
42 #define LOG_TAG "RIL"
43 #include <utils/Log.h>
44
45 #define MAX_AT_RESPONSE 0x1000
46
47 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
48 #define PPP_TTY_PATH "eth0"
49
50 #ifdef USE_TI_COMMANDS
51
52 // Enable a workaround
53 // 1) Make incoming call, do not answer
54 // 2) Hangup remote end
55 // Expected: call should disappear from CLCC line
56 // Actual: Call shows as "ACTIVE" before disappearing
57 #define WORKAROUND_ERRONEOUS_ANSWER 1
58
59 // Some varients of the TI stack do not support the +CGEV unsolicited
60 // response. However, they seem to send an unsolicited +CME ERROR: 150
61 #define WORKAROUND_FAKE_CGEV 1
62 #endif
63
64 /* Modem Technology bits */
65 #define MDM_GSM 0x01
66 #define MDM_WCDMA 0x02
67 #define MDM_CDMA 0x04
68 #define MDM_EVDO 0x08
69 #define MDM_LTE 0x10
70
71 typedef struct {
72 int supportedTechs; // Bitmask of supported Modem Technology bits
73 int currentTech; // Technology the modem is currently using (in the format used by modem)
74 int isMultimode;
75
76 // Preferred mode bitmask. This is actually 4 byte-sized bitmasks with different priority values,
77 // in which the byte number from LSB to MSB give the priority.
78 //
79 // |MSB| | |LSB
80 // value: |00 |00 |00 |00
81 // byte #: |3 |2 |1 |0
82 //
83 // Higher byte order give higher priority. Thus, a value of 0x0000000f represents
84 // a preferred mode of GSM, WCDMA, CDMA, and EvDo in which all are equally preferrable, whereas
85 // 0x00000201 represents a mode with GSM and WCDMA, in which WCDMA is preferred over GSM
86 int32_t preferredNetworkMode;
87 int subscription_source;
88
89 } ModemInfo;
90
91 static ModemInfo *sMdmInfo;
92 // TECH returns the current technology in the format used by the modem.
93 // It can be used as an l-value
94 #define TECH(mdminfo) ((mdminfo)->currentTech)
95 // TECH_BIT returns the bitmask equivalent of the current tech
96 #define TECH_BIT(mdminfo) (1 << ((mdminfo)->currentTech))
97 #define IS_MULTIMODE(mdminfo) ((mdminfo)->isMultimode)
98 #define TECH_SUPPORTED(mdminfo, tech) ((mdminfo)->supportedTechs & (tech))
99 #define PREFERRED_NETWORK(mdminfo) ((mdminfo)->preferredNetworkMode)
100 // CDMA Subscription Source
101 #define SSOURCE(mdminfo) ((mdminfo)->subscription_source)
102
103 static int net2modem[] = {
104 MDM_GSM | MDM_WCDMA, // 0 - GSM / WCDMA Pref
105 MDM_GSM, // 1 - GSM only
106 MDM_WCDMA, // 2 - WCDMA only
107 MDM_GSM | MDM_WCDMA, // 3 - GSM / WCDMA Auto
108 MDM_CDMA | MDM_EVDO, // 4 - CDMA / EvDo Auto
109 MDM_CDMA, // 5 - CDMA only
110 MDM_EVDO, // 6 - EvDo only
111 MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO, // 7 - GSM/WCDMA, CDMA, EvDo
112 MDM_LTE | MDM_CDMA | MDM_EVDO, // 8 - LTE, CDMA and EvDo
113 MDM_LTE | MDM_GSM | MDM_WCDMA, // 9 - LTE, GSM/WCDMA
114 MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
115 MDM_LTE, // 11 - LTE only
116 };
117
118 static int32_t net2pmask[] = {
119 MDM_GSM | (MDM_WCDMA << 8), // 0 - GSM / WCDMA Pref
120 MDM_GSM, // 1 - GSM only
121 MDM_WCDMA, // 2 - WCDMA only
122 MDM_GSM | MDM_WCDMA, // 3 - GSM / WCDMA Auto
123 MDM_CDMA | MDM_EVDO, // 4 - CDMA / EvDo Auto
124 MDM_CDMA, // 5 - CDMA only
125 MDM_EVDO, // 6 - EvDo only
126 MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO, // 7 - GSM/WCDMA, CDMA, EvDo
127 MDM_LTE | MDM_CDMA | MDM_EVDO, // 8 - LTE, CDMA and EvDo
128 MDM_LTE | MDM_GSM | MDM_WCDMA, // 9 - LTE, GSM/WCDMA
129 MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
130 MDM_LTE, // 11 - LTE only
131 };
132
is3gpp2(int radioTech)133 static int is3gpp2(int radioTech) {
134 switch (radioTech) {
135 case RADIO_TECH_IS95A:
136 case RADIO_TECH_IS95B:
137 case RADIO_TECH_1xRTT:
138 case RADIO_TECH_EVDO_0:
139 case RADIO_TECH_EVDO_A:
140 case RADIO_TECH_EVDO_B:
141 case RADIO_TECH_EHRPD:
142 return 1;
143 default:
144 return 0;
145 }
146 }
147
148 typedef enum {
149 SIM_ABSENT = 0,
150 SIM_NOT_READY = 1,
151 SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
152 SIM_PIN = 3,
153 SIM_PUK = 4,
154 SIM_NETWORK_PERSONALIZATION = 5,
155 RUIM_ABSENT = 6,
156 RUIM_NOT_READY = 7,
157 RUIM_READY = 8,
158 RUIM_PIN = 9,
159 RUIM_PUK = 10,
160 RUIM_NETWORK_PERSONALIZATION = 11
161 } SIM_Status;
162
163 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
164 static RIL_RadioState currentState();
165 static int onSupports (int requestCode);
166 static void onCancel (RIL_Token t);
167 static const char *getVersion();
168 static int isRadioOn();
169 static SIM_Status getSIMStatus();
170 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status);
171 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status);
172 static void onDataCallListChanged(void *param);
173
174 extern const char * requestToString(int request);
175
176 /*** Static Variables ***/
177 static const RIL_RadioFunctions s_callbacks = {
178 RIL_VERSION,
179 onRequest,
180 currentState,
181 onSupports,
182 onCancel,
183 getVersion
184 };
185
186 #ifdef RIL_SHLIB
187 static const struct RIL_Env *s_rilenv;
188
189 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
190 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
191 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
192 #endif
193
194 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
195
196 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
197 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
198
199 static int s_port = -1;
200 static const char * s_device_path = NULL;
201 static int s_device_socket = 0;
202
203 /* trigger change to this with s_state_cond */
204 static int s_closed = 0;
205
206 static int sFD; /* file desc of AT channel */
207 static char sATBuffer[MAX_AT_RESPONSE+1];
208 static char *sATBufferCur = NULL;
209
210 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
211 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
212 static const struct timeval TIMEVAL_0 = {0,0};
213
214 #ifdef WORKAROUND_ERRONEOUS_ANSWER
215 // Max number of times we'll try to repoll when we think
216 // we have a AT+CLCC race condition
217 #define REPOLL_CALLS_COUNT_MAX 4
218
219 // Line index that was incoming or waiting at last poll, or -1 for none
220 static int s_incomingOrWaitingLine = -1;
221 // Number of times we've asked for a repoll of AT+CLCC
222 static int s_repollCallsCount = 0;
223 // Should we expect a call to be answered in the next CLCC?
224 static int s_expectAnswer = 0;
225 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
226
227 static int s_cell_info_rate_ms = INT_MAX;
228 static int s_mcc = 0;
229 static int s_mnc = 0;
230 static int s_lac = 0;
231 static int s_cid = 0;
232
233 static void pollSIMState (void *param);
234 static void setRadioState(RIL_RadioState newState);
235 static void setRadioTechnology(ModemInfo *mdm, int newtech);
236 static int query_ctec(ModemInfo *mdm, int *current, int32_t *preferred);
237 static int parse_technology_response(const char *response, int *current, int32_t *preferred);
238 static int techFromModemType(int mdmtype);
239
clccStateToRILState(int state,RIL_CallState * p_state)240 static int clccStateToRILState(int state, RIL_CallState *p_state)
241
242 {
243 switch(state) {
244 case 0: *p_state = RIL_CALL_ACTIVE; return 0;
245 case 1: *p_state = RIL_CALL_HOLDING; return 0;
246 case 2: *p_state = RIL_CALL_DIALING; return 0;
247 case 3: *p_state = RIL_CALL_ALERTING; return 0;
248 case 4: *p_state = RIL_CALL_INCOMING; return 0;
249 case 5: *p_state = RIL_CALL_WAITING; return 0;
250 default: return -1;
251 }
252 }
253
254 /**
255 * Note: directly modified line and has *p_call point directly into
256 * modified line
257 */
callFromCLCCLine(char * line,RIL_Call * p_call)258 static int callFromCLCCLine(char *line, RIL_Call *p_call)
259 {
260 //+CLCC: 1,0,2,0,0,\"+18005551212\",145
261 // index,isMT,state,mode,isMpty(,number,TOA)?
262
263 int err;
264 int state;
265 int mode;
266
267 err = at_tok_start(&line);
268 if (err < 0) goto error;
269
270 err = at_tok_nextint(&line, &(p_call->index));
271 if (err < 0) goto error;
272
273 err = at_tok_nextbool(&line, &(p_call->isMT));
274 if (err < 0) goto error;
275
276 err = at_tok_nextint(&line, &state);
277 if (err < 0) goto error;
278
279 err = clccStateToRILState(state, &(p_call->state));
280 if (err < 0) goto error;
281
282 err = at_tok_nextint(&line, &mode);
283 if (err < 0) goto error;
284
285 p_call->isVoice = (mode == 0);
286
287 err = at_tok_nextbool(&line, &(p_call->isMpty));
288 if (err < 0) goto error;
289
290 if (at_tok_hasmore(&line)) {
291 err = at_tok_nextstr(&line, &(p_call->number));
292
293 /* tolerate null here */
294 if (err < 0) return 0;
295
296 // Some lame implementations return strings
297 // like "NOT AVAILABLE" in the CLCC line
298 if (p_call->number != NULL
299 && 0 == strspn(p_call->number, "+0123456789")
300 ) {
301 p_call->number = NULL;
302 }
303
304 err = at_tok_nextint(&line, &p_call->toa);
305 if (err < 0) goto error;
306 }
307
308 p_call->uusInfo = NULL;
309
310 return 0;
311
312 error:
313 RLOGE("invalid CLCC line\n");
314 return -1;
315 }
316
317
318 /** do post-AT+CFUN=1 initialization */
onRadioPowerOn()319 static void onRadioPowerOn()
320 {
321 #ifdef USE_TI_COMMANDS
322 /* Must be after CFUN=1 */
323 /* TI specific -- notifications for CPHS things such */
324 /* as CPHS message waiting indicator */
325
326 at_send_command("AT%CPHS=1", NULL);
327
328 /* TI specific -- enable NITZ unsol notifs */
329 at_send_command("AT%CTZV=1", NULL);
330 #endif
331
332 pollSIMState(NULL);
333 }
334
335 /** do post- SIM ready initialization */
onSIMReady()336 static void onSIMReady()
337 {
338 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
339 /*
340 * Always send SMS messages directly to the TE
341 *
342 * mode = 1 // discard when link is reserved (link should never be
343 * reserved)
344 * mt = 2 // most messages routed to TE
345 * bm = 2 // new cell BM's routed to TE
346 * ds = 1 // Status reports routed to TE
347 * bfr = 1 // flush buffer
348 */
349 at_send_command("AT+CNMI=1,2,2,1,1", NULL);
350 }
351
requestRadioPower(void * data,size_t datalen,RIL_Token t)352 static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
353 {
354 int onOff;
355
356 int err;
357 ATResponse *p_response = NULL;
358
359 assert (datalen >= sizeof(int *));
360 onOff = ((int *)data)[0];
361
362 if (onOff == 0 && sState != RADIO_STATE_OFF) {
363 err = at_send_command("AT+CFUN=0", &p_response);
364 if (err < 0 || p_response->success == 0) goto error;
365 setRadioState(RADIO_STATE_OFF);
366 } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
367 err = at_send_command("AT+CFUN=1", &p_response);
368 if (err < 0|| p_response->success == 0) {
369 // Some stacks return an error when there is no SIM,
370 // but they really turn the RF portion on
371 // So, if we get an error, let's check to see if it
372 // turned on anyway
373
374 if (isRadioOn() != 1) {
375 goto error;
376 }
377 }
378 setRadioState(RADIO_STATE_ON);
379 }
380
381 at_response_free(p_response);
382 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
383 return;
384 error:
385 at_response_free(p_response);
386 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
387 }
388
389 static void requestOrSendDataCallList(RIL_Token *t);
390
onDataCallListChanged(void * param)391 static void onDataCallListChanged(void *param)
392 {
393 requestOrSendDataCallList(NULL);
394 }
395
requestDataCallList(void * data,size_t datalen,RIL_Token t)396 static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
397 {
398 requestOrSendDataCallList(&t);
399 }
400
requestOrSendDataCallList(RIL_Token * t)401 static void requestOrSendDataCallList(RIL_Token *t)
402 {
403 ATResponse *p_response;
404 ATLine *p_cur;
405 int err;
406 int n = 0;
407 char *out;
408
409 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
410 if (err != 0 || p_response->success == 0) {
411 if (t != NULL)
412 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
413 else
414 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
415 NULL, 0);
416 return;
417 }
418
419 for (p_cur = p_response->p_intermediates; p_cur != NULL;
420 p_cur = p_cur->p_next)
421 n++;
422
423 RIL_Data_Call_Response_v6 *responses =
424 alloca(n * sizeof(RIL_Data_Call_Response_v6));
425
426 int i;
427 for (i = 0; i < n; i++) {
428 responses[i].status = -1;
429 responses[i].suggestedRetryTime = -1;
430 responses[i].cid = -1;
431 responses[i].active = -1;
432 responses[i].type = "";
433 responses[i].ifname = "";
434 responses[i].addresses = "";
435 responses[i].dnses = "";
436 responses[i].gateways = "";
437 }
438
439 RIL_Data_Call_Response_v6 *response = responses;
440 for (p_cur = p_response->p_intermediates; p_cur != NULL;
441 p_cur = p_cur->p_next) {
442 char *line = p_cur->line;
443
444 err = at_tok_start(&line);
445 if (err < 0)
446 goto error;
447
448 err = at_tok_nextint(&line, &response->cid);
449 if (err < 0)
450 goto error;
451
452 err = at_tok_nextint(&line, &response->active);
453 if (err < 0)
454 goto error;
455
456 response++;
457 }
458
459 at_response_free(p_response);
460
461 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
462 if (err != 0 || p_response->success == 0) {
463 if (t != NULL)
464 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
465 else
466 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
467 NULL, 0);
468 return;
469 }
470
471 for (p_cur = p_response->p_intermediates; p_cur != NULL;
472 p_cur = p_cur->p_next) {
473 char *line = p_cur->line;
474 int cid;
475
476 err = at_tok_start(&line);
477 if (err < 0)
478 goto error;
479
480 err = at_tok_nextint(&line, &cid);
481 if (err < 0)
482 goto error;
483
484 for (i = 0; i < n; i++) {
485 if (responses[i].cid == cid)
486 break;
487 }
488
489 if (i >= n) {
490 /* details for a context we didn't hear about in the last request */
491 continue;
492 }
493
494 // Assume no error
495 responses[i].status = 0;
496
497 // type
498 err = at_tok_nextstr(&line, &out);
499 if (err < 0)
500 goto error;
501 responses[i].type = alloca(strlen(out) + 1);
502 strcpy(responses[i].type, out);
503
504 // APN ignored for v5
505 err = at_tok_nextstr(&line, &out);
506 if (err < 0)
507 goto error;
508
509 responses[i].ifname = alloca(strlen(PPP_TTY_PATH) + 1);
510 strcpy(responses[i].ifname, PPP_TTY_PATH);
511
512 err = at_tok_nextstr(&line, &out);
513 if (err < 0)
514 goto error;
515
516 responses[i].addresses = alloca(strlen(out) + 1);
517 strcpy(responses[i].addresses, out);
518
519 {
520 char propValue[PROP_VALUE_MAX];
521
522 if (__system_property_get("ro.kernel.qemu", propValue) != 0) {
523 /* We are in the emulator - the dns servers are listed
524 * by the following system properties, setup in
525 * /system/etc/init.goldfish.sh:
526 * - net.eth0.dns1
527 * - net.eth0.dns2
528 * - net.eth0.dns3
529 * - net.eth0.dns4
530 */
531 const int dnslist_sz = 128;
532 char* dnslist = alloca(dnslist_sz);
533 const char* separator = "";
534 int nn;
535
536 dnslist[0] = 0;
537 for (nn = 1; nn <= 4; nn++) {
538 /* Probe net.eth0.dns<n> */
539 char propName[PROP_NAME_MAX];
540 snprintf(propName, sizeof propName, "net.eth0.dns%d", nn);
541
542 /* Ignore if undefined */
543 if (__system_property_get(propName, propValue) == 0) {
544 continue;
545 }
546
547 /* Append the DNS IP address */
548 strlcat(dnslist, separator, dnslist_sz);
549 strlcat(dnslist, propValue, dnslist_sz);
550 separator = " ";
551 }
552 responses[i].dnses = dnslist;
553
554 /* There is only on gateway in the emulator */
555 responses[i].gateways = "10.0.2.2";
556 }
557 else {
558 /* I don't know where we are, so use the public Google DNS
559 * servers by default and no gateway.
560 */
561 responses[i].dnses = "8.8.8.8 8.8.4.4";
562 responses[i].gateways = "";
563 }
564 }
565 }
566
567 at_response_free(p_response);
568
569 if (t != NULL)
570 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
571 n * sizeof(RIL_Data_Call_Response_v6));
572 else
573 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
574 responses,
575 n * sizeof(RIL_Data_Call_Response_v6));
576
577 return;
578
579 error:
580 if (t != NULL)
581 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
582 else
583 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
584 NULL, 0);
585
586 at_response_free(p_response);
587 }
588
requestQueryNetworkSelectionMode(void * data,size_t datalen,RIL_Token t)589 static void requestQueryNetworkSelectionMode(
590 void *data, size_t datalen, RIL_Token t)
591 {
592 int err;
593 ATResponse *p_response = NULL;
594 int response = 0;
595 char *line;
596
597 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
598
599 if (err < 0 || p_response->success == 0) {
600 goto error;
601 }
602
603 line = p_response->p_intermediates->line;
604
605 err = at_tok_start(&line);
606
607 if (err < 0) {
608 goto error;
609 }
610
611 err = at_tok_nextint(&line, &response);
612
613 if (err < 0) {
614 goto error;
615 }
616
617 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
618 at_response_free(p_response);
619 return;
620 error:
621 at_response_free(p_response);
622 RLOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
623 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
624 }
625
sendCallStateChanged(void * param)626 static void sendCallStateChanged(void *param)
627 {
628 RIL_onUnsolicitedResponse (
629 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
630 NULL, 0);
631 }
632
requestGetCurrentCalls(void * data,size_t datalen,RIL_Token t)633 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
634 {
635 int err;
636 ATResponse *p_response;
637 ATLine *p_cur;
638 int countCalls;
639 int countValidCalls;
640 RIL_Call *p_calls;
641 RIL_Call **pp_calls;
642 int i;
643 int needRepoll = 0;
644
645 #ifdef WORKAROUND_ERRONEOUS_ANSWER
646 int prevIncomingOrWaitingLine;
647
648 prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
649 s_incomingOrWaitingLine = -1;
650 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
651
652 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
653
654 if (err != 0 || p_response->success == 0) {
655 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
656 return;
657 }
658
659 /* count the calls */
660 for (countCalls = 0, p_cur = p_response->p_intermediates
661 ; p_cur != NULL
662 ; p_cur = p_cur->p_next
663 ) {
664 countCalls++;
665 }
666
667 /* yes, there's an array of pointers and then an array of structures */
668
669 pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
670 p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
671 memset (p_calls, 0, countCalls * sizeof(RIL_Call));
672
673 /* init the pointer array */
674 for(i = 0; i < countCalls ; i++) {
675 pp_calls[i] = &(p_calls[i]);
676 }
677
678 for (countValidCalls = 0, p_cur = p_response->p_intermediates
679 ; p_cur != NULL
680 ; p_cur = p_cur->p_next
681 ) {
682 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
683
684 if (err != 0) {
685 continue;
686 }
687
688 #ifdef WORKAROUND_ERRONEOUS_ANSWER
689 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
690 || p_calls[countValidCalls].state == RIL_CALL_WAITING
691 ) {
692 s_incomingOrWaitingLine = p_calls[countValidCalls].index;
693 }
694 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
695
696 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
697 && p_calls[countValidCalls].state != RIL_CALL_HOLDING
698 ) {
699 needRepoll = 1;
700 }
701
702 countValidCalls++;
703 }
704
705 #ifdef WORKAROUND_ERRONEOUS_ANSWER
706 // Basically:
707 // A call was incoming or waiting
708 // Now it's marked as active
709 // But we never answered it
710 //
711 // This is probably a bug, and the call will probably
712 // disappear from the call list in the next poll
713 if (prevIncomingOrWaitingLine >= 0
714 && s_incomingOrWaitingLine < 0
715 && s_expectAnswer == 0
716 ) {
717 for (i = 0; i < countValidCalls ; i++) {
718
719 if (p_calls[i].index == prevIncomingOrWaitingLine
720 && p_calls[i].state == RIL_CALL_ACTIVE
721 && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
722 ) {
723 RLOGI(
724 "Hit WORKAROUND_ERRONOUS_ANSWER case."
725 " Repoll count: %d\n", s_repollCallsCount);
726 s_repollCallsCount++;
727 goto error;
728 }
729 }
730 }
731
732 s_expectAnswer = 0;
733 s_repollCallsCount = 0;
734 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
735
736 RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
737 countValidCalls * sizeof (RIL_Call *));
738
739 at_response_free(p_response);
740
741 #ifdef POLL_CALL_STATE
742 if (countValidCalls) { // We don't seem to get a "NO CARRIER" message from
743 // smd, so we're forced to poll until the call ends.
744 #else
745 if (needRepoll) {
746 #endif
747 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
748 }
749
750 return;
751 error:
752 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
753 at_response_free(p_response);
754 }
755
756 static void requestDial(void *data, size_t datalen, RIL_Token t)
757 {
758 RIL_Dial *p_dial;
759 char *cmd;
760 const char *clir;
761 int ret;
762
763 p_dial = (RIL_Dial *)data;
764
765 switch (p_dial->clir) {
766 case 1: clir = "I"; break; /*invocation*/
767 case 2: clir = "i"; break; /*suppression*/
768 default:
769 case 0: clir = ""; break; /*subscription default*/
770 }
771
772 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
773
774 ret = at_send_command(cmd, NULL);
775
776 free(cmd);
777
778 /* success or failure is ignored by the upper layer here.
779 it will call GET_CURRENT_CALLS and determine success that way */
780 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
781 }
782
783 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
784 {
785 RIL_SMS_WriteArgs *p_args;
786 char *cmd;
787 int length;
788 int err;
789 ATResponse *p_response = NULL;
790
791 p_args = (RIL_SMS_WriteArgs *)data;
792
793 length = strlen(p_args->pdu)/2;
794 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
795
796 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
797
798 if (err != 0 || p_response->success == 0) goto error;
799
800 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
801 at_response_free(p_response);
802
803 return;
804 error:
805 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
806 at_response_free(p_response);
807 }
808
809 static void requestHangup(void *data, size_t datalen, RIL_Token t)
810 {
811 int *p_line;
812
813 int ret;
814 char *cmd;
815
816 p_line = (int *)data;
817
818 // 3GPP 22.030 6.5.5
819 // "Releases a specific active call X"
820 asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
821
822 ret = at_send_command(cmd, NULL);
823
824 free(cmd);
825
826 /* success or failure is ignored by the upper layer here.
827 it will call GET_CURRENT_CALLS and determine success that way */
828 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
829 }
830
831 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
832 {
833 ATResponse *p_response = NULL;
834 int err;
835 char *line;
836 int count =0;
837 int numofElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
838 int response[numofElements];
839
840 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
841
842 if (err < 0 || p_response->success == 0) {
843 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
844 goto error;
845 }
846
847 line = p_response->p_intermediates->line;
848
849 err = at_tok_start(&line);
850 if (err < 0) goto error;
851
852 for (count =0; count < numofElements; count ++) {
853 err = at_tok_nextint(&line, &(response[count]));
854 if (err < 0) goto error;
855 }
856
857 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
858
859 at_response_free(p_response);
860 return;
861
862 error:
863 RLOGE("requestSignalStrength must never return an error when radio is on");
864 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
865 at_response_free(p_response);
866 }
867
868 /**
869 * networkModePossible. Decides whether the network mode is appropriate for the
870 * specified modem
871 */
872 static int networkModePossible(ModemInfo *mdm, int nm)
873 {
874 if ((net2modem[nm] & mdm->supportedTechs) == net2modem[nm]) {
875 return 1;
876 }
877 return 0;
878 }
879 static void requestSetPreferredNetworkType( int request, void *data,
880 size_t datalen, RIL_Token t )
881 {
882 ATResponse *p_response = NULL;
883 char *cmd = NULL;
884 int value = *(int *)data;
885 int current, old;
886 int err;
887 int32_t preferred = net2pmask[value];
888
889 RLOGD("requestSetPreferredNetworkType: current: %x. New: %x", PREFERRED_NETWORK(sMdmInfo), preferred);
890 if (!networkModePossible(sMdmInfo, value)) {
891 RIL_onRequestComplete(t, RIL_E_MODE_NOT_SUPPORTED, NULL, 0);
892 return;
893 }
894 if (query_ctec(sMdmInfo, ¤t, NULL) < 0) {
895 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
896 return;
897 }
898 old = PREFERRED_NETWORK(sMdmInfo);
899 RLOGD("old != preferred: %d", old != preferred);
900 if (old != preferred) {
901 asprintf(&cmd, "AT+CTEC=%d,\"%x\"", current, preferred);
902 RLOGD("Sending command: <%s>", cmd);
903 err = at_send_command_singleline(cmd, "+CTEC:", &p_response);
904 free(cmd);
905 if (err || !p_response->success) {
906 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
907 return;
908 }
909 PREFERRED_NETWORK(sMdmInfo) = value;
910 if (!strstr( p_response->p_intermediates->line, "DONE") ) {
911 int current;
912 int res = parse_technology_response(p_response->p_intermediates->line, ¤t, NULL);
913 switch (res) {
914 case -1: // Error or unable to parse
915 break;
916 case 1: // Only able to parse current
917 case 0: // Both current and preferred were parsed
918 setRadioTechnology(sMdmInfo, current);
919 break;
920 }
921 }
922 }
923 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
924 }
925
926 static void requestGetPreferredNetworkType(int request, void *data,
927 size_t datalen, RIL_Token t)
928 {
929 int preferred;
930 unsigned i;
931
932 switch ( query_ctec(sMdmInfo, NULL, &preferred) ) {
933 case -1: // Error or unable to parse
934 case 1: // Only able to parse current
935 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
936 break;
937 case 0: // Both current and preferred were parsed
938 for ( i = 0 ; i < sizeof(net2pmask) / sizeof(int32_t) ; i++ ) {
939 if (preferred == net2pmask[i]) {
940 RIL_onRequestComplete(t, RIL_E_SUCCESS, &i, sizeof(int));
941 return;
942 }
943 }
944 RLOGE("Unknown preferred mode received from modem: %d", preferred);
945 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
946 break;
947 }
948
949 }
950
951 static void requestCdmaPrlVersion(int request, void *data,
952 size_t datalen, RIL_Token t)
953 {
954 int err;
955 char * responseStr;
956 ATResponse *p_response = NULL;
957 const char *cmd;
958 char *line;
959
960 err = at_send_command_singleline("AT+WPRL?", "+WPRL:", &p_response);
961 if (err < 0 || !p_response->success) goto error;
962 line = p_response->p_intermediates->line;
963 err = at_tok_start(&line);
964 if (err < 0) goto error;
965 err = at_tok_nextstr(&line, &responseStr);
966 if (err < 0 || !responseStr) goto error;
967 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, strlen(responseStr));
968 at_response_free(p_response);
969 return;
970 error:
971 at_response_free(p_response);
972 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
973 }
974
975 static void requestCdmaBaseBandVersion(int request, void *data,
976 size_t datalen, RIL_Token t)
977 {
978 int err;
979 char * responseStr;
980 ATResponse *p_response = NULL;
981 const char *cmd;
982 const char *prefix;
983 char *line, *p;
984 int commas;
985 int skip;
986 int count = 4;
987
988 // Fixed values. TODO: query modem
989 responseStr = strdup("1.0.0.0");
990 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, sizeof(responseStr));
991 free(responseStr);
992 }
993
994 static void requestCdmaDeviceIdentity(int request, void *data,
995 size_t datalen, RIL_Token t)
996 {
997 int err;
998 int response[4];
999 char * responseStr[4];
1000 ATResponse *p_response = NULL;
1001 const char *cmd;
1002 const char *prefix;
1003 char *line, *p;
1004 int commas;
1005 int skip;
1006 int count = 4;
1007
1008 // Fixed values. TODO: Query modem
1009 responseStr[0] = "----";
1010 responseStr[1] = "----";
1011 responseStr[2] = "77777777";
1012
1013 err = at_send_command_numeric("AT+CGSN", &p_response);
1014 if (err < 0 || p_response->success == 0) {
1015 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1016 return;
1017 } else {
1018 responseStr[3] = p_response->p_intermediates->line;
1019 }
1020
1021 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
1022 at_response_free(p_response);
1023
1024 return;
1025 error:
1026 RLOGE("requestCdmaDeviceIdentity must never return an error when radio is on");
1027 at_response_free(p_response);
1028 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1029 }
1030
1031 static void requestCdmaGetSubscriptionSource(int request, void *data,
1032 size_t datalen, RIL_Token t)
1033 {
1034 int err;
1035 int *ss = (int *)data;
1036 ATResponse *p_response = NULL;
1037 char *cmd = NULL;
1038 char *line = NULL;
1039 int response;
1040
1041 asprintf(&cmd, "AT+CCSS?");
1042 if (!cmd) goto error;
1043
1044 err = at_send_command_singleline(cmd, "+CCSS:", &p_response);
1045 if (err < 0 || !p_response->success)
1046 goto error;
1047
1048 line = p_response->p_intermediates->line;
1049 err = at_tok_start(&line);
1050 if (err < 0) goto error;
1051
1052 err = at_tok_nextint(&line, &response);
1053 free(cmd);
1054 cmd = NULL;
1055
1056 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
1057
1058 return;
1059 error:
1060 free(cmd);
1061 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1062 }
1063
1064 static void requestCdmaSetSubscriptionSource(int request, void *data,
1065 size_t datalen, RIL_Token t)
1066 {
1067 int err;
1068 int *ss = (int *)data;
1069 ATResponse *p_response = NULL;
1070 char *cmd = NULL;
1071
1072 if (!ss || !datalen) {
1073 RLOGE("RIL_REQUEST_CDMA_SET_SUBSCRIPTION without data!");
1074 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1075 return;
1076 }
1077 asprintf(&cmd, "AT+CCSS=%d", ss[0]);
1078 if (!cmd) goto error;
1079
1080 err = at_send_command(cmd, &p_response);
1081 if (err < 0 || !p_response->success)
1082 goto error;
1083 free(cmd);
1084 cmd = NULL;
1085
1086 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1087
1088 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, ss, sizeof(ss[0]));
1089
1090 return;
1091 error:
1092 free(cmd);
1093 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1094 }
1095
1096 static void requestCdmaSubscription(int request, void *data,
1097 size_t datalen, RIL_Token t)
1098 {
1099 int err;
1100 int response[5];
1101 char * responseStr[5];
1102 ATResponse *p_response = NULL;
1103 const char *cmd;
1104 const char *prefix;
1105 char *line, *p;
1106 int commas;
1107 int skip;
1108 int count = 5;
1109
1110 // Fixed values. TODO: Query modem
1111 responseStr[0] = "8587777777"; // MDN
1112 responseStr[1] = "1"; // SID
1113 responseStr[2] = "1"; // NID
1114 responseStr[3] = "8587777777"; // MIN
1115 responseStr[4] = "1"; // PRL Version
1116 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
1117
1118 return;
1119 error:
1120 RLOGE("requestRegistrationState must never return an error when radio is on");
1121 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1122 }
1123
1124 static void requestCdmaGetRoamingPreference(int request, void *data,
1125 size_t datalen, RIL_Token t)
1126 {
1127 int roaming_pref = -1;
1128 ATResponse *p_response = NULL;
1129 char *line;
1130 int res;
1131
1132 res = at_send_command_singleline("AT+WRMP?", "+WRMP:", &p_response);
1133 if (res < 0 || !p_response->success) {
1134 goto error;
1135 }
1136 line = p_response->p_intermediates->line;
1137
1138 res = at_tok_start(&line);
1139 if (res < 0) goto error;
1140
1141 res = at_tok_nextint(&line, &roaming_pref);
1142 if (res < 0) goto error;
1143
1144 RIL_onRequestComplete(t, RIL_E_SUCCESS, &roaming_pref, sizeof(roaming_pref));
1145 return;
1146 error:
1147 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1148 }
1149
1150 static void requestCdmaSetRoamingPreference(int request, void *data,
1151 size_t datalen, RIL_Token t)
1152 {
1153 int *pref = (int *)data;
1154 ATResponse *p_response = NULL;
1155 char *line;
1156 int res;
1157 char *cmd = NULL;
1158
1159 asprintf(&cmd, "AT+WRMP=%d", *pref);
1160 if (cmd == NULL) goto error;
1161
1162 res = at_send_command(cmd, &p_response);
1163 if (res < 0 || !p_response->success)
1164 goto error;
1165
1166 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1167 free(cmd);
1168 return;
1169 error:
1170 free(cmd);
1171 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1172 }
1173
1174 static int parseRegistrationState(char *str, int *type, int *items, int **response)
1175 {
1176 int err;
1177 char *line = str, *p;
1178 int *resp = NULL;
1179 int skip;
1180 int count = 3;
1181 int commas;
1182
1183 RLOGD("parseRegistrationState. Parsing: %s",str);
1184 err = at_tok_start(&line);
1185 if (err < 0) goto error;
1186
1187 /* Ok you have to be careful here
1188 * The solicited version of the CREG response is
1189 * +CREG: n, stat, [lac, cid]
1190 * and the unsolicited version is
1191 * +CREG: stat, [lac, cid]
1192 * The <n> parameter is basically "is unsolicited creg on?"
1193 * which it should always be
1194 *
1195 * Now we should normally get the solicited version here,
1196 * but the unsolicited version could have snuck in
1197 * so we have to handle both
1198 *
1199 * Also since the LAC and CID are only reported when registered,
1200 * we can have 1, 2, 3, or 4 arguments here
1201 *
1202 * finally, a +CGREG: answer may have a fifth value that corresponds
1203 * to the network type, as in;
1204 *
1205 * +CGREG: n, stat [,lac, cid [,networkType]]
1206 */
1207
1208 /* count number of commas */
1209 commas = 0;
1210 for (p = line ; *p != '\0' ;p++) {
1211 if (*p == ',') commas++;
1212 }
1213
1214 resp = (int *)calloc(commas + 1, sizeof(int));
1215 if (!resp) goto error;
1216 switch (commas) {
1217 case 0: /* +CREG: <stat> */
1218 err = at_tok_nextint(&line, &resp[0]);
1219 if (err < 0) goto error;
1220 resp[1] = -1;
1221 resp[2] = -1;
1222 break;
1223
1224 case 1: /* +CREG: <n>, <stat> */
1225 err = at_tok_nextint(&line, &skip);
1226 if (err < 0) goto error;
1227 err = at_tok_nextint(&line, &resp[0]);
1228 if (err < 0) goto error;
1229 resp[1] = -1;
1230 resp[2] = -1;
1231 if (err < 0) goto error;
1232 break;
1233
1234 case 2: /* +CREG: <stat>, <lac>, <cid> */
1235 err = at_tok_nextint(&line, &resp[0]);
1236 if (err < 0) goto error;
1237 err = at_tok_nexthexint(&line, &resp[1]);
1238 if (err < 0) goto error;
1239 err = at_tok_nexthexint(&line, &resp[2]);
1240 if (err < 0) goto error;
1241 break;
1242 case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
1243 err = at_tok_nextint(&line, &skip);
1244 if (err < 0) goto error;
1245 err = at_tok_nextint(&line, &resp[0]);
1246 if (err < 0) goto error;
1247 err = at_tok_nexthexint(&line, &resp[1]);
1248 if (err < 0) goto error;
1249 err = at_tok_nexthexint(&line, &resp[2]);
1250 if (err < 0) goto error;
1251 break;
1252 /* special case for CGREG, there is a fourth parameter
1253 * that is the network type (unknown/gprs/edge/umts)
1254 */
1255 case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
1256 err = at_tok_nextint(&line, &skip);
1257 if (err < 0) goto error;
1258 err = at_tok_nextint(&line, &resp[0]);
1259 if (err < 0) goto error;
1260 err = at_tok_nexthexint(&line, &resp[1]);
1261 if (err < 0) goto error;
1262 err = at_tok_nexthexint(&line, &resp[2]);
1263 if (err < 0) goto error;
1264 err = at_tok_nexthexint(&line, &resp[3]);
1265 if (err < 0) goto error;
1266 count = 4;
1267 break;
1268 default:
1269 goto error;
1270 }
1271 s_lac = resp[1];
1272 s_cid = resp[2];
1273 if (response)
1274 *response = resp;
1275 if (items)
1276 *items = commas + 1;
1277 if (type)
1278 *type = techFromModemType(TECH(sMdmInfo));
1279 return 0;
1280 error:
1281 free(resp);
1282 return -1;
1283 }
1284
1285 #define REG_STATE_LEN 15
1286 #define REG_DATA_STATE_LEN 6
1287 static void requestRegistrationState(int request, void *data,
1288 size_t datalen, RIL_Token t)
1289 {
1290 int err;
1291 int *registration;
1292 char **responseStr = NULL;
1293 ATResponse *p_response = NULL;
1294 const char *cmd;
1295 const char *prefix;
1296 char *line;
1297 int i = 0, j, numElements = 0;
1298 int count = 3;
1299 int type, startfrom;
1300
1301 RLOGD("requestRegistrationState");
1302 if (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
1303 cmd = "AT+CREG?";
1304 prefix = "+CREG:";
1305 numElements = REG_STATE_LEN;
1306 } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
1307 cmd = "AT+CGREG?";
1308 prefix = "+CGREG:";
1309 numElements = REG_DATA_STATE_LEN;
1310 } else {
1311 assert(0);
1312 goto error;
1313 }
1314
1315 err = at_send_command_singleline(cmd, prefix, &p_response);
1316
1317 if (err != 0) goto error;
1318
1319 line = p_response->p_intermediates->line;
1320
1321 if (parseRegistrationState(line, &type, &count, ®istration)) goto error;
1322
1323 responseStr = malloc(numElements * sizeof(char *));
1324 if (!responseStr) goto error;
1325 memset(responseStr, 0, numElements * sizeof(char *));
1326 /**
1327 * The first '4' bytes for both registration states remain the same.
1328 * But if the request is 'DATA_REGISTRATION_STATE',
1329 * the 5th and 6th byte(s) are optional.
1330 */
1331 if (is3gpp2(type) == 1) {
1332 RLOGD("registration state type: 3GPP2");
1333 // TODO: Query modem
1334 startfrom = 3;
1335 if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
1336 asprintf(&responseStr[3], "8"); // EvDo revA
1337 asprintf(&responseStr[4], "1"); // BSID
1338 asprintf(&responseStr[5], "123"); // Latitude
1339 asprintf(&responseStr[6], "222"); // Longitude
1340 asprintf(&responseStr[7], "0"); // CSS Indicator
1341 asprintf(&responseStr[8], "4"); // SID
1342 asprintf(&responseStr[9], "65535"); // NID
1343 asprintf(&responseStr[10], "0"); // Roaming indicator
1344 asprintf(&responseStr[11], "1"); // System is in PRL
1345 asprintf(&responseStr[12], "0"); // Default Roaming indicator
1346 asprintf(&responseStr[13], "0"); // Reason for denial
1347 asprintf(&responseStr[14], "0"); // Primary Scrambling Code of Current cell
1348 } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
1349 asprintf(&responseStr[3], "8"); // Available data radio technology
1350 }
1351 } else { // type == RADIO_TECH_3GPP
1352 RLOGD("registration state type: 3GPP");
1353 startfrom = 0;
1354 asprintf(&responseStr[1], "%x", registration[1]);
1355 asprintf(&responseStr[2], "%x", registration[2]);
1356 if (count > 3)
1357 asprintf(&responseStr[3], "%d", registration[3]);
1358 }
1359 asprintf(&responseStr[0], "%d", registration[0]);
1360
1361 /**
1362 * Optional bytes for DATA_REGISTRATION_STATE request
1363 * 4th byte : Registration denial code
1364 * 5th byte : The max. number of simultaneous Data Calls
1365 */
1366 if(request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
1367 // asprintf(&responseStr[4], "3");
1368 // asprintf(&responseStr[5], "1");
1369 }
1370
1371 for (j = startfrom; j < numElements; j++) {
1372 if (!responseStr[i]) goto error;
1373 }
1374 free(registration);
1375 registration = NULL;
1376
1377 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, numElements*sizeof(responseStr));
1378 for (j = 0; j < numElements; j++ ) {
1379 free(responseStr[j]);
1380 responseStr[j] = NULL;
1381 }
1382 free(responseStr);
1383 responseStr = NULL;
1384 at_response_free(p_response);
1385
1386 return;
1387 error:
1388 if (responseStr) {
1389 for (j = 0; j < numElements; j++) {
1390 free(responseStr[j]);
1391 responseStr[j] = NULL;
1392 }
1393 free(responseStr);
1394 responseStr = NULL;
1395 }
1396 RLOGE("requestRegistrationState must never return an error when radio is on");
1397 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1398 at_response_free(p_response);
1399 }
1400
1401 static void requestOperator(void *data, size_t datalen, RIL_Token t)
1402 {
1403 int err;
1404 int i;
1405 int skip;
1406 ATLine *p_cur;
1407 char *response[3];
1408
1409 memset(response, 0, sizeof(response));
1410
1411 ATResponse *p_response = NULL;
1412
1413 err = at_send_command_multiline(
1414 "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
1415 "+COPS:", &p_response);
1416
1417 /* we expect 3 lines here:
1418 * +COPS: 0,0,"T - Mobile"
1419 * +COPS: 0,1,"TMO"
1420 * +COPS: 0,2,"310170"
1421 */
1422
1423 if (err != 0) goto error;
1424
1425 for (i = 0, p_cur = p_response->p_intermediates
1426 ; p_cur != NULL
1427 ; p_cur = p_cur->p_next, i++
1428 ) {
1429 char *line = p_cur->line;
1430
1431 err = at_tok_start(&line);
1432 if (err < 0) goto error;
1433
1434 err = at_tok_nextint(&line, &skip);
1435 if (err < 0) goto error;
1436
1437 // If we're unregistered, we may just get
1438 // a "+COPS: 0" response
1439 if (!at_tok_hasmore(&line)) {
1440 response[i] = NULL;
1441 continue;
1442 }
1443
1444 err = at_tok_nextint(&line, &skip);
1445 if (err < 0) goto error;
1446
1447 // a "+COPS: 0, n" response is also possible
1448 if (!at_tok_hasmore(&line)) {
1449 response[i] = NULL;
1450 continue;
1451 }
1452
1453 err = at_tok_nextstr(&line, &(response[i]));
1454 if (err < 0) goto error;
1455 // Simple assumption that mcc and mnc are 3 digits each
1456 if (strlen(response[i]) == 6) {
1457 if (sscanf(response[i], "%3d%3d", &s_mcc, &s_mnc) != 2) {
1458 RLOGE("requestOperator expected mccmnc to be 6 decimal digits");
1459 }
1460 }
1461 }
1462
1463 if (i != 3) {
1464 /* expect 3 lines exactly */
1465 goto error;
1466 }
1467
1468 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1469 at_response_free(p_response);
1470
1471 return;
1472 error:
1473 RLOGE("requestOperator must not return error when radio is on");
1474 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1475 at_response_free(p_response);
1476 }
1477
1478 static void requestCdmaSendSMS(void *data, size_t datalen, RIL_Token t)
1479 {
1480 int err = 1; // Set to go to error:
1481 RIL_SMS_Response response;
1482 RIL_CDMA_SMS_Message* rcsm;
1483
1484 RLOGD("requestCdmaSendSMS datalen=%d, sizeof(RIL_CDMA_SMS_Message)=%d",
1485 datalen, sizeof(RIL_CDMA_SMS_Message));
1486
1487 // verify data content to test marshalling/unmarshalling:
1488 rcsm = (RIL_CDMA_SMS_Message*)data;
1489 RLOGD("TeleserviceID=%d, bIsServicePresent=%d, \
1490 uServicecategory=%d, sAddress.digit_mode=%d, \
1491 sAddress.Number_mode=%d, sAddress.number_type=%d, ",
1492 rcsm->uTeleserviceID, rcsm->bIsServicePresent,
1493 rcsm->uServicecategory,rcsm->sAddress.digit_mode,
1494 rcsm->sAddress.number_mode,rcsm->sAddress.number_type);
1495
1496 if (err != 0) goto error;
1497
1498 // Cdma Send SMS implementation will go here:
1499 // But it is not implemented yet.
1500
1501 memset(&response, 0, sizeof(response));
1502 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
1503 return;
1504
1505 error:
1506 // Cdma Send SMS will always cause send retry error.
1507 RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, NULL, 0);
1508 }
1509
1510 static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
1511 {
1512 int err;
1513 const char *smsc;
1514 const char *pdu;
1515 int tpLayerLength;
1516 char *cmd1, *cmd2;
1517 RIL_SMS_Response response;
1518 ATResponse *p_response = NULL;
1519
1520 smsc = ((const char **)data)[0];
1521 pdu = ((const char **)data)[1];
1522
1523 tpLayerLength = strlen(pdu)/2;
1524
1525 // "NULL for default SMSC"
1526 if (smsc == NULL) {
1527 smsc= "00";
1528 }
1529
1530 asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
1531 asprintf(&cmd2, "%s%s", smsc, pdu);
1532
1533 err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
1534
1535 if (err != 0 || p_response->success == 0) goto error;
1536
1537 memset(&response, 0, sizeof(response));
1538
1539 /* FIXME fill in messageRef and ackPDU */
1540
1541 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
1542 at_response_free(p_response);
1543
1544 return;
1545 error:
1546 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1547 at_response_free(p_response);
1548 }
1549
1550 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
1551 {
1552 const char *apn;
1553 char *cmd;
1554 int err;
1555 ATResponse *p_response = NULL;
1556
1557 apn = ((const char **)data)[2];
1558
1559 #ifdef USE_TI_COMMANDS
1560 // Config for multislot class 10 (probably default anyway eh?)
1561 err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
1562 NULL);
1563
1564 err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
1565 #endif /* USE_TI_COMMANDS */
1566
1567 int fd, qmistatus;
1568 size_t cur = 0;
1569 size_t len;
1570 ssize_t written, rlen;
1571 char status[32] = {0};
1572 int retry = 10;
1573 const char *pdp_type;
1574
1575 RLOGD("requesting data connection to APN '%s'", apn);
1576
1577 fd = open ("/dev/qmi", O_RDWR);
1578 if (fd >= 0) { /* the device doesn't exist on the emulator */
1579
1580 RLOGD("opened the qmi device\n");
1581 asprintf(&cmd, "up:%s", apn);
1582 len = strlen(cmd);
1583
1584 while (cur < len) {
1585 do {
1586 written = write (fd, cmd + cur, len - cur);
1587 } while (written < 0 && errno == EINTR);
1588
1589 if (written < 0) {
1590 RLOGE("### ERROR writing to /dev/qmi");
1591 close(fd);
1592 goto error;
1593 }
1594
1595 cur += written;
1596 }
1597
1598 // wait for interface to come online
1599
1600 do {
1601 sleep(1);
1602 do {
1603 rlen = read(fd, status, 31);
1604 } while (rlen < 0 && errno == EINTR);
1605
1606 if (rlen < 0) {
1607 RLOGE("### ERROR reading from /dev/qmi");
1608 close(fd);
1609 goto error;
1610 } else {
1611 status[rlen] = '\0';
1612 RLOGD("### status: %s", status);
1613 }
1614 } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
1615
1616 close(fd);
1617
1618 if (retry == 0) {
1619 RLOGE("### Failed to get data connection up\n");
1620 goto error;
1621 }
1622
1623 qmistatus = system("netcfg rmnet0 dhcp");
1624
1625 RLOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus);
1626
1627 if (qmistatus < 0) goto error;
1628
1629 } else {
1630
1631 if (datalen > 6 * sizeof(char *)) {
1632 pdp_type = ((const char **)data)[6];
1633 } else {
1634 pdp_type = "IP";
1635 }
1636
1637 asprintf(&cmd, "AT+CGDCONT=1,\"%s\",\"%s\",,0,0", pdp_type, apn);
1638 //FIXME check for error here
1639 err = at_send_command(cmd, NULL);
1640 free(cmd);
1641
1642 // Set required QoS params to default
1643 err = at_send_command("AT+CGQREQ=1", NULL);
1644
1645 // Set minimum QoS params to default
1646 err = at_send_command("AT+CGQMIN=1", NULL);
1647
1648 // packet-domain event reporting
1649 err = at_send_command("AT+CGEREP=1,0", NULL);
1650
1651 // Hangup anything that's happening there now
1652 err = at_send_command("AT+CGACT=1,0", NULL);
1653
1654 // Start data on PDP context 1
1655 err = at_send_command("ATD*99***1#", &p_response);
1656
1657 if (err < 0 || p_response->success == 0) {
1658 goto error;
1659 }
1660 }
1661
1662 requestOrSendDataCallList(&t);
1663
1664 at_response_free(p_response);
1665
1666 return;
1667 error:
1668 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1669 at_response_free(p_response);
1670
1671 }
1672
1673 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
1674 {
1675 int ackSuccess;
1676 int err;
1677
1678 ackSuccess = ((int *)data)[0];
1679
1680 if (ackSuccess == 1) {
1681 err = at_send_command("AT+CNMA=1", NULL);
1682 } else if (ackSuccess == 0) {
1683 err = at_send_command("AT+CNMA=2", NULL);
1684 } else {
1685 RLOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
1686 goto error;
1687 }
1688
1689 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1690 error:
1691 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1692
1693 }
1694
1695 static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
1696 {
1697 ATResponse *p_response = NULL;
1698 RIL_SIM_IO_Response sr;
1699 int err;
1700 char *cmd = NULL;
1701 RIL_SIM_IO_v6 *p_args;
1702 char *line;
1703
1704 memset(&sr, 0, sizeof(sr));
1705
1706 p_args = (RIL_SIM_IO_v6 *)data;
1707
1708 /* FIXME handle pin2 */
1709
1710 if (p_args->data == NULL) {
1711 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
1712 p_args->command, p_args->fileid,
1713 p_args->p1, p_args->p2, p_args->p3);
1714 } else {
1715 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
1716 p_args->command, p_args->fileid,
1717 p_args->p1, p_args->p2, p_args->p3, p_args->data);
1718 }
1719
1720 err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
1721
1722 if (err < 0 || p_response->success == 0) {
1723 goto error;
1724 }
1725
1726 line = p_response->p_intermediates->line;
1727
1728 err = at_tok_start(&line);
1729 if (err < 0) goto error;
1730
1731 err = at_tok_nextint(&line, &(sr.sw1));
1732 if (err < 0) goto error;
1733
1734 err = at_tok_nextint(&line, &(sr.sw2));
1735 if (err < 0) goto error;
1736
1737 if (at_tok_hasmore(&line)) {
1738 err = at_tok_nextstr(&line, &(sr.simResponse));
1739 if (err < 0) goto error;
1740 }
1741
1742 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
1743 at_response_free(p_response);
1744 free(cmd);
1745
1746 return;
1747 error:
1748 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1749 at_response_free(p_response);
1750 free(cmd);
1751
1752 }
1753
1754 static void requestEnterSimPin(void* data, size_t datalen, RIL_Token t)
1755 {
1756 ATResponse *p_response = NULL;
1757 int err;
1758 char* cmd = NULL;
1759 const char** strings = (const char**)data;;
1760
1761 if ( datalen == sizeof(char*) ) {
1762 asprintf(&cmd, "AT+CPIN=%s", strings[0]);
1763 } else if ( datalen == 2*sizeof(char*) ) {
1764 asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
1765 } else
1766 goto error;
1767
1768 err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
1769 free(cmd);
1770
1771 if (err < 0 || p_response->success == 0) {
1772 error:
1773 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
1774 } else {
1775 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1776 }
1777 at_response_free(p_response);
1778 }
1779
1780
1781 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
1782 {
1783 const char *ussdRequest;
1784
1785 ussdRequest = (char *)(data);
1786
1787
1788 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1789
1790 // @@@ TODO
1791
1792 }
1793
1794 static void requestExitEmergencyMode(void *data, size_t datalen, RIL_Token t)
1795 {
1796 int err;
1797 ATResponse *p_response = NULL;
1798
1799 err = at_send_command("AT+WSOS=0", &p_response);
1800
1801 if (err < 0 || p_response->success == 0) {
1802 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1803 return;
1804 }
1805
1806 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1807 }
1808
1809 // TODO: Use all radio types
1810 static int techFromModemType(int mdmtype)
1811 {
1812 int ret = -1;
1813 switch (1 << mdmtype) {
1814 case MDM_CDMA:
1815 ret = RADIO_TECH_1xRTT;
1816 break;
1817 case MDM_EVDO:
1818 ret = RADIO_TECH_EVDO_A;
1819 break;
1820 case MDM_GSM:
1821 ret = RADIO_TECH_GPRS;
1822 break;
1823 case MDM_WCDMA:
1824 ret = RADIO_TECH_HSPA;
1825 break;
1826 case MDM_LTE:
1827 ret = RADIO_TECH_LTE;
1828 break;
1829 }
1830 return ret;
1831 }
1832
1833 static void requestGetCellInfoList(void *data, size_t datalen, RIL_Token t)
1834 {
1835 uint64_t curTime = ril_nano_time();
1836 RIL_CellInfo ci[1] =
1837 {
1838 { // ci[0]
1839 1, // cellInfoType
1840 1, // registered
1841 curTime - 1000, // Fake some time in the past
1842 { // union CellInfo
1843 { // RIL_CellInfoGsm gsm
1844 { // gsm.cellIdneityGsm
1845 s_mcc, // mcc
1846 s_mnc, // mnc
1847 s_lac, // lac
1848 s_cid, // cid
1849 0 // psc
1850 },
1851 { // gsm.signalStrengthGsm
1852 10, // signalStrength
1853 0 // bitErrorRate
1854 }
1855 }
1856 }
1857 }
1858 };
1859
1860 RIL_onRequestComplete(t, RIL_E_SUCCESS, ci, sizeof(ci));
1861 }
1862
1863
1864 static void requestSetCellInfoListRate(void *data, size_t datalen, RIL_Token t)
1865 {
1866 // For now we'll save the rate but no RIL_UNSOL_CELL_INFO_LIST messages
1867 // will be sent.
1868 assert (datalen == sizeof(int));
1869 s_cell_info_rate_ms = ((int *)data)[0];
1870
1871 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1872 }
1873
1874 /*** Callback methods from the RIL library to us ***/
1875
1876 /**
1877 * Call from RIL to us to make a RIL_REQUEST
1878 *
1879 * Must be completed with a call to RIL_onRequestComplete()
1880 *
1881 * RIL_onRequestComplete() may be called from any thread, before or after
1882 * this function returns.
1883 *
1884 * Will always be called from the same thread, so returning here implies
1885 * that the radio is ready to process another command (whether or not
1886 * the previous command has completed).
1887 */
1888 static void
1889 onRequest (int request, void *data, size_t datalen, RIL_Token t)
1890 {
1891 ATResponse *p_response;
1892 int err;
1893
1894 RLOGD("onRequest: %s", requestToString(request));
1895
1896 /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
1897 * when RADIO_STATE_UNAVAILABLE.
1898 */
1899 if (sState == RADIO_STATE_UNAVAILABLE
1900 && request != RIL_REQUEST_GET_SIM_STATUS
1901 ) {
1902 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1903 return;
1904 }
1905
1906 /* Ignore all non-power requests when RADIO_STATE_OFF
1907 * (except RIL_REQUEST_GET_SIM_STATUS)
1908 */
1909 if (sState == RADIO_STATE_OFF
1910 && !(request == RIL_REQUEST_RADIO_POWER
1911 || request == RIL_REQUEST_GET_SIM_STATUS)
1912 ) {
1913 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1914 return;
1915 }
1916
1917 switch (request) {
1918 case RIL_REQUEST_GET_SIM_STATUS: {
1919 RIL_CardStatus_v6 *p_card_status;
1920 char *p_buffer;
1921 int buffer_size;
1922
1923 int result = getCardStatus(&p_card_status);
1924 if (result == RIL_E_SUCCESS) {
1925 p_buffer = (char *)p_card_status;
1926 buffer_size = sizeof(*p_card_status);
1927 } else {
1928 p_buffer = NULL;
1929 buffer_size = 0;
1930 }
1931 RIL_onRequestComplete(t, result, p_buffer, buffer_size);
1932 freeCardStatus(p_card_status);
1933 break;
1934 }
1935 case RIL_REQUEST_GET_CURRENT_CALLS:
1936 requestGetCurrentCalls(data, datalen, t);
1937 break;
1938 case RIL_REQUEST_DIAL:
1939 requestDial(data, datalen, t);
1940 break;
1941 case RIL_REQUEST_HANGUP:
1942 requestHangup(data, datalen, t);
1943 break;
1944 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
1945 // 3GPP 22.030 6.5.5
1946 // "Releases all held calls or sets User Determined User Busy
1947 // (UDUB) for a waiting call."
1948 at_send_command("AT+CHLD=0", NULL);
1949
1950 /* success or failure is ignored by the upper layer here.
1951 it will call GET_CURRENT_CALLS and determine success that way */
1952 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1953 break;
1954 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
1955 // 3GPP 22.030 6.5.5
1956 // "Releases all active calls (if any exist) and accepts
1957 // the other (held or waiting) call."
1958 at_send_command("AT+CHLD=1", NULL);
1959
1960 /* success or failure is ignored by the upper layer here.
1961 it will call GET_CURRENT_CALLS and determine success that way */
1962 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1963 break;
1964 case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
1965 // 3GPP 22.030 6.5.5
1966 // "Places all active calls (if any exist) on hold and accepts
1967 // the other (held or waiting) call."
1968 at_send_command("AT+CHLD=2", NULL);
1969
1970 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1971 s_expectAnswer = 1;
1972 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
1973
1974 /* success or failure is ignored by the upper layer here.
1975 it will call GET_CURRENT_CALLS and determine success that way */
1976 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1977 break;
1978 case RIL_REQUEST_ANSWER:
1979 at_send_command("ATA", NULL);
1980
1981 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1982 s_expectAnswer = 1;
1983 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
1984
1985 /* success or failure is ignored by the upper layer here.
1986 it will call GET_CURRENT_CALLS and determine success that way */
1987 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1988 break;
1989 case RIL_REQUEST_CONFERENCE:
1990 // 3GPP 22.030 6.5.5
1991 // "Adds a held call to the conversation"
1992 at_send_command("AT+CHLD=3", NULL);
1993
1994 /* success or failure is ignored by the upper layer here.
1995 it will call GET_CURRENT_CALLS and determine success that way */
1996 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1997 break;
1998 case RIL_REQUEST_UDUB:
1999 /* user determined user busy */
2000 /* sometimes used: ATH */
2001 at_send_command("ATH", NULL);
2002
2003 /* success or failure is ignored by the upper layer here.
2004 it will call GET_CURRENT_CALLS and determine success that way */
2005 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2006 break;
2007
2008 case RIL_REQUEST_SEPARATE_CONNECTION:
2009 {
2010 char cmd[12];
2011 int party = ((int*)data)[0];
2012
2013 // Make sure that party is in a valid range.
2014 // (Note: The Telephony middle layer imposes a range of 1 to 7.
2015 // It's sufficient for us to just make sure it's single digit.)
2016 if (party > 0 && party < 10) {
2017 sprintf(cmd, "AT+CHLD=2%d", party);
2018 at_send_command(cmd, NULL);
2019 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2020 } else {
2021 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2022 }
2023 }
2024 break;
2025
2026 case RIL_REQUEST_SIGNAL_STRENGTH:
2027 requestSignalStrength(data, datalen, t);
2028 break;
2029 case RIL_REQUEST_VOICE_REGISTRATION_STATE:
2030 case RIL_REQUEST_DATA_REGISTRATION_STATE:
2031 requestRegistrationState(request, data, datalen, t);
2032 break;
2033 case RIL_REQUEST_OPERATOR:
2034 requestOperator(data, datalen, t);
2035 break;
2036 case RIL_REQUEST_RADIO_POWER:
2037 requestRadioPower(data, datalen, t);
2038 break;
2039 case RIL_REQUEST_DTMF: {
2040 char c = ((char *)data)[0];
2041 char *cmd;
2042 asprintf(&cmd, "AT+VTS=%c", (int)c);
2043 at_send_command(cmd, NULL);
2044 free(cmd);
2045 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2046 break;
2047 }
2048 case RIL_REQUEST_SEND_SMS:
2049 requestSendSMS(data, datalen, t);
2050 break;
2051 case RIL_REQUEST_CDMA_SEND_SMS:
2052 requestCdmaSendSMS(data, datalen, t);
2053 break;
2054 case RIL_REQUEST_SETUP_DATA_CALL:
2055 requestSetupDataCall(data, datalen, t);
2056 break;
2057 case RIL_REQUEST_SMS_ACKNOWLEDGE:
2058 requestSMSAcknowledge(data, datalen, t);
2059 break;
2060
2061 case RIL_REQUEST_GET_IMSI:
2062 p_response = NULL;
2063 err = at_send_command_numeric("AT+CIMI", &p_response);
2064
2065 if (err < 0 || p_response->success == 0) {
2066 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2067 } else {
2068 RIL_onRequestComplete(t, RIL_E_SUCCESS,
2069 p_response->p_intermediates->line, sizeof(char *));
2070 }
2071 at_response_free(p_response);
2072 break;
2073
2074 case RIL_REQUEST_GET_IMEI:
2075 p_response = NULL;
2076 err = at_send_command_numeric("AT+CGSN", &p_response);
2077
2078 if (err < 0 || p_response->success == 0) {
2079 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2080 } else {
2081 RIL_onRequestComplete(t, RIL_E_SUCCESS,
2082 p_response->p_intermediates->line, sizeof(char *));
2083 }
2084 at_response_free(p_response);
2085 break;
2086
2087 case RIL_REQUEST_SIM_IO:
2088 requestSIM_IO(data,datalen,t);
2089 break;
2090
2091 case RIL_REQUEST_SEND_USSD:
2092 requestSendUSSD(data, datalen, t);
2093 break;
2094
2095 case RIL_REQUEST_CANCEL_USSD:
2096 p_response = NULL;
2097 err = at_send_command_numeric("AT+CUSD=2", &p_response);
2098
2099 if (err < 0 || p_response->success == 0) {
2100 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2101 } else {
2102 RIL_onRequestComplete(t, RIL_E_SUCCESS,
2103 p_response->p_intermediates->line, sizeof(char *));
2104 }
2105 at_response_free(p_response);
2106 break;
2107
2108 case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
2109 at_send_command("AT+COPS=0", NULL);
2110 break;
2111
2112 case RIL_REQUEST_DATA_CALL_LIST:
2113 requestDataCallList(data, datalen, t);
2114 break;
2115
2116 case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
2117 requestQueryNetworkSelectionMode(data, datalen, t);
2118 break;
2119
2120 case RIL_REQUEST_OEM_HOOK_RAW:
2121 // echo back data
2122 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
2123 break;
2124
2125
2126 case RIL_REQUEST_OEM_HOOK_STRINGS: {
2127 int i;
2128 const char ** cur;
2129
2130 RLOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
2131
2132
2133 for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
2134 i > 0 ; cur++, i --) {
2135 RLOGD("> '%s'", *cur);
2136 }
2137
2138 // echo back strings
2139 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
2140 break;
2141 }
2142
2143 case RIL_REQUEST_WRITE_SMS_TO_SIM:
2144 requestWriteSmsToSim(data, datalen, t);
2145 break;
2146
2147 case RIL_REQUEST_DELETE_SMS_ON_SIM: {
2148 char * cmd;
2149 p_response = NULL;
2150 asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
2151 err = at_send_command(cmd, &p_response);
2152 free(cmd);
2153 if (err < 0 || p_response->success == 0) {
2154 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2155 } else {
2156 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2157 }
2158 at_response_free(p_response);
2159 break;
2160 }
2161
2162 case RIL_REQUEST_ENTER_SIM_PIN:
2163 case RIL_REQUEST_ENTER_SIM_PUK:
2164 case RIL_REQUEST_ENTER_SIM_PIN2:
2165 case RIL_REQUEST_ENTER_SIM_PUK2:
2166 case RIL_REQUEST_CHANGE_SIM_PIN:
2167 case RIL_REQUEST_CHANGE_SIM_PIN2:
2168 requestEnterSimPin(data, datalen, t);
2169 break;
2170
2171 case RIL_REQUEST_VOICE_RADIO_TECH:
2172 {
2173 int tech = techFromModemType(TECH(sMdmInfo));
2174 if (tech < 0 )
2175 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2176 else
2177 RIL_onRequestComplete(t, RIL_E_SUCCESS, &tech, sizeof(tech));
2178 }
2179 break;
2180 case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
2181 requestSetPreferredNetworkType(request, data, datalen, t);
2182 break;
2183
2184 case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
2185 requestGetPreferredNetworkType(request, data, datalen, t);
2186 break;
2187
2188 /* CDMA Specific Requests */
2189 case RIL_REQUEST_BASEBAND_VERSION:
2190 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2191 requestCdmaBaseBandVersion(request, data, datalen, t);
2192 break;
2193 } // Fall-through if tech is not cdma
2194
2195 case RIL_REQUEST_DEVICE_IDENTITY:
2196 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2197 requestCdmaDeviceIdentity(request, data, datalen, t);
2198 break;
2199 } // Fall-through if tech is not cdma
2200
2201 case RIL_REQUEST_CDMA_SUBSCRIPTION:
2202 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2203 requestCdmaSubscription(request, data, datalen, t);
2204 break;
2205 } // Fall-through if tech is not cdma
2206
2207 case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
2208 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2209 requestCdmaSetSubscriptionSource(request, data, datalen, t);
2210 break;
2211 } // Fall-through if tech is not cdma
2212
2213 case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
2214 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2215 requestCdmaGetSubscriptionSource(request, data, datalen, t);
2216 break;
2217 } // Fall-through if tech is not cdma
2218
2219 case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:
2220 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2221 requestCdmaGetRoamingPreference(request, data, datalen, t);
2222 break;
2223 } // Fall-through if tech is not cdma
2224
2225 case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
2226 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2227 requestCdmaSetRoamingPreference(request, data, datalen, t);
2228 break;
2229 } // Fall-through if tech is not cdma
2230
2231 case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
2232 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
2233 requestExitEmergencyMode(data, datalen, t);
2234 break;
2235 } // Fall-through if tech is not cdma
2236
2237 case RIL_REQUEST_GET_CELL_INFO_LIST:
2238 requestGetCellInfoList(data, datalen, t);
2239 break;
2240
2241 case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
2242 requestSetCellInfoListRate(data, datalen, t);
2243 break;
2244
2245 default:
2246 RLOGD("Request not supported. Tech: %d",TECH(sMdmInfo));
2247 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
2248 break;
2249 }
2250 }
2251
2252 /**
2253 * Synchronous call from the RIL to us to return current radio state.
2254 * RADIO_STATE_UNAVAILABLE should be the initial state.
2255 */
2256 static RIL_RadioState
2257 currentState()
2258 {
2259 return sState;
2260 }
2261 /**
2262 * Call from RIL to us to find out whether a specific request code
2263 * is supported by this implementation.
2264 *
2265 * Return 1 for "supported" and 0 for "unsupported"
2266 */
2267
2268 static int
2269 onSupports (int requestCode)
2270 {
2271 //@@@ todo
2272
2273 return 1;
2274 }
2275
2276 static void onCancel (RIL_Token t)
2277 {
2278 //@@@todo
2279
2280 }
2281
2282 static const char * getVersion(void)
2283 {
2284 return "android reference-ril 1.0";
2285 }
2286
2287 static void
2288 setRadioTechnology(ModemInfo *mdm, int newtech)
2289 {
2290 RLOGD("setRadioTechnology(%d)", newtech);
2291
2292 int oldtech = TECH(mdm);
2293
2294 if (newtech != oldtech) {
2295 RLOGD("Tech change (%d => %d)", oldtech, newtech);
2296 TECH(mdm) = newtech;
2297 if (techFromModemType(newtech) != techFromModemType(oldtech)) {
2298 int tech = techFromModemType(TECH(sMdmInfo));
2299 if (tech > 0 ) {
2300 RIL_onUnsolicitedResponse(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED,
2301 &tech, sizeof(tech));
2302 }
2303 }
2304 }
2305 }
2306
2307 static void
2308 setRadioState(RIL_RadioState newState)
2309 {
2310 RLOGD("setRadioState(%d)", newState);
2311 RIL_RadioState oldState;
2312
2313 pthread_mutex_lock(&s_state_mutex);
2314
2315 oldState = sState;
2316
2317 if (s_closed > 0) {
2318 // If we're closed, the only reasonable state is
2319 // RADIO_STATE_UNAVAILABLE
2320 // This is here because things on the main thread
2321 // may attempt to change the radio state after the closed
2322 // event happened in another thread
2323 newState = RADIO_STATE_UNAVAILABLE;
2324 }
2325
2326 if (sState != newState || s_closed > 0) {
2327 sState = newState;
2328
2329 pthread_cond_broadcast (&s_state_cond);
2330 }
2331
2332 pthread_mutex_unlock(&s_state_mutex);
2333
2334
2335 /* do these outside of the mutex */
2336 if (sState != oldState) {
2337 RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
2338 NULL, 0);
2339
2340 /* FIXME onSimReady() and onRadioPowerOn() cannot be called
2341 * from the AT reader thread
2342 * Currently, this doesn't happen, but if that changes then these
2343 * will need to be dispatched on the request thread
2344 */
2345 if (sState == RADIO_STATE_ON) {
2346 onRadioPowerOn();
2347 }
2348 }
2349 }
2350
2351 /** Returns RUIM_NOT_READY on error */
2352 static SIM_Status
2353 getRUIMStatus()
2354 {
2355 ATResponse *p_response = NULL;
2356 int err;
2357 int ret;
2358 char *cpinLine;
2359 char *cpinResult;
2360
2361 if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
2362 ret = SIM_NOT_READY;
2363 goto done;
2364 }
2365
2366 err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
2367
2368 if (err != 0) {
2369 ret = SIM_NOT_READY;
2370 goto done;
2371 }
2372
2373 switch (at_get_cme_error(p_response)) {
2374 case CME_SUCCESS:
2375 break;
2376
2377 case CME_SIM_NOT_INSERTED:
2378 ret = SIM_ABSENT;
2379 goto done;
2380
2381 default:
2382 ret = SIM_NOT_READY;
2383 goto done;
2384 }
2385
2386 /* CPIN? has succeeded, now look at the result */
2387
2388 cpinLine = p_response->p_intermediates->line;
2389 err = at_tok_start (&cpinLine);
2390
2391 if (err < 0) {
2392 ret = SIM_NOT_READY;
2393 goto done;
2394 }
2395
2396 err = at_tok_nextstr(&cpinLine, &cpinResult);
2397
2398 if (err < 0) {
2399 ret = SIM_NOT_READY;
2400 goto done;
2401 }
2402
2403 if (0 == strcmp (cpinResult, "SIM PIN")) {
2404 ret = SIM_PIN;
2405 goto done;
2406 } else if (0 == strcmp (cpinResult, "SIM PUK")) {
2407 ret = SIM_PUK;
2408 goto done;
2409 } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
2410 return SIM_NETWORK_PERSONALIZATION;
2411 } else if (0 != strcmp (cpinResult, "READY")) {
2412 /* we're treating unsupported lock types as "sim absent" */
2413 ret = SIM_ABSENT;
2414 goto done;
2415 }
2416
2417 at_response_free(p_response);
2418 p_response = NULL;
2419 cpinResult = NULL;
2420
2421 ret = SIM_READY;
2422
2423 done:
2424 at_response_free(p_response);
2425 return ret;
2426 }
2427
2428 /** Returns SIM_NOT_READY on error */
2429 static SIM_Status
2430 getSIMStatus()
2431 {
2432 ATResponse *p_response = NULL;
2433 int err;
2434 int ret;
2435 char *cpinLine;
2436 char *cpinResult;
2437
2438 RLOGD("getSIMStatus(). sState: %d",sState);
2439 if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
2440 ret = SIM_NOT_READY;
2441 goto done;
2442 }
2443
2444 err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
2445
2446 if (err != 0) {
2447 ret = SIM_NOT_READY;
2448 goto done;
2449 }
2450
2451 switch (at_get_cme_error(p_response)) {
2452 case CME_SUCCESS:
2453 break;
2454
2455 case CME_SIM_NOT_INSERTED:
2456 ret = SIM_ABSENT;
2457 goto done;
2458
2459 default:
2460 ret = SIM_NOT_READY;
2461 goto done;
2462 }
2463
2464 /* CPIN? has succeeded, now look at the result */
2465
2466 cpinLine = p_response->p_intermediates->line;
2467 err = at_tok_start (&cpinLine);
2468
2469 if (err < 0) {
2470 ret = SIM_NOT_READY;
2471 goto done;
2472 }
2473
2474 err = at_tok_nextstr(&cpinLine, &cpinResult);
2475
2476 if (err < 0) {
2477 ret = SIM_NOT_READY;
2478 goto done;
2479 }
2480
2481 if (0 == strcmp (cpinResult, "SIM PIN")) {
2482 ret = SIM_PIN;
2483 goto done;
2484 } else if (0 == strcmp (cpinResult, "SIM PUK")) {
2485 ret = SIM_PUK;
2486 goto done;
2487 } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
2488 return SIM_NETWORK_PERSONALIZATION;
2489 } else if (0 != strcmp (cpinResult, "READY")) {
2490 /* we're treating unsupported lock types as "sim absent" */
2491 ret = SIM_ABSENT;
2492 goto done;
2493 }
2494
2495 at_response_free(p_response);
2496 p_response = NULL;
2497 cpinResult = NULL;
2498
2499 ret = SIM_READY;
2500
2501 done:
2502 at_response_free(p_response);
2503 return ret;
2504 }
2505
2506
2507 /**
2508 * Get the current card status.
2509 *
2510 * This must be freed using freeCardStatus.
2511 * @return: On success returns RIL_E_SUCCESS
2512 */
2513 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status) {
2514 static RIL_AppStatus app_status_array[] = {
2515 // SIM_ABSENT = 0
2516 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
2517 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
2518 // SIM_NOT_READY = 1
2519 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
2520 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
2521 // SIM_READY = 2
2522 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
2523 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
2524 // SIM_PIN = 3
2525 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
2526 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
2527 // SIM_PUK = 4
2528 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
2529 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
2530 // SIM_NETWORK_PERSONALIZATION = 5
2531 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
2532 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
2533 // RUIM_ABSENT = 6
2534 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
2535 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
2536 // RUIM_NOT_READY = 7
2537 { RIL_APPTYPE_RUIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
2538 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
2539 // RUIM_READY = 8
2540 { RIL_APPTYPE_RUIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
2541 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
2542 // RUIM_PIN = 9
2543 { RIL_APPTYPE_RUIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
2544 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
2545 // RUIM_PUK = 10
2546 { RIL_APPTYPE_RUIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
2547 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
2548 // RUIM_NETWORK_PERSONALIZATION = 11
2549 { RIL_APPTYPE_RUIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
2550 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }
2551 };
2552 RIL_CardState card_state;
2553 int num_apps;
2554
2555 int sim_status = getSIMStatus();
2556 if (sim_status == SIM_ABSENT) {
2557 card_state = RIL_CARDSTATE_ABSENT;
2558 num_apps = 0;
2559 } else {
2560 card_state = RIL_CARDSTATE_PRESENT;
2561 num_apps = 2;
2562 }
2563
2564 // Allocate and initialize base card status.
2565 RIL_CardStatus_v6 *p_card_status = malloc(sizeof(RIL_CardStatus_v6));
2566 p_card_status->card_state = card_state;
2567 p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
2568 p_card_status->gsm_umts_subscription_app_index = RIL_CARD_MAX_APPS;
2569 p_card_status->cdma_subscription_app_index = RIL_CARD_MAX_APPS;
2570 p_card_status->ims_subscription_app_index = RIL_CARD_MAX_APPS;
2571 p_card_status->num_applications = num_apps;
2572
2573 // Initialize application status
2574 int i;
2575 for (i = 0; i < RIL_CARD_MAX_APPS; i++) {
2576 p_card_status->applications[i] = app_status_array[SIM_ABSENT];
2577 }
2578
2579 // Pickup the appropriate application status
2580 // that reflects sim_status for gsm.
2581 if (num_apps != 0) {
2582 // Only support one app, gsm
2583 p_card_status->num_applications = 2;
2584 p_card_status->gsm_umts_subscription_app_index = 0;
2585 p_card_status->cdma_subscription_app_index = 1;
2586
2587 // Get the correct app status
2588 p_card_status->applications[0] = app_status_array[sim_status];
2589 p_card_status->applications[1] = app_status_array[sim_status + RUIM_ABSENT];
2590 }
2591
2592 *pp_card_status = p_card_status;
2593 return RIL_E_SUCCESS;
2594 }
2595
2596 /**
2597 * Free the card status returned by getCardStatus
2598 */
2599 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status) {
2600 free(p_card_status);
2601 }
2602
2603 /**
2604 * SIM ready means any commands that access the SIM will work, including:
2605 * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
2606 * (all SMS-related commands)
2607 */
2608
2609 static void pollSIMState (void *param)
2610 {
2611 ATResponse *p_response;
2612 int ret;
2613
2614 if (sState != RADIO_STATE_SIM_NOT_READY) {
2615 // no longer valid to poll
2616 return;
2617 }
2618
2619 switch(getSIMStatus()) {
2620 case SIM_ABSENT:
2621 case SIM_PIN:
2622 case SIM_PUK:
2623 case SIM_NETWORK_PERSONALIZATION:
2624 default:
2625 RLOGI("SIM ABSENT or LOCKED");
2626 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
2627 return;
2628
2629 case SIM_NOT_READY:
2630 RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
2631 return;
2632
2633 case SIM_READY:
2634 RLOGI("SIM_READY");
2635 onSIMReady();
2636 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
2637 return;
2638 }
2639 }
2640
2641 /** returns 1 if on, 0 if off, and -1 on error */
2642 static int isRadioOn()
2643 {
2644 ATResponse *p_response = NULL;
2645 int err;
2646 char *line;
2647 char ret;
2648
2649 err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
2650
2651 if (err < 0 || p_response->success == 0) {
2652 // assume radio is off
2653 goto error;
2654 }
2655
2656 line = p_response->p_intermediates->line;
2657
2658 err = at_tok_start(&line);
2659 if (err < 0) goto error;
2660
2661 err = at_tok_nextbool(&line, &ret);
2662 if (err < 0) goto error;
2663
2664 at_response_free(p_response);
2665
2666 return (int)ret;
2667
2668 error:
2669
2670 at_response_free(p_response);
2671 return -1;
2672 }
2673
2674 /**
2675 * Parse the response generated by a +CTEC AT command
2676 * The values read from the response are stored in current and preferred.
2677 * Both current and preferred may be null. The corresponding value is ignored in that case.
2678 *
2679 * @return: -1 if some error occurs (or if the modem doesn't understand the +CTEC command)
2680 * 1 if the response includes the current technology only
2681 * 0 if the response includes both current technology and preferred mode
2682 */
2683 int parse_technology_response( const char *response, int *current, int32_t *preferred )
2684 {
2685 int err;
2686 char *line, *p;
2687 int ct;
2688 int32_t pt = 0;
2689 char *str_pt;
2690
2691 line = p = strdup(response);
2692 RLOGD("Response: %s", line);
2693 err = at_tok_start(&p);
2694 if (err || !at_tok_hasmore(&p)) {
2695 RLOGD("err: %d. p: %s", err, p);
2696 free(line);
2697 return -1;
2698 }
2699
2700 err = at_tok_nextint(&p, &ct);
2701 if (err) {
2702 free(line);
2703 return -1;
2704 }
2705 if (current) *current = ct;
2706
2707 RLOGD("line remaining after int: %s", p);
2708
2709 err = at_tok_nexthexint(&p, &pt);
2710 if (err) {
2711 free(line);
2712 return 1;
2713 }
2714 if (preferred) {
2715 *preferred = pt;
2716 }
2717 free(line);
2718
2719 return 0;
2720 }
2721
2722 int query_supported_techs( ModemInfo *mdm, int *supported )
2723 {
2724 ATResponse *p_response;
2725 int err, val, techs = 0;
2726 char *tok;
2727 char *line;
2728
2729 RLOGD("query_supported_techs");
2730 err = at_send_command_singleline("AT+CTEC=?", "+CTEC:", &p_response);
2731 if (err || !p_response->success)
2732 goto error;
2733 line = p_response->p_intermediates->line;
2734 err = at_tok_start(&line);
2735 if (err || !at_tok_hasmore(&line))
2736 goto error;
2737 while (!at_tok_nextint(&line, &val)) {
2738 techs |= ( 1 << val );
2739 }
2740 if (supported) *supported = techs;
2741 return 0;
2742 error:
2743 at_response_free(p_response);
2744 return -1;
2745 }
2746
2747 /**
2748 * query_ctec. Send the +CTEC AT command to the modem to query the current
2749 * and preferred modes. It leaves values in the addresses pointed to by
2750 * current and preferred. If any of those pointers are NULL, the corresponding value
2751 * is ignored, but the return value will still reflect if retreiving and parsing of the
2752 * values suceeded.
2753 *
2754 * @mdm Currently unused
2755 * @current A pointer to store the current mode returned by the modem. May be null.
2756 * @preferred A pointer to store the preferred mode returned by the modem. May be null.
2757 * @return -1 on error (or failure to parse)
2758 * 1 if only the current mode was returned by modem (or failed to parse preferred)
2759 * 0 if both current and preferred were returned correctly
2760 */
2761 int query_ctec(ModemInfo *mdm, int *current, int32_t *preferred)
2762 {
2763 ATResponse *response = NULL;
2764 int err;
2765 int res;
2766
2767 RLOGD("query_ctec. current: %d, preferred: %d", (int)current, (int) preferred);
2768 err = at_send_command_singleline("AT+CTEC?", "+CTEC:", &response);
2769 if (!err && response->success) {
2770 res = parse_technology_response(response->p_intermediates->line, current, preferred);
2771 at_response_free(response);
2772 return res;
2773 }
2774 RLOGE("Error executing command: %d. response: %x. status: %d", err, (int)response, response? response->success : -1);
2775 at_response_free(response);
2776 return -1;
2777 }
2778
2779 int is_multimode_modem(ModemInfo *mdm)
2780 {
2781 ATResponse *response;
2782 int err;
2783 char *line;
2784 int tech;
2785 int32_t preferred;
2786
2787 if (query_ctec(mdm, &tech, &preferred) == 0) {
2788 mdm->currentTech = tech;
2789 mdm->preferredNetworkMode = preferred;
2790 if (query_supported_techs(mdm, &mdm->supportedTechs)) {
2791 return 0;
2792 }
2793 return 1;
2794 }
2795 return 0;
2796 }
2797
2798 /**
2799 * Find out if our modem is GSM, CDMA or both (Multimode)
2800 */
2801 static void probeForModemMode(ModemInfo *info)
2802 {
2803 ATResponse *response;
2804 int err;
2805 assert (info);
2806 // Currently, our only known multimode modem is qemu's android modem,
2807 // which implements the AT+CTEC command to query and set mode.
2808 // Try that first
2809
2810 if (is_multimode_modem(info)) {
2811 RLOGI("Found Multimode Modem. Supported techs mask: %8.8x. Current tech: %d",
2812 info->supportedTechs, info->currentTech);
2813 return;
2814 }
2815
2816 /* Being here means that our modem is not multimode */
2817 info->isMultimode = 0;
2818
2819 /* CDMA Modems implement the AT+WNAM command */
2820 err = at_send_command_singleline("AT+WNAM","+WNAM:", &response);
2821 if (!err && response->success) {
2822 at_response_free(response);
2823 // TODO: find out if we really support EvDo
2824 info->supportedTechs = MDM_CDMA | MDM_EVDO;
2825 info->currentTech = MDM_CDMA;
2826 RLOGI("Found CDMA Modem");
2827 return;
2828 }
2829 if (!err) at_response_free(response);
2830 // TODO: find out if modem really supports WCDMA/LTE
2831 info->supportedTechs = MDM_GSM | MDM_WCDMA | MDM_LTE;
2832 info->currentTech = MDM_GSM;
2833 RLOGI("Found GSM Modem");
2834 }
2835
2836 /**
2837 * Initialize everything that can be configured while we're still in
2838 * AT+CFUN=0
2839 */
2840 static void initializeCallback(void *param)
2841 {
2842 ATResponse *p_response = NULL;
2843 int err;
2844
2845 setRadioState (RADIO_STATE_OFF);
2846
2847 at_handshake();
2848
2849 probeForModemMode(sMdmInfo);
2850 /* note: we don't check errors here. Everything important will
2851 be handled in onATTimeout and onATReaderClosed */
2852
2853 /* atchannel is tolerant of echo but it must */
2854 /* have verbose result codes */
2855 at_send_command("ATE0Q0V1", NULL);
2856
2857 /* No auto-answer */
2858 at_send_command("ATS0=0", NULL);
2859
2860 /* Extended errors */
2861 at_send_command("AT+CMEE=1", NULL);
2862
2863 /* Network registration events */
2864 err = at_send_command("AT+CREG=2", &p_response);
2865
2866 /* some handsets -- in tethered mode -- don't support CREG=2 */
2867 if (err < 0 || p_response->success == 0) {
2868 at_send_command("AT+CREG=1", NULL);
2869 }
2870
2871 at_response_free(p_response);
2872
2873 /* GPRS registration events */
2874 at_send_command("AT+CGREG=1", NULL);
2875
2876 /* Call Waiting notifications */
2877 at_send_command("AT+CCWA=1", NULL);
2878
2879 /* Alternating voice/data off */
2880 at_send_command("AT+CMOD=0", NULL);
2881
2882 /* Not muted */
2883 at_send_command("AT+CMUT=0", NULL);
2884
2885 /* +CSSU unsolicited supp service notifications */
2886 at_send_command("AT+CSSN=0,1", NULL);
2887
2888 /* no connected line identification */
2889 at_send_command("AT+COLP=0", NULL);
2890
2891 /* HEX character set */
2892 at_send_command("AT+CSCS=\"HEX\"", NULL);
2893
2894 /* USSD unsolicited */
2895 at_send_command("AT+CUSD=1", NULL);
2896
2897 /* Enable +CGEV GPRS event notifications, but don't buffer */
2898 at_send_command("AT+CGEREP=1,0", NULL);
2899
2900 /* SMS PDU mode */
2901 at_send_command("AT+CMGF=0", NULL);
2902
2903 #ifdef USE_TI_COMMANDS
2904
2905 at_send_command("AT%CPI=3", NULL);
2906
2907 /* TI specific -- notifications when SMS is ready (currently ignored) */
2908 at_send_command("AT%CSTAT=1", NULL);
2909
2910 #endif /* USE_TI_COMMANDS */
2911
2912
2913 /* assume radio is off on error */
2914 if (isRadioOn() > 0) {
2915 setRadioState (RADIO_STATE_ON);
2916 }
2917 }
2918
2919 static void waitForClose()
2920 {
2921 pthread_mutex_lock(&s_state_mutex);
2922
2923 while (s_closed == 0) {
2924 pthread_cond_wait(&s_state_cond, &s_state_mutex);
2925 }
2926
2927 pthread_mutex_unlock(&s_state_mutex);
2928 }
2929
2930 /**
2931 * Called by atchannel when an unsolicited line appears
2932 * This is called on atchannel's reader thread. AT commands may
2933 * not be issued here
2934 */
2935 static void onUnsolicited (const char *s, const char *sms_pdu)
2936 {
2937 char *line = NULL, *p;
2938 int err;
2939
2940 /* Ignore unsolicited responses until we're initialized.
2941 * This is OK because the RIL library will poll for initial state
2942 */
2943 if (sState == RADIO_STATE_UNAVAILABLE) {
2944 return;
2945 }
2946
2947 if (strStartsWith(s, "%CTZV:")) {
2948 /* TI specific -- NITZ time */
2949 char *response;
2950
2951 line = p = strdup(s);
2952 at_tok_start(&p);
2953
2954 err = at_tok_nextstr(&p, &response);
2955
2956 free(line);
2957 if (err != 0) {
2958 RLOGE("invalid NITZ line %s\n", s);
2959 } else {
2960 RIL_onUnsolicitedResponse (
2961 RIL_UNSOL_NITZ_TIME_RECEIVED,
2962 response, strlen(response));
2963 }
2964 } else if (strStartsWith(s,"+CRING:")
2965 || strStartsWith(s,"RING")
2966 || strStartsWith(s,"NO CARRIER")
2967 || strStartsWith(s,"+CCWA")
2968 ) {
2969 RIL_onUnsolicitedResponse (
2970 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
2971 NULL, 0);
2972 #ifdef WORKAROUND_FAKE_CGEV
2973 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
2974 #endif /* WORKAROUND_FAKE_CGEV */
2975 } else if (strStartsWith(s,"+CREG:")
2976 || strStartsWith(s,"+CGREG:")
2977 ) {
2978 RIL_onUnsolicitedResponse (
2979 RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
2980 NULL, 0);
2981 #ifdef WORKAROUND_FAKE_CGEV
2982 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
2983 #endif /* WORKAROUND_FAKE_CGEV */
2984 } else if (strStartsWith(s, "+CMT:")) {
2985 RIL_onUnsolicitedResponse (
2986 RIL_UNSOL_RESPONSE_NEW_SMS,
2987 sms_pdu, strlen(sms_pdu));
2988 } else if (strStartsWith(s, "+CDS:")) {
2989 RIL_onUnsolicitedResponse (
2990 RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
2991 sms_pdu, strlen(sms_pdu));
2992 } else if (strStartsWith(s, "+CGEV:")) {
2993 /* Really, we can ignore NW CLASS and ME CLASS events here,
2994 * but right now we don't since extranous
2995 * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
2996 */
2997 /* can't issue AT commands here -- call on main thread */
2998 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
2999 #ifdef WORKAROUND_FAKE_CGEV
3000 } else if (strStartsWith(s, "+CME ERROR: 150")) {
3001 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
3002 #endif /* WORKAROUND_FAKE_CGEV */
3003 } else if (strStartsWith(s, "+CTEC: ")) {
3004 int tech, mask;
3005 switch (parse_technology_response(s, &tech, NULL))
3006 {
3007 case -1: // no argument could be parsed.
3008 RLOGE("invalid CTEC line %s\n", s);
3009 break;
3010 case 1: // current mode correctly parsed
3011 case 0: // preferred mode correctly parsed
3012 mask = 1 << tech;
3013 if (mask != MDM_GSM && mask != MDM_CDMA &&
3014 mask != MDM_WCDMA && mask != MDM_LTE) {
3015 RLOGE("Unknown technology %d\n", tech);
3016 } else {
3017 setRadioTechnology(sMdmInfo, tech);
3018 }
3019 break;
3020 }
3021 } else if (strStartsWith(s, "+CCSS: ")) {
3022 int source = 0;
3023 line = p = strdup(s);
3024 if (!line) {
3025 RLOGE("+CCSS: Unable to allocate memory");
3026 return;
3027 }
3028 if (at_tok_start(&p) < 0) {
3029 free(line);
3030 return;
3031 }
3032 if (at_tok_nextint(&p, &source) < 0) {
3033 RLOGE("invalid +CCSS response: %s", line);
3034 free(line);
3035 return;
3036 }
3037 SSOURCE(sMdmInfo) = source;
3038 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED,
3039 &source, sizeof(source));
3040 } else if (strStartsWith(s, "+WSOS: ")) {
3041 char state = 0;
3042 int unsol;
3043 line = p = strdup(s);
3044 if (!line) {
3045 RLOGE("+WSOS: Unable to allocate memory");
3046 return;
3047 }
3048 if (at_tok_start(&p) < 0) {
3049 free(line);
3050 return;
3051 }
3052 if (at_tok_nextbool(&p, &state) < 0) {
3053 RLOGE("invalid +WSOS response: %s", line);
3054 free(line);
3055 return;
3056 }
3057 free(line);
3058
3059 unsol = state ?
3060 RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE : RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE;
3061
3062 RIL_onUnsolicitedResponse(unsol, NULL, 0);
3063
3064 } else if (strStartsWith(s, "+WPRL: ")) {
3065 int version = -1;
3066 line = p = strdup(s);
3067 if (!line) {
3068 RLOGE("+WPRL: Unable to allocate memory");
3069 return;
3070 }
3071 if (at_tok_start(&p) < 0) {
3072 RLOGE("invalid +WPRL response: %s", s);
3073 free(line);
3074 return;
3075 }
3076 if (at_tok_nextint(&p, &version) < 0) {
3077 RLOGE("invalid +WPRL response: %s", s);
3078 free(line);
3079 return;
3080 }
3081 free(line);
3082 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_PRL_CHANGED, &version, sizeof(version));
3083 } else if (strStartsWith(s, "+CFUN: 0")) {
3084 setRadioState(RADIO_STATE_OFF);
3085 }
3086 }
3087
3088 /* Called on command or reader thread */
3089 static void onATReaderClosed()
3090 {
3091 RLOGI("AT channel closed\n");
3092 at_close();
3093 s_closed = 1;
3094
3095 setRadioState (RADIO_STATE_UNAVAILABLE);
3096 }
3097
3098 /* Called on command thread */
3099 static void onATTimeout()
3100 {
3101 RLOGI("AT channel timeout; closing\n");
3102 at_close();
3103
3104 s_closed = 1;
3105
3106 /* FIXME cause a radio reset here */
3107
3108 setRadioState (RADIO_STATE_UNAVAILABLE);
3109 }
3110
3111 static void usage(char *s)
3112 {
3113 #ifdef RIL_SHLIB
3114 fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
3115 #else
3116 fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
3117 exit(-1);
3118 #endif
3119 }
3120
3121 static void *
3122 mainLoop(void *param)
3123 {
3124 int fd;
3125 int ret;
3126
3127 AT_DUMP("== ", "entering mainLoop()", -1 );
3128 at_set_on_reader_closed(onATReaderClosed);
3129 at_set_on_timeout(onATTimeout);
3130
3131 for (;;) {
3132 fd = -1;
3133 while (fd < 0) {
3134 if (s_port > 0) {
3135 fd = socket_loopback_client(s_port, SOCK_STREAM);
3136 } else if (s_device_socket) {
3137 if (!strcmp(s_device_path, "/dev/socket/qemud")) {
3138 /* Before trying to connect to /dev/socket/qemud (which is
3139 * now another "legacy" way of communicating with the
3140 * emulator), we will try to connecto to gsm service via
3141 * qemu pipe. */
3142 fd = qemu_pipe_open("qemud:gsm");
3143 if (fd < 0) {
3144 /* Qemu-specific control socket */
3145 fd = socket_local_client( "qemud",
3146 ANDROID_SOCKET_NAMESPACE_RESERVED,
3147 SOCK_STREAM );
3148 if (fd >= 0 ) {
3149 char answer[2];
3150
3151 if ( write(fd, "gsm", 3) != 3 ||
3152 read(fd, answer, 2) != 2 ||
3153 memcmp(answer, "OK", 2) != 0)
3154 {
3155 close(fd);
3156 fd = -1;
3157 }
3158 }
3159 }
3160 }
3161 else
3162 fd = socket_local_client( s_device_path,
3163 ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
3164 SOCK_STREAM );
3165 } else if (s_device_path != NULL) {
3166 fd = open (s_device_path, O_RDWR);
3167 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
3168 /* disable echo on serial ports */
3169 struct termios ios;
3170 tcgetattr( fd, &ios );
3171 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
3172 tcsetattr( fd, TCSANOW, &ios );
3173 }
3174 }
3175
3176 if (fd < 0) {
3177 perror ("opening AT interface. retrying...");
3178 sleep(10);
3179 /* never returns */
3180 }
3181 }
3182
3183 s_closed = 0;
3184 ret = at_open(fd, onUnsolicited);
3185
3186 if (ret < 0) {
3187 RLOGE ("AT error %d on at_open\n", ret);
3188 return 0;
3189 }
3190
3191 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
3192
3193 // Give initializeCallback a chance to dispatched, since
3194 // we don't presently have a cancellation mechanism
3195 sleep(1);
3196
3197 waitForClose();
3198 RLOGI("Re-opening after close");
3199 }
3200 }
3201
3202 #ifdef RIL_SHLIB
3203
3204 pthread_t s_tid_mainloop;
3205
3206 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
3207 {
3208 int ret;
3209 int fd = -1;
3210 int opt;
3211 pthread_attr_t attr;
3212
3213 s_rilenv = env;
3214
3215 while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
3216 switch (opt) {
3217 case 'p':
3218 s_port = atoi(optarg);
3219 if (s_port == 0) {
3220 usage(argv[0]);
3221 return NULL;
3222 }
3223 RLOGI("Opening loopback port %d\n", s_port);
3224 break;
3225
3226 case 'd':
3227 s_device_path = optarg;
3228 RLOGI("Opening tty device %s\n", s_device_path);
3229 break;
3230
3231 case 's':
3232 s_device_path = optarg;
3233 s_device_socket = 1;
3234 RLOGI("Opening socket %s\n", s_device_path);
3235 break;
3236
3237 default:
3238 usage(argv[0]);
3239 return NULL;
3240 }
3241 }
3242
3243 if (s_port < 0 && s_device_path == NULL) {
3244 usage(argv[0]);
3245 return NULL;
3246 }
3247
3248 sMdmInfo = calloc(1, sizeof(ModemInfo));
3249 if (!sMdmInfo) {
3250 RLOGE("Unable to alloc memory for ModemInfo");
3251 return NULL;
3252 }
3253 pthread_attr_init (&attr);
3254 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3255 ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
3256
3257 return &s_callbacks;
3258 }
3259 #else /* RIL_SHLIB */
3260 int main (int argc, char **argv)
3261 {
3262 int ret;
3263 int fd = -1;
3264 int opt;
3265
3266 while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
3267 switch (opt) {
3268 case 'p':
3269 s_port = atoi(optarg);
3270 if (s_port == 0) {
3271 usage(argv[0]);
3272 }
3273 RLOGI("Opening loopback port %d\n", s_port);
3274 break;
3275
3276 case 'd':
3277 s_device_path = optarg;
3278 RLOGI("Opening tty device %s\n", s_device_path);
3279 break;
3280
3281 case 's':
3282 s_device_path = optarg;
3283 s_device_socket = 1;
3284 RLOGI("Opening socket %s\n", s_device_path);
3285 break;
3286
3287 default:
3288 usage(argv[0]);
3289 }
3290 }
3291
3292 if (s_port < 0 && s_device_path == NULL) {
3293 usage(argv[0]);
3294 }
3295
3296 RIL_register(&s_callbacks);
3297
3298 mainLoop(NULL);
3299
3300 return 0;
3301 }
3302
3303 #endif /* RIL_SHLIB */
3304