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