OSDN Git Service

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