OSDN Git Service

am 4a24d11: Partially fix 1820187 by using RIL_CallOld since we\'re not
[android-x86/hardware-ril.git] / reference-ril / reference-ril.c
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.h>
19 #include <stdio.h>
20 #include <assert.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <pthread.h>
28 #include <alloca.h>
29 #include "atchannel.h"
30 #include "at_tok.h"
31 #include "misc.h"
32 #include <getopt.h>
33 #include <sys/socket.h>
34 #include <cutils/sockets.h>
35 #include <termios.h>
36
37 #define LOG_TAG "RIL"
38 #include <utils/Log.h>
39
40 #define MAX_AT_RESPONSE 0x1000
41
42 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
43 #define PPP_TTY_PATH "/dev/omap_csmi_tty1"
44
45 #ifdef USE_TI_COMMANDS
46
47 // Enable a workaround
48 // 1) Make incoming call, do not answer
49 // 2) Hangup remote end
50 // Expected: call should disappear from CLCC line
51 // Actual: Call shows as "ACTIVE" before disappearing
52 #define WORKAROUND_ERRONEOUS_ANSWER 1
53
54 // Some varients of the TI stack do not support the +CGEV unsolicited
55 // response. However, they seem to send an unsolicited +CME ERROR: 150
56 #define WORKAROUND_FAKE_CGEV 1
57 #endif
58
59 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
60 static RIL_RadioState currentState();
61 static int onSupports (int requestCode);
62 static void onCancel (RIL_Token t);
63 static const char *getVersion();
64 static int isRadioOn();
65 static int getSIMStatus();
66 static void onDataCallListChanged(void *param);
67
68 extern const char * requestToString(int request);
69
70 /*** Static Variables ***/
71 static const RIL_RadioFunctions s_callbacks = {
72     RIL_VERSION,
73     onRequest,
74     currentState,
75     onSupports,
76     onCancel,
77     getVersion
78 };
79
80 #ifdef RIL_SHLIB
81 static const struct RIL_Env *s_rilenv;
82
83 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
84 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
85 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
86 #endif
87
88 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
89
90 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
91 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
92
93 static int s_port = -1;
94 static const char * s_device_path = NULL;
95 static int          s_device_socket = 0;
96
97 /* trigger change to this with s_state_cond */
98 static int s_closed = 0;
99
100 static int sFD;     /* file desc of AT channel */
101 static char sATBuffer[MAX_AT_RESPONSE+1];
102 static char *sATBufferCur = NULL;
103
104 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
105 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
106 static const struct timeval TIMEVAL_0 = {0,0};
107
108 #ifdef WORKAROUND_ERRONEOUS_ANSWER
109 // Max number of times we'll try to repoll when we think
110 // we have a AT+CLCC race condition
111 #define REPOLL_CALLS_COUNT_MAX 4
112
113 // Line index that was incoming or waiting at last poll, or -1 for none
114 static int s_incomingOrWaitingLine = -1;
115 // Number of times we've asked for a repoll of AT+CLCC
116 static int s_repollCallsCount = 0;
117 // Should we expect a call to be answered in the next CLCC?
118 static int s_expectAnswer = 0;
119 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
120
121 static void pollSIMState (void *param);
122 static void setRadioState(RIL_RadioState newState);
123
124 static int clccStateToRILState(int state, RIL_CallState *p_state)
125
126 {
127     switch(state) {
128         case 0: *p_state = RIL_CALL_ACTIVE;   return 0;
129         case 1: *p_state = RIL_CALL_HOLDING;  return 0;
130         case 2: *p_state = RIL_CALL_DIALING;  return 0;
131         case 3: *p_state = RIL_CALL_ALERTING; return 0;
132         case 4: *p_state = RIL_CALL_INCOMING; return 0;
133         case 5: *p_state = RIL_CALL_WAITING;  return 0;
134         default: return -1;
135     }
136 }
137
138 /**
139  * Note: directly modified line and has *p_call point directly into
140  * modified line
141  */
142 static int callFromCLCCLine(char *line, RIL_CallOld *p_call)
143 {
144         //+CLCC: 1,0,2,0,0,\"+18005551212\",145
145         //     index,isMT,state,mode,isMpty(,number,TOA)?
146
147     int err;
148     int state;
149     int mode;
150
151     err = at_tok_start(&line);
152     if (err < 0) goto error;
153
154     err = at_tok_nextint(&line, &(p_call->index));
155     if (err < 0) goto error;
156
157     err = at_tok_nextbool(&line, &(p_call->isMT));
158     if (err < 0) goto error;
159
160     err = at_tok_nextint(&line, &state);
161     if (err < 0) goto error;
162
163     err = clccStateToRILState(state, &(p_call->state));
164     if (err < 0) goto error;
165
166     err = at_tok_nextint(&line, &mode);
167     if (err < 0) goto error;
168
169     p_call->isVoice = (mode == 0);
170
171     err = at_tok_nextbool(&line, &(p_call->isMpty));
172     if (err < 0) goto error;
173
174     if (at_tok_hasmore(&line)) {
175         err = at_tok_nextstr(&line, &(p_call->number));
176
177         /* tolerate null here */
178         if (err < 0) return 0;
179
180         // Some lame implementations return strings
181         // like "NOT AVAILABLE" in the CLCC line
182         if (p_call->number != NULL
183             && 0 == strspn(p_call->number, "+0123456789")
184         ) {
185             p_call->number = NULL;
186         }
187
188         err = at_tok_nextint(&line, &p_call->toa);
189         if (err < 0) goto error;
190     }
191
192     return 0;
193
194 error:
195     LOGE("invalid CLCC line\n");
196     return -1;
197 }
198
199
200 /** do post-AT+CFUN=1 initialization */
201 static void onRadioPowerOn()
202 {
203 #ifdef USE_TI_COMMANDS
204     /*  Must be after CFUN=1 */
205     /*  TI specific -- notifications for CPHS things such */
206     /*  as CPHS message waiting indicator */
207
208     at_send_command("AT%CPHS=1", NULL);
209
210     /*  TI specific -- enable NITZ unsol notifs */
211     at_send_command("AT%CTZV=1", NULL);
212 #endif
213
214     pollSIMState(NULL);
215 }
216
217 /** do post- SIM ready initialization */
218 static void onSIMReady()
219 {
220     at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
221     /*
222      * Always send SMS messages directly to the TE
223      *
224      * mode = 1 // discard when link is reserved (link should never be
225      *             reserved)
226      * mt = 2   // most messages routed to TE
227      * bm = 2   // new cell BM's routed to TE
228      * ds = 1   // Status reports routed to TE
229      * bfr = 1  // flush buffer
230      */
231     at_send_command("AT+CNMI=1,2,2,1,1", NULL);
232 }
233
234 static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
235 {
236     int onOff;
237
238     int err;
239     ATResponse *p_response = NULL;
240
241     assert (datalen >= sizeof(int *));
242     onOff = ((int *)data)[0];
243
244     if (onOff == 0 && sState != RADIO_STATE_OFF) {
245         err = at_send_command("AT+CFUN=0", &p_response);
246        if (err < 0 || p_response->success == 0) goto error;
247         setRadioState(RADIO_STATE_OFF);
248     } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
249         err = at_send_command("AT+CFUN=1", &p_response);
250         if (err < 0|| p_response->success == 0) {
251             // Some stacks return an error when there is no SIM,
252             // but they really turn the RF portion on
253             // So, if we get an error, let's check to see if it
254             // turned on anyway
255
256             if (isRadioOn() != 1) {
257                 goto error;
258             }
259         }
260         setRadioState(RADIO_STATE_SIM_NOT_READY);
261     }
262
263     at_response_free(p_response);
264     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
265     return;
266 error:
267     at_response_free(p_response);
268     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
269 }
270
271 static void requestOrSendDataCallList(RIL_Token *t);
272
273 static void onDataCallListChanged(void *param)
274 {
275     requestOrSendDataCallList(NULL);
276 }
277
278 static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
279 {
280     requestOrSendDataCallList(&t);
281 }
282
283 static void requestOrSendDataCallList(RIL_Token *t)
284 {
285     ATResponse *p_response;
286     ATLine *p_cur;
287     int err;
288     int n = 0;
289     char *out;
290
291     err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
292     if (err != 0 || p_response->success == 0) {
293         if (t != NULL)
294             RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
295         else
296             RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
297                                       NULL, 0);
298         return;
299     }
300
301     for (p_cur = p_response->p_intermediates; p_cur != NULL;
302          p_cur = p_cur->p_next)
303         n++;
304
305     RIL_Data_Call_Response *responses =
306         alloca(n * sizeof(RIL_Data_Call_Response));
307
308     int i;
309     for (i = 0; i < n; i++) {
310         responses[i].cid = -1;
311         responses[i].active = -1;
312         responses[i].type = "";
313         responses[i].apn = "";
314         responses[i].address = "";
315     }
316
317     RIL_Data_Call_Response *response = responses;
318     for (p_cur = p_response->p_intermediates; p_cur != NULL;
319          p_cur = p_cur->p_next) {
320         char *line = p_cur->line;
321
322         err = at_tok_start(&line);
323         if (err < 0)
324             goto error;
325
326         err = at_tok_nextint(&line, &response->cid);
327         if (err < 0)
328             goto error;
329
330         err = at_tok_nextint(&line, &response->active);
331         if (err < 0)
332             goto error;
333
334         response++;
335     }
336
337     at_response_free(p_response);
338
339     err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
340     if (err != 0 || p_response->success == 0) {
341         if (t != NULL)
342             RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
343         else
344             RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
345                                       NULL, 0);
346         return;
347     }
348
349     for (p_cur = p_response->p_intermediates; p_cur != NULL;
350          p_cur = p_cur->p_next) {
351         char *line = p_cur->line;
352         int cid;
353         char *type;
354         char *apn;
355         char *address;
356
357
358         err = at_tok_start(&line);
359         if (err < 0)
360             goto error;
361
362         err = at_tok_nextint(&line, &cid);
363         if (err < 0)
364             goto error;
365
366         for (i = 0; i < n; i++) {
367             if (responses[i].cid == cid)
368                 break;
369         }
370
371         if (i >= n) {
372             /* details for a context we didn't hear about in the last request */
373             continue;
374         }
375
376         err = at_tok_nextstr(&line, &out);
377         if (err < 0)
378             goto error;
379
380         responses[i].type = alloca(strlen(out) + 1);
381         strcpy(responses[i].type, out);
382
383         err = at_tok_nextstr(&line, &out);
384         if (err < 0)
385             goto error;
386
387         responses[i].apn = alloca(strlen(out) + 1);
388         strcpy(responses[i].apn, out);
389
390         err = at_tok_nextstr(&line, &out);
391         if (err < 0)
392             goto error;
393
394         responses[i].address = alloca(strlen(out) + 1);
395         strcpy(responses[i].address, out);
396     }
397
398     at_response_free(p_response);
399
400     if (t != NULL)
401         RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
402                               n * sizeof(RIL_Data_Call_Response));
403     else
404         RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
405                                   responses,
406                                   n * sizeof(RIL_Data_Call_Response));
407
408     return;
409
410 error:
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
417     at_response_free(p_response);
418 }
419
420 static void requestQueryNetworkSelectionMode(
421                 void *data, size_t datalen, RIL_Token t)
422 {
423     int err;
424     ATResponse *p_response = NULL;
425     int response = 0;
426     char *line;
427
428     err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
429
430     if (err < 0 || p_response->success == 0) {
431         goto error;
432     }
433
434     line = p_response->p_intermediates->line;
435
436     err = at_tok_start(&line);
437
438     if (err < 0) {
439         goto error;
440     }
441
442     err = at_tok_nextint(&line, &response);
443
444     if (err < 0) {
445         goto error;
446     }
447
448     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
449     at_response_free(p_response);
450     return;
451 error:
452     at_response_free(p_response);
453     LOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
454     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
455 }
456
457 static void sendCallStateChanged(void *param)
458 {
459     RIL_onUnsolicitedResponse (
460         RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
461         NULL, 0);
462 }
463
464 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
465 {
466     int err;
467     ATResponse *p_response;
468     ATLine *p_cur;
469     int countCalls;
470     int countValidCalls;
471     RIL_CallOld *p_calls;
472     RIL_CallOld **pp_calls;
473     int i;
474     int needRepoll = 0;
475
476 #ifdef WORKAROUND_ERRONEOUS_ANSWER
477     int prevIncomingOrWaitingLine;
478
479     prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
480     s_incomingOrWaitingLine = -1;
481 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
482
483     err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
484
485     if (err != 0 || p_response->success == 0) {
486         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
487         return;
488     }
489
490     /* count the calls */
491     for (countCalls = 0, p_cur = p_response->p_intermediates
492             ; p_cur != NULL
493             ; p_cur = p_cur->p_next
494     ) {
495         countCalls++;
496     }
497
498     /* yes, there's an array of pointers and then an array of structures */
499
500     pp_calls = (RIL_CallOld **)alloca(countCalls * sizeof(RIL_CallOld *));
501     p_calls = (RIL_CallOld *)alloca(countCalls * sizeof(RIL_CallOld));
502     memset (p_calls, 0, countCalls * sizeof(RIL_CallOld));
503
504     /* init the pointer array */
505     for(i = 0; i < countCalls ; i++) {
506         pp_calls[i] = &(p_calls[i]);
507     }
508
509     for (countValidCalls = 0, p_cur = p_response->p_intermediates
510             ; p_cur != NULL
511             ; p_cur = p_cur->p_next
512     ) {
513         err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
514
515         if (err != 0) {
516             continue;
517         }
518
519 #ifdef WORKAROUND_ERRONEOUS_ANSWER
520         if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
521             || p_calls[countValidCalls].state == RIL_CALL_WAITING
522         ) {
523             s_incomingOrWaitingLine = p_calls[countValidCalls].index;
524         }
525 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
526
527         if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
528             && p_calls[countValidCalls].state != RIL_CALL_HOLDING
529         ) {
530             needRepoll = 1;
531         }
532
533         countValidCalls++;
534     }
535
536 #ifdef WORKAROUND_ERRONEOUS_ANSWER
537     // Basically:
538     // A call was incoming or waiting
539     // Now it's marked as active
540     // But we never answered it
541     //
542     // This is probably a bug, and the call will probably
543     // disappear from the call list in the next poll
544     if (prevIncomingOrWaitingLine >= 0
545             && s_incomingOrWaitingLine < 0
546             && s_expectAnswer == 0
547     ) {
548         for (i = 0; i < countValidCalls ; i++) {
549
550             if (p_calls[i].index == prevIncomingOrWaitingLine
551                     && p_calls[i].state == RIL_CALL_ACTIVE
552                     && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
553             ) {
554                 LOGI(
555                     "Hit WORKAROUND_ERRONOUS_ANSWER case."
556                     " Repoll count: %d\n", s_repollCallsCount);
557                 s_repollCallsCount++;
558                 goto error;
559             }
560         }
561     }
562
563     s_expectAnswer = 0;
564     s_repollCallsCount = 0;
565 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
566
567     RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
568             countValidCalls * sizeof (RIL_CallOld *));
569
570     at_response_free(p_response);
571
572 #ifdef POLL_CALL_STATE
573     if (countValidCalls) {  // We don't seem to get a "NO CARRIER" message from
574                             // smd, so we're forced to poll until the call ends.
575 #else
576     if (needRepoll) {
577 #endif
578         RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
579     }
580
581     return;
582 error:
583     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
584     at_response_free(p_response);
585 }
586
587 static void requestDial(void *data, size_t datalen, RIL_Token t)
588 {
589     RIL_Dial *p_dial;
590     char *cmd;
591     const char *clir;
592     int ret;
593
594     p_dial = (RIL_Dial *)data;
595
596     switch (p_dial->clir) {
597         case 1: clir = "I"; break;  /*invocation*/
598         case 2: clir = "i"; break;  /*suppression*/
599         default:
600         case 0: clir = ""; break;   /*subscription default*/
601     }
602
603     asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
604
605     ret = at_send_command(cmd, NULL);
606
607     free(cmd);
608
609     /* success or failure is ignored by the upper layer here.
610        it will call GET_CURRENT_CALLS and determine success that way */
611     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
612 }
613
614 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
615 {
616     RIL_SMS_WriteArgs *p_args;
617     char *cmd;
618     int length;
619     int err;
620     ATResponse *p_response = NULL;
621
622     p_args = (RIL_SMS_WriteArgs *)data;
623
624     length = strlen(p_args->pdu)/2;
625     asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
626
627     err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
628
629     if (err != 0 || p_response->success == 0) goto error;
630
631     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
632     at_response_free(p_response);
633
634     return;
635 error:
636     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
637     at_response_free(p_response);
638 }
639
640 static void requestHangup(void *data, size_t datalen, RIL_Token t)
641 {
642     int *p_line;
643
644     int ret;
645     char *cmd;
646
647     p_line = (int *)data;
648
649     // 3GPP 22.030 6.5.5
650     // "Releases a specific active call X"
651     asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
652
653     ret = at_send_command(cmd, NULL);
654
655     free(cmd);
656
657     /* success or failure is ignored by the upper layer here.
658        it will call GET_CURRENT_CALLS and determine success that way */
659     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
660 }
661
662 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
663 {
664     ATResponse *p_response = NULL;
665     int err;
666     int response[2];
667     char *line;
668
669     err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
670
671     if (err < 0 || p_response->success == 0) {
672         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
673         goto error;
674     }
675
676     line = p_response->p_intermediates->line;
677
678     err = at_tok_start(&line);
679     if (err < 0) goto error;
680
681     err = at_tok_nextint(&line, &(response[0]));
682     if (err < 0) goto error;
683
684     err = at_tok_nextint(&line, &(response[1]));
685     if (err < 0) goto error;
686
687     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
688
689     at_response_free(p_response);
690     return;
691
692 error:
693     LOGE("requestSignalStrength must never return an error when radio is on");
694     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
695     at_response_free(p_response);
696 }
697
698 static void requestRegistrationState(int request, void *data,
699                                         size_t datalen, RIL_Token t)
700 {
701     int err;
702     int response[4];
703     char * responseStr[4];
704     ATResponse *p_response = NULL;
705     const char *cmd;
706     const char *prefix;
707     char *line, *p;
708     int commas;
709     int skip;
710     int count = 3;
711
712
713     if (request == RIL_REQUEST_REGISTRATION_STATE) {
714         cmd = "AT+CREG?";
715         prefix = "+CREG:";
716     } else if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
717         cmd = "AT+CGREG?";
718         prefix = "+CGREG:";
719     } else {
720         assert(0);
721         goto error;
722     }
723
724     err = at_send_command_singleline(cmd, prefix, &p_response);
725
726     if (err != 0) goto error;
727
728     line = p_response->p_intermediates->line;
729
730     err = at_tok_start(&line);
731     if (err < 0) goto error;
732
733     /* Ok you have to be careful here
734      * The solicited version of the CREG response is
735      * +CREG: n, stat, [lac, cid]
736      * and the unsolicited version is
737      * +CREG: stat, [lac, cid]
738      * The <n> parameter is basically "is unsolicited creg on?"
739      * which it should always be
740      *
741      * Now we should normally get the solicited version here,
742      * but the unsolicited version could have snuck in
743      * so we have to handle both
744      *
745      * Also since the LAC and CID are only reported when registered,
746      * we can have 1, 2, 3, or 4 arguments here
747      *
748      * finally, a +CGREG: answer may have a fifth value that corresponds
749      * to the network type, as in;
750      *
751      *   +CGREG: n, stat [,lac, cid [,networkType]]
752      */
753
754     /* count number of commas */
755     commas = 0;
756     for (p = line ; *p != '\0' ;p++) {
757         if (*p == ',') commas++;
758     }
759
760     switch (commas) {
761         case 0: /* +CREG: <stat> */
762             err = at_tok_nextint(&line, &response[0]);
763             if (err < 0) goto error;
764             response[1] = -1;
765             response[2] = -1;
766         break;
767
768         case 1: /* +CREG: <n>, <stat> */
769             err = at_tok_nextint(&line, &skip);
770             if (err < 0) goto error;
771             err = at_tok_nextint(&line, &response[0]);
772             if (err < 0) goto error;
773             response[1] = -1;
774             response[2] = -1;
775             if (err < 0) goto error;
776         break;
777
778         case 2: /* +CREG: <stat>, <lac>, <cid> */
779             err = at_tok_nextint(&line, &response[0]);
780             if (err < 0) goto error;
781             err = at_tok_nexthexint(&line, &response[1]);
782             if (err < 0) goto error;
783             err = at_tok_nexthexint(&line, &response[2]);
784             if (err < 0) goto error;
785         break;
786         case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
787             err = at_tok_nextint(&line, &skip);
788             if (err < 0) goto error;
789             err = at_tok_nextint(&line, &response[0]);
790             if (err < 0) goto error;
791             err = at_tok_nexthexint(&line, &response[1]);
792             if (err < 0) goto error;
793             err = at_tok_nexthexint(&line, &response[2]);
794             if (err < 0) goto error;
795         break;
796         /* special case for CGREG, there is a fourth parameter
797          * that is the network type (unknown/gprs/edge/umts)
798          */
799         case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
800             err = at_tok_nextint(&line, &skip);
801             if (err < 0) goto error;
802             err = at_tok_nextint(&line, &response[0]);
803             if (err < 0) goto error;
804             err = at_tok_nexthexint(&line, &response[1]);
805             if (err < 0) goto error;
806             err = at_tok_nexthexint(&line, &response[2]);
807             if (err < 0) goto error;
808             err = at_tok_nexthexint(&line, &response[3]);
809             if (err < 0) goto error;
810             count = 4;
811         break;
812         default:
813             goto error;
814     }
815
816     asprintf(&responseStr[0], "%d", response[0]);
817     asprintf(&responseStr[1], "%d", response[1]);
818     asprintf(&responseStr[2], "%d", response[2]);
819
820     if (count > 3)
821         asprintf(&responseStr[3], "%d", response[3]);
822
823     RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
824     at_response_free(p_response);
825
826     return;
827 error:
828     LOGE("requestRegistrationState must never return an error when radio is on");
829     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
830     at_response_free(p_response);
831 }
832
833 static void requestOperator(void *data, size_t datalen, RIL_Token t)
834 {
835     int err;
836     int i;
837     int skip;
838     ATLine *p_cur;
839     char *response[3];
840
841     memset(response, 0, sizeof(response));
842
843     ATResponse *p_response = NULL;
844
845     err = at_send_command_multiline(
846         "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
847         "+COPS:", &p_response);
848
849     /* we expect 3 lines here:
850      * +COPS: 0,0,"T - Mobile"
851      * +COPS: 0,1,"TMO"
852      * +COPS: 0,2,"310170"
853      */
854
855     if (err != 0) goto error;
856
857     for (i = 0, p_cur = p_response->p_intermediates
858             ; p_cur != NULL
859             ; p_cur = p_cur->p_next, i++
860     ) {
861         char *line = p_cur->line;
862
863         err = at_tok_start(&line);
864         if (err < 0) goto error;
865
866         err = at_tok_nextint(&line, &skip);
867         if (err < 0) goto error;
868
869         // If we're unregistered, we may just get
870         // a "+COPS: 0" response
871         if (!at_tok_hasmore(&line)) {
872             response[i] = NULL;
873             continue;
874         }
875
876         err = at_tok_nextint(&line, &skip);
877         if (err < 0) goto error;
878
879         // a "+COPS: 0, n" response is also possible
880         if (!at_tok_hasmore(&line)) {
881             response[i] = NULL;
882             continue;
883         }
884
885         err = at_tok_nextstr(&line, &(response[i]));
886         if (err < 0) goto error;
887     }
888
889     if (i != 3) {
890         /* expect 3 lines exactly */
891         goto error;
892     }
893
894     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
895     at_response_free(p_response);
896
897     return;
898 error:
899     LOGE("requestOperator must not return error when radio is on");
900     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
901     at_response_free(p_response);
902 }
903
904 static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
905 {
906     int err;
907     const char *smsc;
908     const char *pdu;
909     int tpLayerLength;
910     char *cmd1, *cmd2;
911     RIL_SMS_Response response;
912     ATResponse *p_response = NULL;
913
914     smsc = ((const char **)data)[0];
915     pdu = ((const char **)data)[1];
916
917     tpLayerLength = strlen(pdu)/2;
918
919     // "NULL for default SMSC"
920     if (smsc == NULL) {
921         smsc= "00";
922     }
923
924     asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
925     asprintf(&cmd2, "%s%s", smsc, pdu);
926
927     err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
928
929     if (err != 0 || p_response->success == 0) goto error;
930
931     memset(&response, 0, sizeof(response));
932
933     /* FIXME fill in messageRef and ackPDU */
934
935     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
936     at_response_free(p_response);
937
938     return;
939 error:
940     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
941     at_response_free(p_response);
942 }
943
944 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
945 {
946     const char *apn;
947     char *cmd;
948     int err;
949     ATResponse *p_response = NULL;
950     char *response[2] = { "1", PPP_TTY_PATH };
951
952     apn = ((const char **)data)[2];
953
954 #ifdef USE_TI_COMMANDS
955     // Config for multislot class 10 (probably default anyway eh?)
956     err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
957                         NULL);
958
959     err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
960 #endif /* USE_TI_COMMANDS */
961
962     int fd, qmistatus;
963     size_t cur = 0;
964     size_t len;
965     ssize_t written, rlen;
966     char status[32] = {0};
967     int retry = 10;
968
969     LOGD("requesting data connection to APN '%s'", apn);
970
971     fd = open ("/dev/qmi", O_RDWR);
972     if (fd >= 0) { /* the device doesn't exist on the emulator */
973
974             LOGD("opened the qmi device\n");
975             asprintf(&cmd, "up:%s", apn);
976             len = strlen(cmd);
977
978             while (cur < len) {
979                     do {
980                     written = write (fd, cmd + cur, len - cur);
981                 } while (written < 0 && errno == EINTR);
982
983                 if (written < 0) {
984                 LOGE("### ERROR writing to /dev/qmi");
985                 close(fd);
986                 goto error;
987             }
988
989             cur += written;
990         }
991
992         // wait for interface to come online
993
994         do {
995             sleep(1);
996             do {
997                 rlen = read(fd, status, 31);
998             } while (rlen < 0 && errno == EINTR);
999
1000             if (rlen < 0) {
1001                 LOGE("### ERROR reading from /dev/qmi");
1002                 close(fd);
1003                 goto error;
1004             } else {
1005                 status[rlen] = '\0';
1006                 LOGD("### status: %s", status);
1007             }
1008         } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
1009
1010         close(fd);
1011
1012         if (retry == 0) {
1013             LOGE("### Failed to get data connection up\n");
1014                 goto error;
1015                 }
1016
1017         qmistatus = system("netcfg rmnet0 dhcp");
1018
1019         LOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus);
1020
1021             if (qmistatus < 0) goto error;
1022
1023         } else {
1024
1025         asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
1026             //FIXME check for error here
1027             err = at_send_command(cmd, NULL);
1028             free(cmd);
1029
1030             // Set required QoS params to default
1031             err = at_send_command("AT+CGQREQ=1", NULL);
1032
1033             // Set minimum QoS params to default
1034             err = at_send_command("AT+CGQMIN=1", NULL);
1035
1036             // packet-domain event reporting
1037             err = at_send_command("AT+CGEREP=1,0", NULL);
1038
1039             // Hangup anything that's happening there now
1040             err = at_send_command("AT+CGACT=1,0", NULL);
1041
1042             // Start data on PDP context 1
1043             err = at_send_command("ATD*99***1#", &p_response);
1044
1045             if (err < 0 || p_response->success == 0) {
1046                 goto error;
1047             }
1048     }
1049
1050     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1051     at_response_free(p_response);
1052
1053     return;
1054 error:
1055     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1056     at_response_free(p_response);
1057
1058 }
1059
1060 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
1061 {
1062     int ackSuccess;
1063     int err;
1064
1065     ackSuccess = ((int *)data)[0];
1066
1067     if (ackSuccess == 1) {
1068         err = at_send_command("AT+CNMA=1", NULL);
1069     } else if (ackSuccess == 0)  {
1070         err = at_send_command("AT+CNMA=2", NULL);
1071     } else {
1072         LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
1073         goto error;
1074     }
1075
1076     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1077 error:
1078     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1079
1080 }
1081
1082 static void  requestSIM_IO(void *data, size_t datalen, RIL_Token t)
1083 {
1084     ATResponse *p_response = NULL;
1085     RIL_SIM_IO_Response sr;
1086     int err;
1087     char *cmd = NULL;
1088     RIL_SIM_IO *p_args;
1089     char *line;
1090
1091     memset(&sr, 0, sizeof(sr));
1092
1093     p_args = (RIL_SIM_IO *)data;
1094
1095     /* FIXME handle pin2 */
1096
1097     if (p_args->data == NULL) {
1098         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
1099                     p_args->command, p_args->fileid,
1100                     p_args->p1, p_args->p2, p_args->p3);
1101     } else {
1102         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
1103                     p_args->command, p_args->fileid,
1104                     p_args->p1, p_args->p2, p_args->p3, p_args->data);
1105     }
1106
1107     err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
1108
1109     if (err < 0 || p_response->success == 0) {
1110         goto error;
1111     }
1112
1113     line = p_response->p_intermediates->line;
1114
1115     err = at_tok_start(&line);
1116     if (err < 0) goto error;
1117
1118     err = at_tok_nextint(&line, &(sr.sw1));
1119     if (err < 0) goto error;
1120
1121     err = at_tok_nextint(&line, &(sr.sw2));
1122     if (err < 0) goto error;
1123
1124     if (at_tok_hasmore(&line)) {
1125         err = at_tok_nextstr(&line, &(sr.simResponse));
1126         if (err < 0) goto error;
1127     }
1128
1129     RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
1130     at_response_free(p_response);
1131     free(cmd);
1132
1133     return;
1134 error:
1135     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1136     at_response_free(p_response);
1137     free(cmd);
1138
1139 }
1140
1141 static void  requestEnterSimPin(void*  data, size_t  datalen, RIL_Token  t)
1142 {
1143     ATResponse   *p_response = NULL;
1144     int           err;
1145     char*         cmd = NULL;
1146     const char**  strings = (const char**)data;;
1147
1148     if ( datalen == sizeof(char*) ) {
1149         asprintf(&cmd, "AT+CPIN=%s", strings[0]);
1150     } else if ( datalen == 2*sizeof(char*) ) {
1151         asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
1152     } else
1153         goto error;
1154
1155     err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
1156     free(cmd);
1157
1158     if (err < 0 || p_response->success == 0) {
1159 error:
1160         RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
1161     } else {
1162         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1163     }
1164     at_response_free(p_response);
1165 }
1166
1167
1168 static void  requestSendUSSD(void *data, size_t datalen, RIL_Token t)
1169 {
1170     const char *ussdRequest;
1171
1172     ussdRequest = (char *)(data);
1173
1174
1175     RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1176
1177 // @@@ TODO
1178
1179 }
1180
1181
1182 /*** Callback methods from the RIL library to us ***/
1183
1184 /**
1185  * Call from RIL to us to make a RIL_REQUEST
1186  *
1187  * Must be completed with a call to RIL_onRequestComplete()
1188  *
1189  * RIL_onRequestComplete() may be called from any thread, before or after
1190  * this function returns.
1191  *
1192  * Will always be called from the same thread, so returning here implies
1193  * that the radio is ready to process another command (whether or not
1194  * the previous command has completed).
1195  */
1196 static void
1197 onRequest (int request, void *data, size_t datalen, RIL_Token t)
1198 {
1199     ATResponse *p_response;
1200     int err;
1201
1202     LOGD("onRequest: %s", requestToString(request));
1203
1204     /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
1205      * when RADIO_STATE_UNAVAILABLE.
1206      */
1207     if (sState == RADIO_STATE_UNAVAILABLE
1208         && request != RIL_REQUEST_GET_SIM_STATUS
1209     ) {
1210         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1211         return;
1212     }
1213
1214     /* Ignore all non-power requests when RADIO_STATE_OFF
1215      * (except RIL_REQUEST_GET_SIM_STATUS)
1216      */
1217     if (sState == RADIO_STATE_OFF
1218         && !(request == RIL_REQUEST_RADIO_POWER
1219             || request == RIL_REQUEST_GET_SIM_STATUS)
1220     ) {
1221         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1222         return;
1223     }
1224
1225     switch (request) {
1226         case RIL_REQUEST_GET_SIM_STATUS: {
1227             int simStatus;
1228
1229             simStatus = getSIMStatus();
1230
1231             RIL_onRequestComplete(t, RIL_E_SUCCESS, &simStatus, sizeof(simStatus));
1232             break;
1233         }
1234         case RIL_REQUEST_GET_CURRENT_CALLS:
1235             requestGetCurrentCalls(data, datalen, t);
1236             break;
1237         case RIL_REQUEST_DIAL:
1238             requestDial(data, datalen, t);
1239             break;
1240         case RIL_REQUEST_HANGUP:
1241             requestHangup(data, datalen, t);
1242             break;
1243         case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
1244             // 3GPP 22.030 6.5.5
1245             // "Releases all held calls or sets User Determined User Busy
1246             //  (UDUB) for a waiting call."
1247             at_send_command("AT+CHLD=0", NULL);
1248
1249             /* success or failure is ignored by the upper layer here.
1250                it will call GET_CURRENT_CALLS and determine success that way */
1251             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1252             break;
1253         case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
1254             // 3GPP 22.030 6.5.5
1255             // "Releases all active calls (if any exist) and accepts
1256             //  the other (held or waiting) call."
1257             at_send_command("AT+CHLD=1", NULL);
1258
1259             /* success or failure is ignored by the upper layer here.
1260                it will call GET_CURRENT_CALLS and determine success that way */
1261             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1262             break;
1263         case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
1264             // 3GPP 22.030 6.5.5
1265             // "Places all active calls (if any exist) on hold and accepts
1266             //  the other (held or waiting) call."
1267             at_send_command("AT+CHLD=2", NULL);
1268
1269 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1270             s_expectAnswer = 1;
1271 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
1272
1273             /* success or failure is ignored by the upper layer here.
1274                it will call GET_CURRENT_CALLS and determine success that way */
1275             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1276             break;
1277         case RIL_REQUEST_ANSWER:
1278             at_send_command("ATA", NULL);
1279
1280 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1281             s_expectAnswer = 1;
1282 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
1283
1284             /* success or failure is ignored by the upper layer here.
1285                it will call GET_CURRENT_CALLS and determine success that way */
1286             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1287             break;
1288         case RIL_REQUEST_CONFERENCE:
1289             // 3GPP 22.030 6.5.5
1290             // "Adds a held call to the conversation"
1291             at_send_command("AT+CHLD=3", NULL);
1292
1293             /* success or failure is ignored by the upper layer here.
1294                it will call GET_CURRENT_CALLS and determine success that way */
1295             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1296             break;
1297         case RIL_REQUEST_UDUB:
1298             /* user determined user busy */
1299             /* sometimes used: ATH */
1300             at_send_command("ATH", NULL);
1301
1302             /* success or failure is ignored by the upper layer here.
1303                it will call GET_CURRENT_CALLS and determine success that way */
1304             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1305             break;
1306
1307         case RIL_REQUEST_SEPARATE_CONNECTION:
1308             {
1309                 char  cmd[12];
1310                 int   party = ((int*)data)[0];
1311
1312                 // Make sure that party is in a valid range.
1313                 // (Note: The Telephony middle layer imposes a range of 1 to 7.
1314                 // It's sufficient for us to just make sure it's single digit.)
1315                 if (party > 0 && party < 10) {
1316                     sprintf(cmd, "AT+CHLD=2%d", party);
1317                     at_send_command(cmd, NULL);
1318                     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1319                 } else {
1320                     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1321                 }
1322             }
1323             break;
1324
1325         case RIL_REQUEST_SIGNAL_STRENGTH:
1326             requestSignalStrength(data, datalen, t);
1327             break;
1328         case RIL_REQUEST_REGISTRATION_STATE:
1329         case RIL_REQUEST_GPRS_REGISTRATION_STATE:
1330             requestRegistrationState(request, data, datalen, t);
1331             break;
1332         case RIL_REQUEST_OPERATOR:
1333             requestOperator(data, datalen, t);
1334             break;
1335         case RIL_REQUEST_RADIO_POWER:
1336             requestRadioPower(data, datalen, t);
1337             break;
1338         case RIL_REQUEST_DTMF: {
1339             char c = ((char *)data)[0];
1340             char *cmd;
1341             asprintf(&cmd, "AT+VTS=%c", (int)c);
1342             at_send_command(cmd, NULL);
1343             free(cmd);
1344             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1345             break;
1346         }
1347         case RIL_REQUEST_SEND_SMS:
1348             requestSendSMS(data, datalen, t);
1349             break;
1350         case RIL_REQUEST_SETUP_DATA_CALL:
1351             requestSetupDataCall(data, datalen, t);
1352             break;
1353         case RIL_REQUEST_SMS_ACKNOWLEDGE:
1354             requestSMSAcknowledge(data, datalen, t);
1355             break;
1356
1357         case RIL_REQUEST_GET_IMSI:
1358             p_response = NULL;
1359             err = at_send_command_numeric("AT+CIMI", &p_response);
1360
1361             if (err < 0 || p_response->success == 0) {
1362                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1363             } else {
1364                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1365                     p_response->p_intermediates->line, sizeof(char *));
1366             }
1367             at_response_free(p_response);
1368             break;
1369
1370         case RIL_REQUEST_GET_IMEI:
1371             p_response = NULL;
1372             err = at_send_command_numeric("AT+CGSN", &p_response);
1373
1374             if (err < 0 || p_response->success == 0) {
1375                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1376             } else {
1377                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1378                     p_response->p_intermediates->line, sizeof(char *));
1379             }
1380             at_response_free(p_response);
1381             break;
1382
1383         case RIL_REQUEST_SIM_IO:
1384             requestSIM_IO(data,datalen,t);
1385             break;
1386
1387         case RIL_REQUEST_SEND_USSD:
1388             requestSendUSSD(data, datalen, t);
1389             break;
1390
1391         case RIL_REQUEST_CANCEL_USSD:
1392             p_response = NULL;
1393             err = at_send_command_numeric("AT+CUSD=2", &p_response);
1394
1395             if (err < 0 || p_response->success == 0) {
1396                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1397             } else {
1398                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1399                     p_response->p_intermediates->line, sizeof(char *));
1400             }
1401             at_response_free(p_response);
1402             break;
1403
1404         case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
1405             at_send_command("AT+COPS=0", NULL);
1406             break;
1407
1408         case RIL_REQUEST_DATA_CALL_LIST:
1409             requestDataCallList(data, datalen, t);
1410             break;
1411
1412         case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
1413             requestQueryNetworkSelectionMode(data, datalen, t);
1414             break;
1415
1416         case RIL_REQUEST_OEM_HOOK_RAW:
1417             // echo back data
1418             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1419             break;
1420
1421
1422         case RIL_REQUEST_OEM_HOOK_STRINGS: {
1423             int i;
1424             const char ** cur;
1425
1426             LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
1427
1428
1429             for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
1430                     i > 0 ; cur++, i --) {
1431                 LOGD("> '%s'", *cur);
1432             }
1433
1434             // echo back strings
1435             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1436             break;
1437         }
1438
1439         case RIL_REQUEST_WRITE_SMS_TO_SIM:
1440             requestWriteSmsToSim(data, datalen, t);
1441             break;
1442
1443         case RIL_REQUEST_DELETE_SMS_ON_SIM: {
1444             char * cmd;
1445             p_response = NULL;
1446             asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
1447             err = at_send_command(cmd, &p_response);
1448             free(cmd);
1449             if (err < 0 || p_response->success == 0) {
1450                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1451             } else {
1452                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1453             }
1454             at_response_free(p_response);
1455             break;
1456         }
1457
1458         case RIL_REQUEST_ENTER_SIM_PIN:
1459         case RIL_REQUEST_ENTER_SIM_PUK:
1460         case RIL_REQUEST_ENTER_SIM_PIN2:
1461         case RIL_REQUEST_ENTER_SIM_PUK2:
1462         case RIL_REQUEST_CHANGE_SIM_PIN:
1463         case RIL_REQUEST_CHANGE_SIM_PIN2:
1464             requestEnterSimPin(data, datalen, t);
1465             break;
1466
1467         default:
1468             RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1469             break;
1470     }
1471 }
1472
1473 /**
1474  * Synchronous call from the RIL to us to return current radio state.
1475  * RADIO_STATE_UNAVAILABLE should be the initial state.
1476  */
1477 static RIL_RadioState
1478 currentState()
1479 {
1480     return sState;
1481 }
1482 /**
1483  * Call from RIL to us to find out whether a specific request code
1484  * is supported by this implementation.
1485  *
1486  * Return 1 for "supported" and 0 for "unsupported"
1487  */
1488
1489 static int
1490 onSupports (int requestCode)
1491 {
1492     //@@@ todo
1493
1494     return 1;
1495 }
1496
1497 static void onCancel (RIL_Token t)
1498 {
1499     //@@@todo
1500
1501 }
1502
1503 static const char * getVersion(void)
1504 {
1505     return "android reference-ril 1.0";
1506 }
1507
1508 static void
1509 setRadioState(RIL_RadioState newState)
1510 {
1511     RIL_RadioState oldState;
1512
1513     pthread_mutex_lock(&s_state_mutex);
1514
1515     oldState = sState;
1516
1517     if (s_closed > 0) {
1518         // If we're closed, the only reasonable state is
1519         // RADIO_STATE_UNAVAILABLE
1520         // This is here because things on the main thread
1521         // may attempt to change the radio state after the closed
1522         // event happened in another thread
1523         newState = RADIO_STATE_UNAVAILABLE;
1524     }
1525
1526     if (sState != newState || s_closed > 0) {
1527         sState = newState;
1528
1529         pthread_cond_broadcast (&s_state_cond);
1530     }
1531
1532     pthread_mutex_unlock(&s_state_mutex);
1533
1534
1535     /* do these outside of the mutex */
1536     if (sState != oldState) {
1537         RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
1538                                     NULL, 0);
1539
1540         /* FIXME onSimReady() and onRadioPowerOn() cannot be called
1541          * from the AT reader thread
1542          * Currently, this doesn't happen, but if that changes then these
1543          * will need to be dispatched on the request thread
1544          */
1545         if (sState == RADIO_STATE_SIM_READY) {
1546             onSIMReady();
1547         } else if (sState == RADIO_STATE_SIM_NOT_READY) {
1548             onRadioPowerOn();
1549         }
1550     }
1551 }
1552
1553 /** returns one of RIM_SIM_*. Returns RIL_SIM_NOT_READY on error */
1554 static int
1555 getSIMStatus()
1556 {
1557     ATResponse *p_response = NULL;
1558     int err;
1559     int ret;
1560     char *cpinLine;
1561     char *cpinResult;
1562
1563     if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
1564         ret = RIL_SIM_NOT_READY;
1565         goto done;
1566     }
1567
1568     err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
1569
1570     if (err != 0) {
1571         ret = RIL_SIM_NOT_READY;
1572         goto done;
1573     }
1574
1575     switch (at_get_cme_error(p_response)) {
1576         case CME_SUCCESS:
1577             break;
1578
1579         case CME_SIM_NOT_INSERTED:
1580             ret = RIL_SIM_ABSENT;
1581             goto done;
1582
1583         default:
1584             ret = RIL_SIM_NOT_READY;
1585             goto done;
1586     }
1587
1588     /* CPIN? has succeeded, now look at the result */
1589
1590     cpinLine = p_response->p_intermediates->line;
1591     err = at_tok_start (&cpinLine);
1592
1593     if (err < 0) {
1594         ret = RIL_SIM_NOT_READY;
1595         goto done;
1596     }
1597
1598     err = at_tok_nextstr(&cpinLine, &cpinResult);
1599
1600     if (err < 0) {
1601         ret = RIL_SIM_NOT_READY;
1602         goto done;
1603     }
1604
1605     if (0 == strcmp (cpinResult, "SIM PIN")) {
1606         ret = RIL_SIM_PIN;
1607         goto done;
1608     } else if (0 == strcmp (cpinResult, "SIM PUK")) {
1609         ret = RIL_SIM_PUK;
1610         goto done;
1611     } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
1612         return RIL_SIM_NETWORK_PERSONALIZATION;
1613     } else if (0 != strcmp (cpinResult, "READY"))  {
1614         /* we're treating unsupported lock types as "sim absent" */
1615         ret = RIL_SIM_ABSENT;
1616         goto done;
1617     }
1618
1619     at_response_free(p_response);
1620     p_response = NULL;
1621     cpinResult = NULL;
1622
1623     ret = RIL_SIM_READY;
1624
1625 done:
1626     at_response_free(p_response);
1627     return ret;
1628 }
1629
1630
1631 /**
1632  * SIM ready means any commands that access the SIM will work, including:
1633  *  AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
1634  *  (all SMS-related commands)
1635  */
1636
1637 static void pollSIMState (void *param)
1638 {
1639     ATResponse *p_response;
1640     int ret;
1641
1642     if (sState != RADIO_STATE_SIM_NOT_READY) {
1643         // no longer valid to poll
1644         return;
1645     }
1646
1647     switch(getSIMStatus()) {
1648         case RIL_SIM_ABSENT:
1649         case RIL_SIM_PIN:
1650         case RIL_SIM_PUK:
1651         case RIL_SIM_NETWORK_PERSONALIZATION:
1652         default:
1653             setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
1654         return;
1655
1656         case RIL_SIM_NOT_READY:
1657             RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
1658         return;
1659
1660         case RIL_SIM_READY:
1661             setRadioState(RADIO_STATE_SIM_READY);
1662         return;
1663     }
1664 }
1665
1666 /** returns 1 if on, 0 if off, and -1 on error */
1667 static int isRadioOn()
1668 {
1669     ATResponse *p_response = NULL;
1670     int err;
1671     char *line;
1672     char ret;
1673
1674     err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
1675
1676     if (err < 0 || p_response->success == 0) {
1677         // assume radio is off
1678         goto error;
1679     }
1680
1681     line = p_response->p_intermediates->line;
1682
1683     err = at_tok_start(&line);
1684     if (err < 0) goto error;
1685
1686     err = at_tok_nextbool(&line, &ret);
1687     if (err < 0) goto error;
1688
1689     at_response_free(p_response);
1690
1691     return (int)ret;
1692
1693 error:
1694
1695     at_response_free(p_response);
1696     return -1;
1697 }
1698
1699 /**
1700  * Initialize everything that can be configured while we're still in
1701  * AT+CFUN=0
1702  */
1703 static void initializeCallback(void *param)
1704 {
1705     ATResponse *p_response = NULL;
1706     int err;
1707
1708     setRadioState (RADIO_STATE_OFF);
1709
1710     at_handshake();
1711
1712     /* note: we don't check errors here. Everything important will
1713        be handled in onATTimeout and onATReaderClosed */
1714
1715     /*  atchannel is tolerant of echo but it must */
1716     /*  have verbose result codes */
1717     at_send_command("ATE0Q0V1", NULL);
1718
1719     /*  No auto-answer */
1720     at_send_command("ATS0=0", NULL);
1721
1722     /*  Extended errors */
1723     at_send_command("AT+CMEE=1", NULL);
1724
1725     /*  Network registration events */
1726     err = at_send_command("AT+CREG=2", &p_response);
1727
1728     /* some handsets -- in tethered mode -- don't support CREG=2 */
1729     if (err < 0 || p_response->success == 0) {
1730         at_send_command("AT+CREG=1", NULL);
1731     }
1732
1733     at_response_free(p_response);
1734
1735     /*  GPRS registration events */
1736     at_send_command("AT+CGREG=1", NULL);
1737
1738     /*  Call Waiting notifications */
1739     at_send_command("AT+CCWA=1", NULL);
1740
1741     /*  Alternating voice/data off */
1742     at_send_command("AT+CMOD=0", NULL);
1743
1744     /*  Not muted */
1745     at_send_command("AT+CMUT=0", NULL);
1746
1747     /*  +CSSU unsolicited supp service notifications */
1748     at_send_command("AT+CSSN=0,1", NULL);
1749
1750     /*  no connected line identification */
1751     at_send_command("AT+COLP=0", NULL);
1752
1753     /*  HEX character set */
1754     at_send_command("AT+CSCS=\"HEX\"", NULL);
1755
1756     /*  USSD unsolicited */
1757     at_send_command("AT+CUSD=1", NULL);
1758
1759     /*  Enable +CGEV GPRS event notifications, but don't buffer */
1760     at_send_command("AT+CGEREP=1,0", NULL);
1761
1762     /*  SMS PDU mode */
1763     at_send_command("AT+CMGF=0", NULL);
1764
1765 #ifdef USE_TI_COMMANDS
1766
1767     at_send_command("AT%CPI=3", NULL);
1768
1769     /*  TI specific -- notifications when SMS is ready (currently ignored) */
1770     at_send_command("AT%CSTAT=1", NULL);
1771
1772 #endif /* USE_TI_COMMANDS */
1773
1774
1775     /* assume radio is off on error */
1776     if (isRadioOn() > 0) {
1777         setRadioState (RADIO_STATE_SIM_NOT_READY);
1778     }
1779 }
1780
1781 static void waitForClose()
1782 {
1783     pthread_mutex_lock(&s_state_mutex);
1784
1785     while (s_closed == 0) {
1786         pthread_cond_wait(&s_state_cond, &s_state_mutex);
1787     }
1788
1789     pthread_mutex_unlock(&s_state_mutex);
1790 }
1791
1792 /**
1793  * Called by atchannel when an unsolicited line appears
1794  * This is called on atchannel's reader thread. AT commands may
1795  * not be issued here
1796  */
1797 static void onUnsolicited (const char *s, const char *sms_pdu)
1798 {
1799     char *line = NULL;
1800     int err;
1801
1802     /* Ignore unsolicited responses until we're initialized.
1803      * This is OK because the RIL library will poll for initial state
1804      */
1805     if (sState == RADIO_STATE_UNAVAILABLE) {
1806         return;
1807     }
1808
1809     if (strStartsWith(s, "%CTZV:")) {
1810         /* TI specific -- NITZ time */
1811         char *response;
1812
1813         line = strdup(s);
1814         at_tok_start(&line);
1815
1816         err = at_tok_nextstr(&line, &response);
1817
1818         if (err != 0) {
1819             LOGE("invalid NITZ line %s\n", s);
1820         } else {
1821             RIL_onUnsolicitedResponse (
1822                 RIL_UNSOL_NITZ_TIME_RECEIVED,
1823                 response, strlen(response));
1824         }
1825     } else if (strStartsWith(s,"+CRING:")
1826                 || strStartsWith(s,"RING")
1827                 || strStartsWith(s,"NO CARRIER")
1828                 || strStartsWith(s,"+CCWA")
1829     ) {
1830         RIL_onUnsolicitedResponse (
1831             RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
1832             NULL, 0);
1833 #ifdef WORKAROUND_FAKE_CGEV
1834         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
1835 #endif /* WORKAROUND_FAKE_CGEV */
1836     } else if (strStartsWith(s,"+CREG:")
1837                 || strStartsWith(s,"+CGREG:")
1838     ) {
1839         RIL_onUnsolicitedResponse (
1840             RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
1841             NULL, 0);
1842 #ifdef WORKAROUND_FAKE_CGEV
1843         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); 
1844 #endif /* WORKAROUND_FAKE_CGEV */
1845     } else if (strStartsWith(s, "+CMT:")) {
1846         RIL_onUnsolicitedResponse (
1847             RIL_UNSOL_RESPONSE_NEW_SMS,
1848             sms_pdu, strlen(sms_pdu));
1849     } else if (strStartsWith(s, "+CDS:")) {
1850         RIL_onUnsolicitedResponse (
1851             RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
1852             sms_pdu, strlen(sms_pdu));
1853     } else if (strStartsWith(s, "+CGEV:")) {
1854         /* Really, we can ignore NW CLASS and ME CLASS events here,
1855          * but right now we don't since extranous
1856          * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
1857          */
1858         /* can't issue AT commands here -- call on main thread */
1859         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1860 #ifdef WORKAROUND_FAKE_CGEV
1861     } else if (strStartsWith(s, "+CME ERROR: 150")) {
1862         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1863 #endif /* WORKAROUND_FAKE_CGEV */
1864     }
1865 }
1866
1867 /* Called on command or reader thread */
1868 static void onATReaderClosed()
1869 {
1870     LOGI("AT channel closed\n");
1871     at_close();
1872     s_closed = 1;
1873
1874     setRadioState (RADIO_STATE_UNAVAILABLE);
1875 }
1876
1877 /* Called on command thread */
1878 static void onATTimeout()
1879 {
1880     LOGI("AT channel timeout; closing\n");
1881     at_close();
1882
1883     s_closed = 1;
1884
1885     /* FIXME cause a radio reset here */
1886
1887     setRadioState (RADIO_STATE_UNAVAILABLE);
1888 }
1889
1890 static void usage(char *s)
1891 {
1892 #ifdef RIL_SHLIB
1893     fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
1894 #else
1895     fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
1896     exit(-1);
1897 #endif
1898 }
1899
1900 static void *
1901 mainLoop(void *param)
1902 {
1903     int fd;
1904     int ret;
1905
1906     AT_DUMP("== ", "entering mainLoop()", -1 );
1907     at_set_on_reader_closed(onATReaderClosed);
1908     at_set_on_timeout(onATTimeout);
1909
1910     for (;;) {
1911         fd = -1;
1912         while  (fd < 0) {
1913             if (s_port > 0) {
1914                 fd = socket_loopback_client(s_port, SOCK_STREAM);
1915             } else if (s_device_socket) {
1916                 if (!strcmp(s_device_path, "/dev/socket/qemud")) {
1917                     /* Qemu-specific control socket */
1918                     fd = socket_local_client( "qemud",
1919                                               ANDROID_SOCKET_NAMESPACE_RESERVED,
1920                                               SOCK_STREAM );
1921                     if (fd >= 0 ) {
1922                         char  answer[2];
1923
1924                         if ( write(fd, "gsm", 3) != 3 ||
1925                              read(fd, answer, 2) != 2 ||
1926                              memcmp(answer, "OK", 2) != 0)
1927                         {
1928                             close(fd);
1929                             fd = -1;
1930                         }
1931                    }
1932                 }
1933                 else
1934                     fd = socket_local_client( s_device_path,
1935                                             ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
1936                                             SOCK_STREAM );
1937             } else if (s_device_path != NULL) {
1938                 fd = open (s_device_path, O_RDWR);
1939                 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
1940                     /* disable echo on serial ports */
1941                     struct termios  ios;
1942                     tcgetattr( fd, &ios );
1943                     ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
1944                     tcsetattr( fd, TCSANOW, &ios );
1945                 }
1946             }
1947
1948             if (fd < 0) {
1949                 perror ("opening AT interface. retrying...");
1950                 sleep(10);
1951                 /* never returns */
1952             }
1953         }
1954
1955         s_closed = 0;
1956         ret = at_open(fd, onUnsolicited);
1957
1958         if (ret < 0) {
1959             LOGE ("AT error %d on at_open\n", ret);
1960             return 0;
1961         }
1962
1963         RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
1964
1965         // Give initializeCallback a chance to dispatched, since
1966         // we don't presently have a cancellation mechanism
1967         sleep(1);
1968
1969         waitForClose();
1970         LOGI("Re-opening after close");
1971     }
1972 }
1973
1974 #ifdef RIL_SHLIB
1975
1976 pthread_t s_tid_mainloop;
1977
1978 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
1979 {
1980     int ret;
1981     int fd = -1;
1982     int opt;
1983     pthread_attr_t attr;
1984
1985     s_rilenv = env;
1986
1987     while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
1988         switch (opt) {
1989             case 'p':
1990                 s_port = atoi(optarg);
1991                 if (s_port == 0) {
1992                     usage(argv[0]);
1993                     return NULL;
1994                 }
1995                 LOGI("Opening loopback port %d\n", s_port);
1996             break;
1997
1998             case 'd':
1999                 s_device_path = optarg;
2000                 LOGI("Opening tty device %s\n", s_device_path);
2001             break;
2002
2003             case 's':
2004                 s_device_path   = optarg;
2005                 s_device_socket = 1;
2006                 LOGI("Opening socket %s\n", s_device_path);
2007             break;
2008
2009             default:
2010                 usage(argv[0]);
2011                 return NULL;
2012         }
2013     }
2014
2015     if (s_port < 0 && s_device_path == NULL) {
2016         usage(argv[0]);
2017         return NULL;
2018     }
2019
2020     pthread_attr_init (&attr);
2021     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2022     ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
2023
2024     return &s_callbacks;
2025 }
2026 #else /* RIL_SHLIB */
2027 int main (int argc, char **argv)
2028 {
2029     int ret;
2030     int fd = -1;
2031     int opt;
2032
2033     while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
2034         switch (opt) {
2035             case 'p':
2036                 s_port = atoi(optarg);
2037                 if (s_port == 0) {
2038                     usage(argv[0]);
2039                 }
2040                 LOGI("Opening loopback port %d\n", s_port);
2041             break;
2042
2043             case 'd':
2044                 s_device_path = optarg;
2045                 LOGI("Opening tty device %s\n", s_device_path);
2046             break;
2047
2048             case 's':
2049                 s_device_path   = optarg;
2050                 s_device_socket = 1;
2051                 LOGI("Opening socket %s\n", s_device_path);
2052             break;
2053
2054             default:
2055                 usage(argv[0]);
2056         }
2057     }
2058
2059     if (s_port < 0 && s_device_path == NULL) {
2060         usage(argv[0]);
2061     }
2062
2063     RIL_register(&s_callbacks);
2064
2065     mainLoop(NULL);
2066
2067     return 0;
2068 }
2069
2070 #endif /* RIL_SHLIB */