OSDN Git Service

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