Home | History | Annotate | Download | only in reference-ril
      1 /* //device/system/reference-ril/reference-ril.c
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include <telephony/ril.h>
     19 #include <stdio.h>
     20 #include <assert.h>
     21 #include <string.h>
     22 #include <errno.h>
     23 #include <unistd.h>
     24 #include <sys/types.h>
     25 #include <sys/stat.h>
     26 #include <fcntl.h>
     27 #include <pthread.h>
     28 #include <alloca.h>
     29 #include "atchannel.h"
     30 #include "at_tok.h"
     31 #include "misc.h"
     32 #include <getopt.h>
     33 #include <sys/socket.h>
     34 #include <cutils/sockets.h>
     35 #include <termios.h>
     36 
     37 #define LOG_TAG "RIL"
     38 #include <utils/Log.h>
     39 
     40 #define MAX_AT_RESPONSE 0x1000
     41 
     42 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
     43 #define PPP_TTY_PATH "/dev/omap_csmi_tty1"
     44 
     45 #ifdef USE_TI_COMMANDS
     46 
     47 // Enable a workaround
     48 // 1) Make incoming call, do not answer
     49 // 2) Hangup remote end
     50 // Expected: call should disappear from CLCC line
     51 // Actual: Call shows as "ACTIVE" before disappearing
     52 #define WORKAROUND_ERRONEOUS_ANSWER 1
     53 
     54 // Some varients of the TI stack do not support the +CGEV unsolicited
     55 // response. However, they seem to send an unsolicited +CME ERROR: 150
     56 #define WORKAROUND_FAKE_CGEV 1
     57 #endif
     58 
     59 typedef enum {
     60     SIM_ABSENT = 0,
     61     SIM_NOT_READY = 1,
     62     SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
     63     SIM_PIN = 3,
     64     SIM_PUK = 4,
     65     SIM_NETWORK_PERSONALIZATION = 5
     66 } SIM_Status;
     67 
     68 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
     69 static RIL_RadioState currentState();
     70 static int onSupports (int requestCode);
     71 static void onCancel (RIL_Token t);
     72 static const char *getVersion();
     73 static int isRadioOn();
     74 static SIM_Status getSIMStatus();
     75 static int getCardStatus(RIL_CardStatus **pp_card_status);
     76 static void freeCardStatus(RIL_CardStatus *p_card_status);
     77 static void onDataCallListChanged(void *param);
     78 
     79 extern const char * requestToString(int request);
     80 
     81 /*** Static Variables ***/
     82 static const RIL_RadioFunctions s_callbacks = {
     83     RIL_VERSION,
     84     onRequest,
     85     currentState,
     86     onSupports,
     87     onCancel,
     88     getVersion
     89 };
     90 
     91 #ifdef RIL_SHLIB
     92 static const struct RIL_Env *s_rilenv;
     93 
     94 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
     95 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
     96 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
     97 #endif
     98 
     99 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
    100 
    101 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
    102 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
    103 
    104 static int s_port = -1;
    105 static const char * s_device_path = NULL;
    106 static int          s_device_socket = 0;
    107 
    108 /* trigger change to this with s_state_cond */
    109 static int s_closed = 0;
    110 
    111 static int sFD;     /* file desc of AT channel */
    112 static char sATBuffer[MAX_AT_RESPONSE+1];
    113 static char *sATBufferCur = NULL;
    114 
    115 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
    116 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
    117 static const struct timeval TIMEVAL_0 = {0,0};
    118 
    119 #ifdef WORKAROUND_ERRONEOUS_ANSWER
    120 // Max number of times we'll try to repoll when we think
    121 // we have a AT+CLCC race condition
    122 #define REPOLL_CALLS_COUNT_MAX 4
    123 
    124 // Line index that was incoming or waiting at last poll, or -1 for none
    125 static int s_incomingOrWaitingLine = -1;
    126 // Number of times we've asked for a repoll of AT+CLCC
    127 static int s_repollCallsCount = 0;
    128 // Should we expect a call to be answered in the next CLCC?
    129 static int s_expectAnswer = 0;
    130 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
    131 
    132 static void pollSIMState (void *param);
    133 static void setRadioState(RIL_RadioState newState);
    134 
    135 static int clccStateToRILState(int state, RIL_CallState *p_state)
    136 
    137 {
    138     switch(state) {
    139         case 0: *p_state = RIL_CALL_ACTIVE;   return 0;
    140         case 1: *p_state = RIL_CALL_HOLDING;  return 0;
    141         case 2: *p_state = RIL_CALL_DIALING;  return 0;
    142         case 3: *p_state = RIL_CALL_ALERTING; return 0;
    143         case 4: *p_state = RIL_CALL_INCOMING; return 0;
    144         case 5: *p_state = RIL_CALL_WAITING;  return 0;
    145         default: return -1;
    146     }
    147 }
    148 
    149 /**
    150  * Note: directly modified line and has *p_call point directly into
    151  * modified line
    152  */
    153 static int callFromCLCCLine(char *line, RIL_Call *p_call)
    154 {
    155         //+CLCC: 1,0,2,0,0,\"+18005551212\",145
    156         //     index,isMT,state,mode,isMpty(,number,TOA)?
    157 
    158     int err;
    159     int state;
    160     int mode;
    161 
    162     err = at_tok_start(&line);
    163     if (err < 0) goto error;
    164 
    165     err = at_tok_nextint(&line, &(p_call->index));
    166     if (err < 0) goto error;
    167 
    168     err = at_tok_nextbool(&line, &(p_call->isMT));
    169     if (err < 0) goto error;
    170 
    171     err = at_tok_nextint(&line, &state);
    172     if (err < 0) goto error;
    173 
    174     err = clccStateToRILState(state, &(p_call->state));
    175     if (err < 0) goto error;
    176 
    177     err = at_tok_nextint(&line, &mode);
    178     if (err < 0) goto error;
    179 
    180     p_call->isVoice = (mode == 0);
    181 
    182     err = at_tok_nextbool(&line, &(p_call->isMpty));
    183     if (err < 0) goto error;
    184 
    185     if (at_tok_hasmore(&line)) {
    186         err = at_tok_nextstr(&line, &(p_call->number));
    187 
    188         /* tolerate null here */
    189         if (err < 0) return 0;
    190 
    191         // Some lame implementations return strings
    192         // like "NOT AVAILABLE" in the CLCC line
    193         if (p_call->number != NULL
    194             && 0 == strspn(p_call->number, "+0123456789")
    195         ) {
    196             p_call->number = NULL;
    197         }
    198 
    199         err = at_tok_nextint(&line, &p_call->toa);
    200         if (err < 0) goto error;
    201     }
    202 
    203     p_call->uusInfo = NULL;
    204 
    205     return 0;
    206 
    207 error:
    208     LOGE("invalid CLCC line\n");
    209     return -1;
    210 }
    211 
    212 
    213 /** do post-AT+CFUN=1 initialization */
    214 static void onRadioPowerOn()
    215 {
    216 #ifdef USE_TI_COMMANDS
    217     /*  Must be after CFUN=1 */
    218     /*  TI specific -- notifications for CPHS things such */
    219     /*  as CPHS message waiting indicator */
    220 
    221     at_send_command("AT%CPHS=1", NULL);
    222 
    223     /*  TI specific -- enable NITZ unsol notifs */
    224     at_send_command("AT%CTZV=1", NULL);
    225 #endif
    226 
    227     pollSIMState(NULL);
    228 }
    229 
    230 /** do post- SIM ready initialization */
    231 static void onSIMReady()
    232 {
    233     at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
    234     /*
    235      * Always send SMS messages directly to the TE
    236      *
    237      * mode = 1 // discard when link is reserved (link should never be
    238      *             reserved)
    239      * mt = 2   // most messages routed to TE
    240      * bm = 2   // new cell BM's routed to TE
    241      * ds = 1   // Status reports routed to TE
    242      * bfr = 1  // flush buffer
    243      */
    244     at_send_command("AT+CNMI=1,2,2,1,1", 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 
   1055 	    // Start data on PDP context 1
   1056 	    err = at_send_command("ATD*99***1#", &p_response);
   1057 
   1058 	    if (err < 0 || p_response->success == 0) {
   1059 	        goto error;
   1060 	    }
   1061     }
   1062 
   1063     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
   1064     at_response_free(p_response);
   1065 
   1066     return;
   1067 error:
   1068     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1069     at_response_free(p_response);
   1070 
   1071 }
   1072 
   1073 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
   1074 {
   1075     int ackSuccess;
   1076     int err;
   1077 
   1078     ackSuccess = ((int *)data)[0];
   1079 
   1080     if (ackSuccess == 1) {
   1081         err = at_send_command("AT+CNMA=1", NULL);
   1082     } else if (ackSuccess == 0)  {
   1083         err = at_send_command("AT+CNMA=2", NULL);
   1084     } else {
   1085         LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
   1086         goto error;
   1087     }
   1088 
   1089     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1090 error:
   1091     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1092 
   1093 }
   1094 
   1095 static void  requestSIM_IO(void *data, size_t datalen, RIL_Token t)
   1096 {
   1097     ATResponse *p_response = NULL;
   1098     RIL_SIM_IO_Response sr;
   1099     int err;
   1100     char *cmd = NULL;
   1101     RIL_SIM_IO *p_args;
   1102     char *line;
   1103 
   1104     memset(&sr, 0, sizeof(sr));
   1105 
   1106     p_args = (RIL_SIM_IO *)data;
   1107 
   1108     /* FIXME handle pin2 */
   1109 
   1110     if (p_args->data == NULL) {
   1111         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
   1112                     p_args->command, p_args->fileid,
   1113                     p_args->p1, p_args->p2, p_args->p3);
   1114     } else {
   1115         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
   1116                     p_args->command, p_args->fileid,
   1117                     p_args->p1, p_args->p2, p_args->p3, p_args->data);
   1118     }
   1119 
   1120     err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
   1121 
   1122     if (err < 0 || p_response->success == 0) {
   1123         goto error;
   1124     }
   1125 
   1126     line = p_response->p_intermediates->line;
   1127 
   1128     err = at_tok_start(&line);
   1129     if (err < 0) goto error;
   1130 
   1131     err = at_tok_nextint(&line, &(sr.sw1));
   1132     if (err < 0) goto error;
   1133 
   1134     err = at_tok_nextint(&line, &(sr.sw2));
   1135     if (err < 0) goto error;
   1136 
   1137     if (at_tok_hasmore(&line)) {
   1138         err = at_tok_nextstr(&line, &(sr.simResponse));
   1139         if (err < 0) goto error;
   1140     }
   1141 
   1142     RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
   1143     at_response_free(p_response);
   1144     free(cmd);
   1145 
   1146     return;
   1147 error:
   1148     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1149     at_response_free(p_response);
   1150     free(cmd);
   1151 
   1152 }
   1153 
   1154 static void  requestEnterSimPin(void*  data, size_t  datalen, RIL_Token  t)
   1155 {
   1156     ATResponse   *p_response = NULL;
   1157     int           err;
   1158     char*         cmd = NULL;
   1159     const char**  strings = (const char**)data;;
   1160 
   1161     if ( datalen == sizeof(char*) ) {
   1162         asprintf(&cmd, "AT+CPIN=%s", strings[0]);
   1163     } else if ( datalen == 2*sizeof(char*) ) {
   1164         asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
   1165     } else
   1166         goto error;
   1167 
   1168     err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
   1169     free(cmd);
   1170 
   1171     if (err < 0 || p_response->success == 0) {
   1172 error:
   1173         RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
   1174     } else {
   1175         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1176     }
   1177     at_response_free(p_response);
   1178 }
   1179 
   1180 
   1181 static void  requestSendUSSD(void *data, size_t datalen, RIL_Token t)
   1182 {
   1183     const char *ussdRequest;
   1184 
   1185     ussdRequest = (char *)(data);
   1186 
   1187 
   1188     RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
   1189 
   1190 // @@@ TODO
   1191 
   1192 }
   1193 
   1194 
   1195 /*** Callback methods from the RIL library to us ***/
   1196 
   1197 /**
   1198  * Call from RIL to us to make a RIL_REQUEST
   1199  *
   1200  * Must be completed with a call to RIL_onRequestComplete()
   1201  *
   1202  * RIL_onRequestComplete() may be called from any thread, before or after
   1203  * this function returns.
   1204  *
   1205  * Will always be called from the same thread, so returning here implies
   1206  * that the radio is ready to process another command (whether or not
   1207  * the previous command has completed).
   1208  */
   1209 static void
   1210 onRequest (int request, void *data, size_t datalen, RIL_Token t)
   1211 {
   1212     ATResponse *p_response;
   1213     int err;
   1214 
   1215     LOGD("onRequest: %s", requestToString(request));
   1216 
   1217     /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
   1218      * when RADIO_STATE_UNAVAILABLE.
   1219      */
   1220     if (sState == RADIO_STATE_UNAVAILABLE
   1221         && request != RIL_REQUEST_GET_SIM_STATUS
   1222     ) {
   1223         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
   1224         return;
   1225     }
   1226 
   1227     /* Ignore all non-power requests when RADIO_STATE_OFF
   1228      * (except RIL_REQUEST_GET_SIM_STATUS)
   1229      */
   1230     if (sState == RADIO_STATE_OFF
   1231         && !(request == RIL_REQUEST_RADIO_POWER
   1232             || request == RIL_REQUEST_GET_SIM_STATUS)
   1233     ) {
   1234         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
   1235         return;
   1236     }
   1237 
   1238     switch (request) {
   1239         case RIL_REQUEST_GET_SIM_STATUS: {
   1240             RIL_CardStatus *p_card_status;
   1241             char *p_buffer;
   1242             int buffer_size;
   1243 
   1244             int result = getCardStatus(&p_card_status);
   1245             if (result == RIL_E_SUCCESS) {
   1246                 p_buffer = (char *)p_card_status;
   1247                 buffer_size = sizeof(*p_card_status);
   1248             } else {
   1249                 p_buffer = NULL;
   1250                 buffer_size = 0;
   1251             }
   1252             RIL_onRequestComplete(t, result, p_buffer, buffer_size);
   1253             freeCardStatus(p_card_status);
   1254             break;
   1255         }
   1256         case RIL_REQUEST_GET_CURRENT_CALLS:
   1257             requestGetCurrentCalls(data, datalen, t);
   1258             break;
   1259         case RIL_REQUEST_DIAL:
   1260             requestDial(data, datalen, t);
   1261             break;
   1262         case RIL_REQUEST_HANGUP:
   1263             requestHangup(data, datalen, t);
   1264             break;
   1265         case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
   1266             // 3GPP 22.030 6.5.5
   1267             // "Releases all held calls or sets User Determined User Busy
   1268             //  (UDUB) for a waiting call."
   1269             at_send_command("AT+CHLD=0", NULL);
   1270 
   1271             /* success or failure is ignored by the upper layer here.
   1272                it will call GET_CURRENT_CALLS and determine success that way */
   1273             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1274             break;
   1275         case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
   1276             // 3GPP 22.030 6.5.5
   1277             // "Releases all active calls (if any exist) and accepts
   1278             //  the other (held or waiting) call."
   1279             at_send_command("AT+CHLD=1", 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_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
   1286             // 3GPP 22.030 6.5.5
   1287             // "Places all active calls (if any exist) on hold and accepts
   1288             //  the other (held or waiting) call."
   1289             at_send_command("AT+CHLD=2", NULL);
   1290 
   1291 #ifdef WORKAROUND_ERRONEOUS_ANSWER
   1292             s_expectAnswer = 1;
   1293 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
   1294 
   1295             /* success or failure is ignored by the upper layer here.
   1296                it will call GET_CURRENT_CALLS and determine success that way */
   1297             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1298             break;
   1299         case RIL_REQUEST_ANSWER:
   1300             at_send_command("ATA", NULL);
   1301 
   1302 #ifdef WORKAROUND_ERRONEOUS_ANSWER
   1303             s_expectAnswer = 1;
   1304 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
   1305 
   1306             /* success or failure is ignored by the upper layer here.
   1307                it will call GET_CURRENT_CALLS and determine success that way */
   1308             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1309             break;
   1310         case RIL_REQUEST_CONFERENCE:
   1311             // 3GPP 22.030 6.5.5
   1312             // "Adds a held call to the conversation"
   1313             at_send_command("AT+CHLD=3", NULL);
   1314 
   1315             /* success or failure is ignored by the upper layer here.
   1316                it will call GET_CURRENT_CALLS and determine success that way */
   1317             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1318             break;
   1319         case RIL_REQUEST_UDUB:
   1320             /* user determined user busy */
   1321             /* sometimes used: ATH */
   1322             at_send_command("ATH", NULL);
   1323 
   1324             /* success or failure is ignored by the upper layer here.
   1325                it will call GET_CURRENT_CALLS and determine success that way */
   1326             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1327             break;
   1328 
   1329         case RIL_REQUEST_SEPARATE_CONNECTION:
   1330             {
   1331                 char  cmd[12];
   1332                 int   party = ((int*)data)[0];
   1333 
   1334                 // Make sure that party is in a valid range.
   1335                 // (Note: The Telephony middle layer imposes a range of 1 to 7.
   1336                 // It's sufficient for us to just make sure it's single digit.)
   1337                 if (party > 0 && party < 10) {
   1338                     sprintf(cmd, "AT+CHLD=2%d", party);
   1339                     at_send_command(cmd, NULL);
   1340                     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1341                 } else {
   1342                     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1343                 }
   1344             }
   1345             break;
   1346 
   1347         case RIL_REQUEST_SIGNAL_STRENGTH:
   1348             requestSignalStrength(data, datalen, t);
   1349             break;
   1350         case RIL_REQUEST_REGISTRATION_STATE:
   1351         case RIL_REQUEST_GPRS_REGISTRATION_STATE:
   1352             requestRegistrationState(request, data, datalen, t);
   1353             break;
   1354         case RIL_REQUEST_OPERATOR:
   1355             requestOperator(data, datalen, t);
   1356             break;
   1357         case RIL_REQUEST_RADIO_POWER:
   1358             requestRadioPower(data, datalen, t);
   1359             break;
   1360         case RIL_REQUEST_DTMF: {
   1361             char c = ((char *)data)[0];
   1362             char *cmd;
   1363             asprintf(&cmd, "AT+VTS=%c", (int)c);
   1364             at_send_command(cmd, NULL);
   1365             free(cmd);
   1366             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1367             break;
   1368         }
   1369         case RIL_REQUEST_SEND_SMS:
   1370             requestSendSMS(data, datalen, t);
   1371             break;
   1372         case RIL_REQUEST_SETUP_DATA_CALL:
   1373             requestSetupDataCall(data, datalen, t);
   1374             break;
   1375         case RIL_REQUEST_SMS_ACKNOWLEDGE:
   1376             requestSMSAcknowledge(data, datalen, t);
   1377             break;
   1378 
   1379         case RIL_REQUEST_GET_IMSI:
   1380             p_response = NULL;
   1381             err = at_send_command_numeric("AT+CIMI", &p_response);
   1382 
   1383             if (err < 0 || p_response->success == 0) {
   1384                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1385             } else {
   1386                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
   1387                     p_response->p_intermediates->line, sizeof(char *));
   1388             }
   1389             at_response_free(p_response);
   1390             break;
   1391 
   1392         case RIL_REQUEST_GET_IMEI:
   1393             p_response = NULL;
   1394             err = at_send_command_numeric("AT+CGSN", &p_response);
   1395 
   1396             if (err < 0 || p_response->success == 0) {
   1397                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1398             } else {
   1399                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
   1400                     p_response->p_intermediates->line, sizeof(char *));
   1401             }
   1402             at_response_free(p_response);
   1403             break;
   1404 
   1405         case RIL_REQUEST_SIM_IO:
   1406             requestSIM_IO(data,datalen,t);
   1407             break;
   1408 
   1409         case RIL_REQUEST_SEND_USSD:
   1410             requestSendUSSD(data, datalen, t);
   1411             break;
   1412 
   1413         case RIL_REQUEST_CANCEL_USSD:
   1414             p_response = NULL;
   1415             err = at_send_command_numeric("AT+CUSD=2", &p_response);
   1416 
   1417             if (err < 0 || p_response->success == 0) {
   1418                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1419             } else {
   1420                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
   1421                     p_response->p_intermediates->line, sizeof(char *));
   1422             }
   1423             at_response_free(p_response);
   1424             break;
   1425 
   1426         case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
   1427             at_send_command("AT+COPS=0", NULL);
   1428             break;
   1429 
   1430         case RIL_REQUEST_DATA_CALL_LIST:
   1431             requestDataCallList(data, datalen, t);
   1432             break;
   1433 
   1434         case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
   1435             requestQueryNetworkSelectionMode(data, datalen, t);
   1436             break;
   1437 
   1438         case RIL_REQUEST_OEM_HOOK_RAW:
   1439             // echo back data
   1440             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
   1441             break;
   1442 
   1443 
   1444         case RIL_REQUEST_OEM_HOOK_STRINGS: {
   1445             int i;
   1446             const char ** cur;
   1447 
   1448             LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
   1449 
   1450 
   1451             for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
   1452                     i > 0 ; cur++, i --) {
   1453                 LOGD("> '%s'", *cur);
   1454             }
   1455 
   1456             // echo back strings
   1457             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
   1458             break;
   1459         }
   1460 
   1461         case RIL_REQUEST_WRITE_SMS_TO_SIM:
   1462             requestWriteSmsToSim(data, datalen, t);
   1463             break;
   1464 
   1465         case RIL_REQUEST_DELETE_SMS_ON_SIM: {
   1466             char * cmd;
   1467             p_response = NULL;
   1468             asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
   1469             err = at_send_command(cmd, &p_response);
   1470             free(cmd);
   1471             if (err < 0 || p_response->success == 0) {
   1472                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1473             } else {
   1474                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1475             }
   1476             at_response_free(p_response);
   1477             break;
   1478         }
   1479 
   1480         case RIL_REQUEST_ENTER_SIM_PIN:
   1481         case RIL_REQUEST_ENTER_SIM_PUK:
   1482         case RIL_REQUEST_ENTER_SIM_PIN2:
   1483         case RIL_REQUEST_ENTER_SIM_PUK2:
   1484         case RIL_REQUEST_CHANGE_SIM_PIN:
   1485         case RIL_REQUEST_CHANGE_SIM_PIN2:
   1486             requestEnterSimPin(data, datalen, t);
   1487             break;
   1488 
   1489         default:
   1490             RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
   1491             break;
   1492     }
   1493 }
   1494 
   1495 /**
   1496  * Synchronous call from the RIL to us to return current radio state.
   1497  * RADIO_STATE_UNAVAILABLE should be the initial state.
   1498  */
   1499 static RIL_RadioState
   1500 currentState()
   1501 {
   1502     return sState;
   1503 }
   1504 /**
   1505  * Call from RIL to us to find out whether a specific request code
   1506  * is supported by this implementation.
   1507  *
   1508  * Return 1 for "supported" and 0 for "unsupported"
   1509  */
   1510 
   1511 static int
   1512 onSupports (int requestCode)
   1513 {
   1514     //@@@ todo
   1515 
   1516     return 1;
   1517 }
   1518 
   1519 static void onCancel (RIL_Token t)
   1520 {
   1521     //@@@todo
   1522 
   1523 }
   1524 
   1525 static const char * getVersion(void)
   1526 {
   1527     return "android reference-ril 1.0";
   1528 }
   1529 
   1530 static void
   1531 setRadioState(RIL_RadioState newState)
   1532 {
   1533     RIL_RadioState oldState;
   1534 
   1535     pthread_mutex_lock(&s_state_mutex);
   1536 
   1537     oldState = sState;
   1538 
   1539     if (s_closed > 0) {
   1540         // If we're closed, the only reasonable state is
   1541         // RADIO_STATE_UNAVAILABLE
   1542         // This is here because things on the main thread
   1543         // may attempt to change the radio state after the closed
   1544         // event happened in another thread
   1545         newState = RADIO_STATE_UNAVAILABLE;
   1546     }
   1547 
   1548     if (sState != newState || s_closed > 0) {
   1549         sState = newState;
   1550 
   1551         pthread_cond_broadcast (&s_state_cond);
   1552     }
   1553 
   1554     pthread_mutex_unlock(&s_state_mutex);
   1555 
   1556 
   1557     /* do these outside of the mutex */
   1558     if (sState != oldState) {
   1559         RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
   1560                                     NULL, 0);
   1561 
   1562         /* FIXME onSimReady() and onRadioPowerOn() cannot be called
   1563          * from the AT reader thread
   1564          * Currently, this doesn't happen, but if that changes then these
   1565          * will need to be dispatched on the request thread
   1566          */
   1567         if (sState == RADIO_STATE_SIM_READY) {
   1568             onSIMReady();
   1569         } else if (sState == RADIO_STATE_SIM_NOT_READY) {
   1570             onRadioPowerOn();
   1571         }
   1572     }
   1573 }
   1574 
   1575 /** Returns SIM_NOT_READY on error */
   1576 static SIM_Status
   1577 getSIMStatus()
   1578 {
   1579     ATResponse *p_response = NULL;
   1580     int err;
   1581     int ret;
   1582     char *cpinLine;
   1583     char *cpinResult;
   1584 
   1585     if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
   1586         ret = SIM_NOT_READY;
   1587         goto done;
   1588     }
   1589 
   1590     err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
   1591 
   1592     if (err != 0) {
   1593         ret = SIM_NOT_READY;
   1594         goto done;
   1595     }
   1596 
   1597     switch (at_get_cme_error(p_response)) {
   1598         case CME_SUCCESS:
   1599             break;
   1600 
   1601         case CME_SIM_NOT_INSERTED:
   1602             ret = SIM_ABSENT;
   1603             goto done;
   1604 
   1605         default:
   1606             ret = SIM_NOT_READY;
   1607             goto done;
   1608     }
   1609 
   1610     /* CPIN? has succeeded, now look at the result */
   1611 
   1612     cpinLine = p_response->p_intermediates->line;
   1613     err = at_tok_start (&cpinLine);
   1614 
   1615     if (err < 0) {
   1616         ret = SIM_NOT_READY;
   1617         goto done;
   1618     }
   1619 
   1620     err = at_tok_nextstr(&cpinLine, &cpinResult);
   1621 
   1622     if (err < 0) {
   1623         ret = SIM_NOT_READY;
   1624         goto done;
   1625     }
   1626 
   1627     if (0 == strcmp (cpinResult, "SIM PIN")) {
   1628         ret = SIM_PIN;
   1629         goto done;
   1630     } else if (0 == strcmp (cpinResult, "SIM PUK")) {
   1631         ret = SIM_PUK;
   1632         goto done;
   1633     } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
   1634         return SIM_NETWORK_PERSONALIZATION;
   1635     } else if (0 != strcmp (cpinResult, "READY"))  {
   1636         /* we're treating unsupported lock types as "sim absent" */
   1637         ret = SIM_ABSENT;
   1638         goto done;
   1639     }
   1640 
   1641     at_response_free(p_response);
   1642     p_response = NULL;
   1643     cpinResult = NULL;
   1644 
   1645     ret = SIM_READY;
   1646 
   1647 done:
   1648     at_response_free(p_response);
   1649     return ret;
   1650 }
   1651 
   1652 
   1653 /**
   1654  * Get the current card status.
   1655  *
   1656  * This must be freed using freeCardStatus.
   1657  * @return: On success returns RIL_E_SUCCESS
   1658  */
   1659 static int getCardStatus(RIL_CardStatus **pp_card_status) {
   1660     static RIL_AppStatus app_status_array[] = {
   1661         // SIM_ABSENT = 0
   1662         { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
   1663           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   1664         // SIM_NOT_READY = 1
   1665         { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
   1666           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   1667         // SIM_READY = 2
   1668         { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
   1669           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   1670         // SIM_PIN = 3
   1671         { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
   1672           NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
   1673         // SIM_PUK = 4
   1674         { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
   1675           NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
   1676         // SIM_NETWORK_PERSONALIZATION = 5
   1677         { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
   1678           NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }
   1679     };
   1680     RIL_CardState card_state;
   1681     int num_apps;
   1682 
   1683     int sim_status = getSIMStatus();
   1684     if (sim_status == SIM_ABSENT) {
   1685         card_state = RIL_CARDSTATE_ABSENT;
   1686         num_apps = 0;
   1687     } else {
   1688         card_state = RIL_CARDSTATE_PRESENT;
   1689         num_apps = 1;
   1690     }
   1691 
   1692     // Allocate and initialize base card status.
   1693     RIL_CardStatus *p_card_status = malloc(sizeof(RIL_CardStatus));
   1694     p_card_status->card_state = card_state;
   1695     p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
   1696     p_card_status->gsm_umts_subscription_app_index = RIL_CARD_MAX_APPS;
   1697     p_card_status->cdma_subscription_app_index = RIL_CARD_MAX_APPS;
   1698     p_card_status->num_applications = num_apps;
   1699 
   1700     // Initialize application status
   1701     int i;
   1702     for (i = 0; i < RIL_CARD_MAX_APPS; i++) {
   1703         p_card_status->applications[i] = app_status_array[SIM_ABSENT];
   1704     }
   1705 
   1706     // Pickup the appropriate application status
   1707     // that reflects sim_status for gsm.
   1708     if (num_apps != 0) {
   1709         // Only support one app, gsm
   1710         p_card_status->num_applications = 1;
   1711         p_card_status->gsm_umts_subscription_app_index = 0;
   1712 
   1713         // Get the correct app status
   1714         p_card_status->applications[0] = app_status_array[sim_status];
   1715     }
   1716 
   1717     *pp_card_status = p_card_status;
   1718     return RIL_E_SUCCESS;
   1719 }
   1720 
   1721 /**
   1722  * Free the card status returned by getCardStatus
   1723  */
   1724 static void freeCardStatus(RIL_CardStatus *p_card_status) {
   1725     free(p_card_status);
   1726 }
   1727 
   1728 /**
   1729  * SIM ready means any commands that access the SIM will work, including:
   1730  *  AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
   1731  *  (all SMS-related commands)
   1732  */
   1733 
   1734 static void pollSIMState (void *param)
   1735 {
   1736     ATResponse *p_response;
   1737     int ret;
   1738 
   1739     if (sState != RADIO_STATE_SIM_NOT_READY) {
   1740         // no longer valid to poll
   1741         return;
   1742     }
   1743 
   1744     switch(getSIMStatus()) {
   1745         case SIM_ABSENT:
   1746         case SIM_PIN:
   1747         case SIM_PUK:
   1748         case SIM_NETWORK_PERSONALIZATION:
   1749         default:
   1750             setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
   1751         return;
   1752 
   1753         case SIM_NOT_READY:
   1754             RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
   1755         return;
   1756 
   1757         case SIM_READY:
   1758             setRadioState(RADIO_STATE_SIM_READY);
   1759         return;
   1760     }
   1761 }
   1762 
   1763 /** returns 1 if on, 0 if off, and -1 on error */
   1764 static int isRadioOn()
   1765 {
   1766     ATResponse *p_response = NULL;
   1767     int err;
   1768     char *line;
   1769     char ret;
   1770 
   1771     err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
   1772 
   1773     if (err < 0 || p_response->success == 0) {
   1774         // assume radio is off
   1775         goto error;
   1776     }
   1777 
   1778     line = p_response->p_intermediates->line;
   1779 
   1780     err = at_tok_start(&line);
   1781     if (err < 0) goto error;
   1782 
   1783     err = at_tok_nextbool(&line, &ret);
   1784     if (err < 0) goto error;
   1785 
   1786     at_response_free(p_response);
   1787 
   1788     return (int)ret;
   1789 
   1790 error:
   1791 
   1792     at_response_free(p_response);
   1793     return -1;
   1794 }
   1795 
   1796 /**
   1797  * Initialize everything that can be configured while we're still in
   1798  * AT+CFUN=0
   1799  */
   1800 static void initializeCallback(void *param)
   1801 {
   1802     ATResponse *p_response = NULL;
   1803     int err;
   1804 
   1805     setRadioState (RADIO_STATE_OFF);
   1806 
   1807     at_handshake();
   1808 
   1809     /* note: we don't check errors here. Everything important will
   1810        be handled in onATTimeout and onATReaderClosed */
   1811 
   1812     /*  atchannel is tolerant of echo but it must */
   1813     /*  have verbose result codes */
   1814     at_send_command("ATE0Q0V1", NULL);
   1815 
   1816     /*  No auto-answer */
   1817     at_send_command("ATS0=0", NULL);
   1818 
   1819     /*  Extended errors */
   1820     at_send_command("AT+CMEE=1", NULL);
   1821 
   1822     /*  Network registration events */
   1823     err = at_send_command("AT+CREG=2", &p_response);
   1824 
   1825     /* some handsets -- in tethered mode -- don't support CREG=2 */
   1826     if (err < 0 || p_response->success == 0) {
   1827         at_send_command("AT+CREG=1", NULL);
   1828     }
   1829 
   1830     at_response_free(p_response);
   1831 
   1832     /*  GPRS registration events */
   1833     at_send_command("AT+CGREG=1", NULL);
   1834 
   1835     /*  Call Waiting notifications */
   1836     at_send_command("AT+CCWA=1", NULL);
   1837 
   1838     /*  Alternating voice/data off */
   1839     at_send_command("AT+CMOD=0", NULL);
   1840 
   1841     /*  Not muted */
   1842     at_send_command("AT+CMUT=0", NULL);
   1843 
   1844     /*  +CSSU unsolicited supp service notifications */
   1845     at_send_command("AT+CSSN=0,1", NULL);
   1846 
   1847     /*  no connected line identification */
   1848     at_send_command("AT+COLP=0", NULL);
   1849 
   1850     /*  HEX character set */
   1851     at_send_command("AT+CSCS=\"HEX\"", NULL);
   1852 
   1853     /*  USSD unsolicited */
   1854     at_send_command("AT+CUSD=1", NULL);
   1855 
   1856     /*  Enable +CGEV GPRS event notifications, but don't buffer */
   1857     at_send_command("AT+CGEREP=1,0", NULL);
   1858 
   1859     /*  SMS PDU mode */
   1860     at_send_command("AT+CMGF=0", NULL);
   1861 
   1862 #ifdef USE_TI_COMMANDS
   1863 
   1864     at_send_command("AT%CPI=3", NULL);
   1865 
   1866     /*  TI specific -- notifications when SMS is ready (currently ignored) */
   1867     at_send_command("AT%CSTAT=1", NULL);
   1868 
   1869 #endif /* USE_TI_COMMANDS */
   1870 
   1871 
   1872     /* assume radio is off on error */
   1873     if (isRadioOn() > 0) {
   1874         setRadioState (RADIO_STATE_SIM_NOT_READY);
   1875     }
   1876 }
   1877 
   1878 static void waitForClose()
   1879 {
   1880     pthread_mutex_lock(&s_state_mutex);
   1881 
   1882     while (s_closed == 0) {
   1883         pthread_cond_wait(&s_state_cond, &s_state_mutex);
   1884     }
   1885 
   1886     pthread_mutex_unlock(&s_state_mutex);
   1887 }
   1888 
   1889 /**
   1890  * Called by atchannel when an unsolicited line appears
   1891  * This is called on atchannel's reader thread. AT commands may
   1892  * not be issued here
   1893  */
   1894 static void onUnsolicited (const char *s, const char *sms_pdu)
   1895 {
   1896     char *line = NULL;
   1897     int err;
   1898 
   1899     /* Ignore unsolicited responses until we're initialized.
   1900      * This is OK because the RIL library will poll for initial state
   1901      */
   1902     if (sState == RADIO_STATE_UNAVAILABLE) {
   1903         return;
   1904     }
   1905 
   1906     if (strStartsWith(s, "%CTZV:")) {
   1907         /* TI specific -- NITZ time */
   1908         char *response;
   1909 
   1910         line = strdup(s);
   1911         at_tok_start(&line);
   1912 
   1913         err = at_tok_nextstr(&line, &response);
   1914 
   1915         if (err != 0) {
   1916             LOGE("invalid NITZ line %s\n", s);
   1917         } else {
   1918             RIL_onUnsolicitedResponse (
   1919                 RIL_UNSOL_NITZ_TIME_RECEIVED,
   1920                 response, strlen(response));
   1921         }
   1922     } else if (strStartsWith(s,"+CRING:")
   1923                 || strStartsWith(s,"RING")
   1924                 || strStartsWith(s,"NO CARRIER")
   1925                 || strStartsWith(s,"+CCWA")
   1926     ) {
   1927         RIL_onUnsolicitedResponse (
   1928             RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
   1929             NULL, 0);
   1930 #ifdef WORKAROUND_FAKE_CGEV
   1931         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
   1932 #endif /* WORKAROUND_FAKE_CGEV */
   1933     } else if (strStartsWith(s,"+CREG:")
   1934                 || strStartsWith(s,"+CGREG:")
   1935     ) {
   1936         RIL_onUnsolicitedResponse (
   1937             RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
   1938             NULL, 0);
   1939 #ifdef WORKAROUND_FAKE_CGEV
   1940         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
   1941 #endif /* WORKAROUND_FAKE_CGEV */
   1942     } else if (strStartsWith(s, "+CMT:")) {
   1943         RIL_onUnsolicitedResponse (
   1944             RIL_UNSOL_RESPONSE_NEW_SMS,
   1945             sms_pdu, strlen(sms_pdu));
   1946     } else if (strStartsWith(s, "+CDS:")) {
   1947         RIL_onUnsolicitedResponse (
   1948             RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
   1949             sms_pdu, strlen(sms_pdu));
   1950     } else if (strStartsWith(s, "+CGEV:")) {
   1951         /* Really, we can ignore NW CLASS and ME CLASS events here,
   1952          * but right now we don't since extranous
   1953          * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
   1954          */
   1955         /* can't issue AT commands here -- call on main thread */
   1956         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
   1957 #ifdef WORKAROUND_FAKE_CGEV
   1958     } else if (strStartsWith(s, "+CME ERROR: 150")) {
   1959         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
   1960 #endif /* WORKAROUND_FAKE_CGEV */
   1961     }
   1962 }
   1963 
   1964 /* Called on command or reader thread */
   1965 static void onATReaderClosed()
   1966 {
   1967     LOGI("AT channel closed\n");
   1968     at_close();
   1969     s_closed = 1;
   1970 
   1971     setRadioState (RADIO_STATE_UNAVAILABLE);
   1972 }
   1973 
   1974 /* Called on command thread */
   1975 static void onATTimeout()
   1976 {
   1977     LOGI("AT channel timeout; closing\n");
   1978     at_close();
   1979 
   1980     s_closed = 1;
   1981 
   1982     /* FIXME cause a radio reset here */
   1983 
   1984     setRadioState (RADIO_STATE_UNAVAILABLE);
   1985 }
   1986 
   1987 static void usage(char *s)
   1988 {
   1989 #ifdef RIL_SHLIB
   1990     fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
   1991 #else
   1992     fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
   1993     exit(-1);
   1994 #endif
   1995 }
   1996 
   1997 static void *
   1998 mainLoop(void *param)
   1999 {
   2000     int fd;
   2001     int ret;
   2002 
   2003     AT_DUMP("== ", "entering mainLoop()", -1 );
   2004     at_set_on_reader_closed(onATReaderClosed);
   2005     at_set_on_timeout(onATTimeout);
   2006 
   2007     for (;;) {
   2008         fd = -1;
   2009         while  (fd < 0) {
   2010             if (s_port > 0) {
   2011                 fd = socket_loopback_client(s_port, SOCK_STREAM);
   2012             } else if (s_device_socket) {
   2013                 if (!strcmp(s_device_path, "/dev/socket/qemud")) {
   2014                     /* Qemu-specific control socket */
   2015                     fd = socket_local_client( "qemud",
   2016                                               ANDROID_SOCKET_NAMESPACE_RESERVED,
   2017                                               SOCK_STREAM );
   2018                     if (fd >= 0 ) {
   2019                         char  answer[2];
   2020 
   2021                         if ( write(fd, "gsm", 3) != 3 ||
   2022                              read(fd, answer, 2) != 2 ||
   2023                              memcmp(answer, "OK", 2) != 0)
   2024                         {
   2025                             close(fd);
   2026                             fd = -1;
   2027                         }
   2028                    }
   2029                 }
   2030                 else
   2031                     fd = socket_local_client( s_device_path,
   2032                                             ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
   2033                                             SOCK_STREAM );
   2034             } else if (s_device_path != NULL) {
   2035                 fd = open (s_device_path, O_RDWR);
   2036                 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
   2037                     /* disable echo on serial ports */
   2038                     struct termios  ios;
   2039                     tcgetattr( fd, &ios );
   2040                     ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
   2041                     tcsetattr( fd, TCSANOW, &ios );
   2042                 }
   2043             }
   2044 
   2045             if (fd < 0) {
   2046                 perror ("opening AT interface. retrying...");
   2047                 sleep(10);
   2048                 /* never returns */
   2049             }
   2050         }
   2051 
   2052         s_closed = 0;
   2053         ret = at_open(fd, onUnsolicited);
   2054 
   2055         if (ret < 0) {
   2056             LOGE ("AT error %d on at_open\n", ret);
   2057             return 0;
   2058         }
   2059 
   2060         RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
   2061 
   2062         // Give initializeCallback a chance to dispatched, since
   2063         // we don't presently have a cancellation mechanism
   2064         sleep(1);
   2065 
   2066         waitForClose();
   2067         LOGI("Re-opening after close");
   2068     }
   2069 }
   2070 
   2071 #ifdef RIL_SHLIB
   2072 
   2073 pthread_t s_tid_mainloop;
   2074 
   2075 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
   2076 {
   2077     int ret;
   2078     int fd = -1;
   2079     int opt;
   2080     pthread_attr_t attr;
   2081 
   2082     s_rilenv = env;
   2083 
   2084     while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
   2085         switch (opt) {
   2086             case 'p':
   2087                 s_port = atoi(optarg);
   2088                 if (s_port == 0) {
   2089                     usage(argv[0]);
   2090                     return NULL;
   2091                 }
   2092                 LOGI("Opening loopback port %d\n", s_port);
   2093             break;
   2094 
   2095             case 'd':
   2096                 s_device_path = optarg;
   2097                 LOGI("Opening tty device %s\n", s_device_path);
   2098             break;
   2099 
   2100             case 's':
   2101                 s_device_path   = optarg;
   2102                 s_device_socket = 1;
   2103                 LOGI("Opening socket %s\n", s_device_path);
   2104             break;
   2105 
   2106             default:
   2107                 usage(argv[0]);
   2108                 return NULL;
   2109         }
   2110     }
   2111 
   2112     if (s_port < 0 && s_device_path == NULL) {
   2113         usage(argv[0]);
   2114         return NULL;
   2115     }
   2116 
   2117     pthread_attr_init (&attr);
   2118     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   2119     ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
   2120 
   2121     return &s_callbacks;
   2122 }
   2123 #else /* RIL_SHLIB */
   2124 int main (int argc, char **argv)
   2125 {
   2126     int ret;
   2127     int fd = -1;
   2128     int opt;
   2129 
   2130     while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
   2131         switch (opt) {
   2132             case 'p':
   2133                 s_port = atoi(optarg);
   2134                 if (s_port == 0) {
   2135                     usage(argv[0]);
   2136                 }
   2137                 LOGI("Opening loopback port %d\n", s_port);
   2138             break;
   2139 
   2140             case 'd':
   2141                 s_device_path = optarg;
   2142                 LOGI("Opening tty device %s\n", s_device_path);
   2143             break;
   2144 
   2145             case 's':
   2146                 s_device_path   = optarg;
   2147                 s_device_socket = 1;
   2148                 LOGI("Opening socket %s\n", s_device_path);
   2149             break;
   2150 
   2151             default:
   2152                 usage(argv[0]);
   2153         }
   2154     }
   2155 
   2156     if (s_port < 0 && s_device_path == NULL) {
   2157         usage(argv[0]);
   2158     }
   2159 
   2160     RIL_register(&s_callbacks);
   2161 
   2162     mainLoop(NULL);
   2163 
   2164     return 0;
   2165 }
   2166 
   2167 #endif /* RIL_SHLIB */
   2168