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_cdma_sms.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 #include <sys/system_properties.h>
     37 
     38 #include "ril.h"
     39 #include "hardware/qemu_pipe.h"
     40 
     41 #define LOG_TAG "RIL"
     42 #include <utils/Log.h>
     43 
     44 #define MAX_AT_RESPONSE 0x1000
     45 
     46 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
     47 #define PPP_TTY_PATH "eth0"
     48 
     49 #ifdef USE_TI_COMMANDS
     50 
     51 // Enable a workaround
     52 // 1) Make incoming call, do not answer
     53 // 2) Hangup remote end
     54 // Expected: call should disappear from CLCC line
     55 // Actual: Call shows as "ACTIVE" before disappearing
     56 #define WORKAROUND_ERRONEOUS_ANSWER 1
     57 
     58 // Some varients of the TI stack do not support the +CGEV unsolicited
     59 // response. However, they seem to send an unsolicited +CME ERROR: 150
     60 #define WORKAROUND_FAKE_CGEV 1
     61 #endif
     62 
     63 /* Modem Technology bits */
     64 #define MDM_GSM         0x01
     65 #define MDM_WCDMA       0x02
     66 #define MDM_CDMA        0x04
     67 #define MDM_EVDO        0x08
     68 #define MDM_LTE         0x10
     69 
     70 typedef struct {
     71     int supportedTechs; // Bitmask of supported Modem Technology bits
     72     int currentTech;    // Technology the modem is currently using (in the format used by modem)
     73     int isMultimode;
     74 
     75     // Preferred mode bitmask. This is actually 4 byte-sized bitmasks with different priority values,
     76     // in which the byte number from LSB to MSB give the priority.
     77     //
     78     //          |MSB|   |   |LSB
     79     // value:   |00 |00 |00 |00
     80     // byte #:  |3  |2  |1  |0
     81     //
     82     // Higher byte order give higher priority. Thus, a value of 0x0000000f represents
     83     // a preferred mode of GSM, WCDMA, CDMA, and EvDo in which all are equally preferrable, whereas
     84     // 0x00000201 represents a mode with GSM and WCDMA, in which WCDMA is preferred over GSM
     85     int32_t preferredNetworkMode;
     86     int subscription_source;
     87 
     88 } ModemInfo;
     89 
     90 static ModemInfo *sMdmInfo;
     91 // TECH returns the current technology in the format used by the modem.
     92 // It can be used as an l-value
     93 #define TECH(mdminfo)                 ((mdminfo)->currentTech)
     94 // TECH_BIT returns the bitmask equivalent of the current tech
     95 #define TECH_BIT(mdminfo)            (1 << ((mdminfo)->currentTech))
     96 #define IS_MULTIMODE(mdminfo)         ((mdminfo)->isMultimode)
     97 #define TECH_SUPPORTED(mdminfo, tech) ((mdminfo)->supportedTechs & (tech))
     98 #define PREFERRED_NETWORK(mdminfo)    ((mdminfo)->preferredNetworkMode)
     99 // CDMA Subscription Source
    100 #define SSOURCE(mdminfo)              ((mdminfo)->subscription_source)
    101 
    102 static int net2modem[] = {
    103     MDM_GSM | MDM_WCDMA,                                 // 0  - GSM / WCDMA Pref
    104     MDM_GSM,                                             // 1  - GSM only
    105     MDM_WCDMA,                                           // 2  - WCDMA only
    106     MDM_GSM | MDM_WCDMA,                                 // 3  - GSM / WCDMA Auto
    107     MDM_CDMA | MDM_EVDO,                                 // 4  - CDMA / EvDo Auto
    108     MDM_CDMA,                                            // 5  - CDMA only
    109     MDM_EVDO,                                            // 6  - EvDo only
    110     MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO,           // 7  - GSM/WCDMA, CDMA, EvDo
    111     MDM_LTE | MDM_CDMA | MDM_EVDO,                       // 8  - LTE, CDMA and EvDo
    112     MDM_LTE | MDM_GSM | MDM_WCDMA,                       // 9  - LTE, GSM/WCDMA
    113     MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
    114     MDM_LTE,                                             // 11 - LTE only
    115 };
    116 
    117 static int32_t net2pmask[] = {
    118     MDM_GSM | (MDM_WCDMA << 8),                          // 0  - GSM / WCDMA Pref
    119     MDM_GSM,                                             // 1  - GSM only
    120     MDM_WCDMA,                                           // 2  - WCDMA only
    121     MDM_GSM | MDM_WCDMA,                                 // 3  - GSM / WCDMA Auto
    122     MDM_CDMA | MDM_EVDO,                                 // 4  - CDMA / EvDo Auto
    123     MDM_CDMA,                                            // 5  - CDMA only
    124     MDM_EVDO,                                            // 6  - EvDo only
    125     MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO,           // 7  - GSM/WCDMA, CDMA, EvDo
    126     MDM_LTE | MDM_CDMA | MDM_EVDO,                       // 8  - LTE, CDMA and EvDo
    127     MDM_LTE | MDM_GSM | MDM_WCDMA,                       // 9  - LTE, GSM/WCDMA
    128     MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
    129     MDM_LTE,                                             // 11 - LTE only
    130 };
    131 
    132 static int is3gpp2(int radioTech) {
    133     switch (radioTech) {
    134         case RADIO_TECH_IS95A:
    135         case RADIO_TECH_IS95B:
    136         case RADIO_TECH_1xRTT:
    137         case RADIO_TECH_EVDO_0:
    138         case RADIO_TECH_EVDO_A:
    139         case RADIO_TECH_EVDO_B:
    140         case RADIO_TECH_EHRPD:
    141             return 1;
    142         default:
    143             return 0;
    144     }
    145 }
    146 
    147 typedef enum {
    148     SIM_ABSENT = 0,
    149     SIM_NOT_READY = 1,
    150     SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
    151     SIM_PIN = 3,
    152     SIM_PUK = 4,
    153     SIM_NETWORK_PERSONALIZATION = 5,
    154     RUIM_ABSENT = 6,
    155     RUIM_NOT_READY = 7,
    156     RUIM_READY = 8,
    157     RUIM_PIN = 9,
    158     RUIM_PUK = 10,
    159     RUIM_NETWORK_PERSONALIZATION = 11
    160 } SIM_Status;
    161 
    162 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
    163 static RIL_RadioState currentState();
    164 static int onSupports (int requestCode);
    165 static void onCancel (RIL_Token t);
    166 static const char *getVersion();
    167 static int isRadioOn();
    168 static SIM_Status getSIMStatus();
    169 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status);
    170 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status);
    171 static void onDataCallListChanged(void *param);
    172 
    173 extern const char * requestToString(int request);
    174 
    175 /*** Static Variables ***/
    176 static const RIL_RadioFunctions s_callbacks = {
    177     RIL_VERSION,
    178     onRequest,
    179     currentState,
    180     onSupports,
    181     onCancel,
    182     getVersion
    183 };
    184 
    185 #ifdef RIL_SHLIB
    186 static const struct RIL_Env *s_rilenv;
    187 
    188 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
    189 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
    190 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
    191 #endif
    192 
    193 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
    194 
    195 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
    196 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
    197 
    198 static int s_port = -1;
    199 static const char * s_device_path = NULL;
    200 static int          s_device_socket = 0;
    201 
    202 /* trigger change to this with s_state_cond */
    203 static int s_closed = 0;
    204 
    205 static int sFD;     /* file desc of AT channel */
    206 static char sATBuffer[MAX_AT_RESPONSE+1];
    207 static char *sATBufferCur = NULL;
    208 
    209 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
    210 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
    211 static const struct timeval TIMEVAL_0 = {0,0};
    212 
    213 #ifdef WORKAROUND_ERRONEOUS_ANSWER
    214 // Max number of times we'll try to repoll when we think
    215 // we have a AT+CLCC race condition
    216 #define REPOLL_CALLS_COUNT_MAX 4
    217 
    218 // Line index that was incoming or waiting at last poll, or -1 for none
    219 static int s_incomingOrWaitingLine = -1;
    220 // Number of times we've asked for a repoll of AT+CLCC
    221 static int s_repollCallsCount = 0;
    222 // Should we expect a call to be answered in the next CLCC?
    223 static int s_expectAnswer = 0;
    224 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
    225 
    226 static void pollSIMState (void *param);
    227 static void setRadioState(RIL_RadioState newState);
    228 static void setRadioTechnology(ModemInfo *mdm, int newtech);
    229 static int query_ctec(ModemInfo *mdm, int *current, int32_t *preferred);
    230 static int parse_technology_response(const char *response, int *current, int32_t *preferred);
    231 static int techFromModemType(int mdmtype);
    232 
    233 static int clccStateToRILState(int state, RIL_CallState *p_state)
    234 
    235 {
    236     switch(state) {
    237         case 0: *p_state = RIL_CALL_ACTIVE;   return 0;
    238         case 1: *p_state = RIL_CALL_HOLDING;  return 0;
    239         case 2: *p_state = RIL_CALL_DIALING;  return 0;
    240         case 3: *p_state = RIL_CALL_ALERTING; return 0;
    241         case 4: *p_state = RIL_CALL_INCOMING; return 0;
    242         case 5: *p_state = RIL_CALL_WAITING;  return 0;
    243         default: return -1;
    244     }
    245 }
    246 
    247 /**
    248  * Note: directly modified line and has *p_call point directly into
    249  * modified line
    250  */
    251 static int callFromCLCCLine(char *line, RIL_Call *p_call)
    252 {
    253         //+CLCC: 1,0,2,0,0,\"+18005551212\",145
    254         //     index,isMT,state,mode,isMpty(,number,TOA)?
    255 
    256     int err;
    257     int state;
    258     int mode;
    259 
    260     err = at_tok_start(&line);
    261     if (err < 0) goto error;
    262 
    263     err = at_tok_nextint(&line, &(p_call->index));
    264     if (err < 0) goto error;
    265 
    266     err = at_tok_nextbool(&line, &(p_call->isMT));
    267     if (err < 0) goto error;
    268 
    269     err = at_tok_nextint(&line, &state);
    270     if (err < 0) goto error;
    271 
    272     err = clccStateToRILState(state, &(p_call->state));
    273     if (err < 0) goto error;
    274 
    275     err = at_tok_nextint(&line, &mode);
    276     if (err < 0) goto error;
    277 
    278     p_call->isVoice = (mode == 0);
    279 
    280     err = at_tok_nextbool(&line, &(p_call->isMpty));
    281     if (err < 0) goto error;
    282 
    283     if (at_tok_hasmore(&line)) {
    284         err = at_tok_nextstr(&line, &(p_call->number));
    285 
    286         /* tolerate null here */
    287         if (err < 0) return 0;
    288 
    289         // Some lame implementations return strings
    290         // like "NOT AVAILABLE" in the CLCC line
    291         if (p_call->number != NULL
    292             && 0 == strspn(p_call->number, "+0123456789")
    293         ) {
    294             p_call->number = NULL;
    295         }
    296 
    297         err = at_tok_nextint(&line, &p_call->toa);
    298         if (err < 0) goto error;
    299     }
    300 
    301     p_call->uusInfo = NULL;
    302 
    303     return 0;
    304 
    305 error:
    306     ALOGE("invalid CLCC line\n");
    307     return -1;
    308 }
    309 
    310 
    311 /** do post-AT+CFUN=1 initialization */
    312 static void onRadioPowerOn()
    313 {
    314 #ifdef USE_TI_COMMANDS
    315     /*  Must be after CFUN=1 */
    316     /*  TI specific -- notifications for CPHS things such */
    317     /*  as CPHS message waiting indicator */
    318 
    319     at_send_command("AT%CPHS=1", NULL);
    320 
    321     /*  TI specific -- enable NITZ unsol notifs */
    322     at_send_command("AT%CTZV=1", NULL);
    323 #endif
    324 
    325     pollSIMState(NULL);
    326 }
    327 
    328 /** do post- SIM ready initialization */
    329 static void onSIMReady()
    330 {
    331     at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
    332     /*
    333      * Always send SMS messages directly to the TE
    334      *
    335      * mode = 1 // discard when link is reserved (link should never be
    336      *             reserved)
    337      * mt = 2   // most messages routed to TE
    338      * bm = 2   // new cell BM's routed to TE
    339      * ds = 1   // Status reports routed to TE
    340      * bfr = 1  // flush buffer
    341      */
    342     at_send_command("AT+CNMI=1,2,2,1,1", NULL);
    343 }
    344 
    345 static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
    346 {
    347     int onOff;
    348 
    349     int err;
    350     ATResponse *p_response = NULL;
    351 
    352     assert (datalen >= sizeof(int *));
    353     onOff = ((int *)data)[0];
    354 
    355     if (onOff == 0 && sState != RADIO_STATE_OFF) {
    356         err = at_send_command("AT+CFUN=0", &p_response);
    357        if (err < 0 || p_response->success == 0) goto error;
    358         setRadioState(RADIO_STATE_OFF);
    359     } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
    360         err = at_send_command("AT+CFUN=1", &p_response);
    361         if (err < 0|| p_response->success == 0) {
    362             // Some stacks return an error when there is no SIM,
    363             // but they really turn the RF portion on
    364             // So, if we get an error, let's check to see if it
    365             // turned on anyway
    366 
    367             if (isRadioOn() != 1) {
    368                 goto error;
    369             }
    370         }
    371         setRadioState(RADIO_STATE_ON);
    372     }
    373 
    374     at_response_free(p_response);
    375     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
    376     return;
    377 error:
    378     at_response_free(p_response);
    379     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    380 }
    381 
    382 static void requestOrSendDataCallList(RIL_Token *t);
    383 
    384 static void onDataCallListChanged(void *param)
    385 {
    386     requestOrSendDataCallList(NULL);
    387 }
    388 
    389 static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
    390 {
    391     requestOrSendDataCallList(&t);
    392 }
    393 
    394 static void requestOrSendDataCallList(RIL_Token *t)
    395 {
    396     ATResponse *p_response;
    397     ATLine *p_cur;
    398     int err;
    399     int n = 0;
    400     char *out;
    401 
    402     err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
    403     if (err != 0 || p_response->success == 0) {
    404         if (t != NULL)
    405             RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
    406         else
    407             RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
    408                                       NULL, 0);
    409         return;
    410     }
    411 
    412     for (p_cur = p_response->p_intermediates; p_cur != NULL;
    413          p_cur = p_cur->p_next)
    414         n++;
    415 
    416     RIL_Data_Call_Response_v6 *responses =
    417         alloca(n * sizeof(RIL_Data_Call_Response_v6));
    418 
    419     int i;
    420     for (i = 0; i < n; i++) {
    421         responses[i].status = -1;
    422         responses[i].suggestedRetryTime = -1;
    423         responses[i].cid = -1;
    424         responses[i].active = -1;
    425         responses[i].type = "";
    426         responses[i].ifname = "";
    427         responses[i].addresses = "";
    428         responses[i].dnses = "";
    429         responses[i].gateways = "";
    430     }
    431 
    432     RIL_Data_Call_Response_v6 *response = responses;
    433     for (p_cur = p_response->p_intermediates; p_cur != NULL;
    434          p_cur = p_cur->p_next) {
    435         char *line = p_cur->line;
    436 
    437         err = at_tok_start(&line);
    438         if (err < 0)
    439             goto error;
    440 
    441         err = at_tok_nextint(&line, &response->cid);
    442         if (err < 0)
    443             goto error;
    444 
    445         err = at_tok_nextint(&line, &response->active);
    446         if (err < 0)
    447             goto error;
    448 
    449         response++;
    450     }
    451 
    452     at_response_free(p_response);
    453 
    454     err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
    455     if (err != 0 || p_response->success == 0) {
    456         if (t != NULL)
    457             RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
    458         else
    459             RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
    460                                       NULL, 0);
    461         return;
    462     }
    463 
    464     for (p_cur = p_response->p_intermediates; p_cur != NULL;
    465          p_cur = p_cur->p_next) {
    466         char *line = p_cur->line;
    467         int cid;
    468 
    469         err = at_tok_start(&line);
    470         if (err < 0)
    471             goto error;
    472 
    473         err = at_tok_nextint(&line, &cid);
    474         if (err < 0)
    475             goto error;
    476 
    477         for (i = 0; i < n; i++) {
    478             if (responses[i].cid == cid)
    479                 break;
    480         }
    481 
    482         if (i >= n) {
    483             /* details for a context we didn't hear about in the last request */
    484             continue;
    485         }
    486 
    487         // Assume no error
    488         responses[i].status = 0;
    489 
    490         // type
    491         err = at_tok_nextstr(&line, &out);
    492         if (err < 0)
    493             goto error;
    494         responses[i].type = alloca(strlen(out) + 1);
    495         strcpy(responses[i].type, out);
    496 
    497         // APN ignored for v5
    498         err = at_tok_nextstr(&line, &out);
    499         if (err < 0)
    500             goto error;
    501 
    502         responses[i].ifname = alloca(strlen(PPP_TTY_PATH) + 1);
    503         strcpy(responses[i].ifname, PPP_TTY_PATH);
    504 
    505         err = at_tok_nextstr(&line, &out);
    506         if (err < 0)
    507             goto error;
    508 
    509         responses[i].addresses = alloca(strlen(out) + 1);
    510         strcpy(responses[i].addresses, out);
    511 
    512         {
    513             char  propValue[PROP_VALUE_MAX];
    514 
    515             if (__system_property_get("ro.kernel.qemu", propValue) != 0) {
    516                 /* We are in the emulator - the dns servers are listed
    517                  * by the following system properties, setup in
    518                  * /system/etc/init.goldfish.sh:
    519                  *  - net.eth0.dns1
    520                  *  - net.eth0.dns2
    521                  *  - net.eth0.dns3
    522                  *  - net.eth0.dns4
    523                  */
    524                 const int   dnslist_sz = 128;
    525                 char*       dnslist = alloca(dnslist_sz);
    526                 const char* separator = "";
    527                 int         nn;
    528 
    529                 dnslist[0] = 0;
    530                 for (nn = 1; nn <= 4; nn++) {
    531                     /* Probe net.eth0.dns<n> */
    532                     char  propName[PROP_NAME_MAX];
    533                     snprintf(propName, sizeof propName, "net.eth0.dns%d", nn);
    534 
    535                     /* Ignore if undefined */
    536                     if (__system_property_get(propName, propValue) == 0) {
    537                         continue;
    538                     }
    539 
    540                     /* Append the DNS IP address */
    541                     strlcat(dnslist, separator, dnslist_sz);
    542                     strlcat(dnslist, propValue, dnslist_sz);
    543                     separator = " ";
    544                 }
    545                 responses[i].dnses = dnslist;
    546 
    547                 /* There is only on gateway in the emulator */
    548                 responses[i].gateways = "10.0.2.2";
    549             }
    550             else {
    551                 /* I don't know where we are, so use the public Google DNS
    552                  * servers by default and no gateway.
    553                  */
    554                 responses[i].dnses = "8.8.8.8 8.8.4.4";
    555                 responses[i].gateways = "";
    556             }
    557         }
    558     }
    559 
    560     at_response_free(p_response);
    561 
    562     if (t != NULL)
    563         RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
    564                               n * sizeof(RIL_Data_Call_Response_v6));
    565     else
    566         RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
    567                                   responses,
    568                                   n * sizeof(RIL_Data_Call_Response_v6));
    569 
    570     return;
    571 
    572 error:
    573     if (t != NULL)
    574         RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
    575     else
    576         RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
    577                                   NULL, 0);
    578 
    579     at_response_free(p_response);
    580 }
    581 
    582 static void requestQueryNetworkSelectionMode(
    583                 void *data, size_t datalen, RIL_Token t)
    584 {
    585     int err;
    586     ATResponse *p_response = NULL;
    587     int response = 0;
    588     char *line;
    589 
    590     err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
    591 
    592     if (err < 0 || p_response->success == 0) {
    593         goto error;
    594     }
    595 
    596     line = p_response->p_intermediates->line;
    597 
    598     err = at_tok_start(&line);
    599 
    600     if (err < 0) {
    601         goto error;
    602     }
    603 
    604     err = at_tok_nextint(&line, &response);
    605 
    606     if (err < 0) {
    607         goto error;
    608     }
    609 
    610     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
    611     at_response_free(p_response);
    612     return;
    613 error:
    614     at_response_free(p_response);
    615     ALOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
    616     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    617 }
    618 
    619 static void sendCallStateChanged(void *param)
    620 {
    621     RIL_onUnsolicitedResponse (
    622         RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
    623         NULL, 0);
    624 }
    625 
    626 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
    627 {
    628     int err;
    629     ATResponse *p_response;
    630     ATLine *p_cur;
    631     int countCalls;
    632     int countValidCalls;
    633     RIL_Call *p_calls;
    634     RIL_Call **pp_calls;
    635     int i;
    636     int needRepoll = 0;
    637 
    638 #ifdef WORKAROUND_ERRONEOUS_ANSWER
    639     int prevIncomingOrWaitingLine;
    640 
    641     prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
    642     s_incomingOrWaitingLine = -1;
    643 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
    644 
    645     err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
    646 
    647     if (err != 0 || p_response->success == 0) {
    648         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    649         return;
    650     }
    651 
    652     /* count the calls */
    653     for (countCalls = 0, p_cur = p_response->p_intermediates
    654             ; p_cur != NULL
    655             ; p_cur = p_cur->p_next
    656     ) {
    657         countCalls++;
    658     }
    659 
    660     /* yes, there's an array of pointers and then an array of structures */
    661 
    662     pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
    663     p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
    664     memset (p_calls, 0, countCalls * sizeof(RIL_Call));
    665 
    666     /* init the pointer array */
    667     for(i = 0; i < countCalls ; i++) {
    668         pp_calls[i] = &(p_calls[i]);
    669     }
    670 
    671     for (countValidCalls = 0, p_cur = p_response->p_intermediates
    672             ; p_cur != NULL
    673             ; p_cur = p_cur->p_next
    674     ) {
    675         err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
    676 
    677         if (err != 0) {
    678             continue;
    679         }
    680 
    681 #ifdef WORKAROUND_ERRONEOUS_ANSWER
    682         if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
    683             || p_calls[countValidCalls].state == RIL_CALL_WAITING
    684         ) {
    685             s_incomingOrWaitingLine = p_calls[countValidCalls].index;
    686         }
    687 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
    688 
    689         if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
    690             && p_calls[countValidCalls].state != RIL_CALL_HOLDING
    691         ) {
    692             needRepoll = 1;
    693         }
    694 
    695         countValidCalls++;
    696     }
    697 
    698 #ifdef WORKAROUND_ERRONEOUS_ANSWER
    699     // Basically:
    700     // A call was incoming or waiting
    701     // Now it's marked as active
    702     // But we never answered it
    703     //
    704     // This is probably a bug, and the call will probably
    705     // disappear from the call list in the next poll
    706     if (prevIncomingOrWaitingLine >= 0
    707             && s_incomingOrWaitingLine < 0
    708             && s_expectAnswer == 0
    709     ) {
    710         for (i = 0; i < countValidCalls ; i++) {
    711 
    712             if (p_calls[i].index == prevIncomingOrWaitingLine
    713                     && p_calls[i].state == RIL_CALL_ACTIVE
    714                     && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
    715             ) {
    716                 ALOGI(
    717                     "Hit WORKAROUND_ERRONOUS_ANSWER case."
    718                     " Repoll count: %d\n", s_repollCallsCount);
    719                 s_repollCallsCount++;
    720                 goto error;
    721             }
    722         }
    723     }
    724 
    725     s_expectAnswer = 0;
    726     s_repollCallsCount = 0;
    727 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
    728 
    729     RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
    730             countValidCalls * sizeof (RIL_Call *));
    731 
    732     at_response_free(p_response);
    733 
    734 #ifdef POLL_CALL_STATE
    735     if (countValidCalls) {  // We don't seem to get a "NO CARRIER" message from
    736                             // smd, so we're forced to poll until the call ends.
    737 #else
    738     if (needRepoll) {
    739 #endif
    740         RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
    741     }
    742 
    743     return;
    744 error:
    745     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    746     at_response_free(p_response);
    747 }
    748 
    749 static void requestDial(void *data, size_t datalen, RIL_Token t)
    750 {
    751     RIL_Dial *p_dial;
    752     char *cmd;
    753     const char *clir;
    754     int ret;
    755 
    756     p_dial = (RIL_Dial *)data;
    757 
    758     switch (p_dial->clir) {
    759         case 1: clir = "I"; break;  /*invocation*/
    760         case 2: clir = "i"; break;  /*suppression*/
    761         default:
    762         case 0: clir = ""; break;   /*subscription default*/
    763     }
    764 
    765     asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
    766 
    767     ret = at_send_command(cmd, NULL);
    768 
    769     free(cmd);
    770 
    771     /* success or failure is ignored by the upper layer here.
    772        it will call GET_CURRENT_CALLS and determine success that way */
    773     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
    774 }
    775 
    776 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
    777 {
    778     RIL_SMS_WriteArgs *p_args;
    779     char *cmd;
    780     int length;
    781     int err;
    782     ATResponse *p_response = NULL;
    783 
    784     p_args = (RIL_SMS_WriteArgs *)data;
    785 
    786     length = strlen(p_args->pdu)/2;
    787     asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
    788 
    789     err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
    790 
    791     if (err != 0 || p_response->success == 0) goto error;
    792 
    793     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
    794     at_response_free(p_response);
    795 
    796     return;
    797 error:
    798     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    799     at_response_free(p_response);
    800 }
    801 
    802 static void requestHangup(void *data, size_t datalen, RIL_Token t)
    803 {
    804     int *p_line;
    805 
    806     int ret;
    807     char *cmd;
    808 
    809     p_line = (int *)data;
    810 
    811     // 3GPP 22.030 6.5.5
    812     // "Releases a specific active call X"
    813     asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
    814 
    815     ret = at_send_command(cmd, NULL);
    816 
    817     free(cmd);
    818 
    819     /* success or failure is ignored by the upper layer here.
    820        it will call GET_CURRENT_CALLS and determine success that way */
    821     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
    822 }
    823 
    824 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
    825 {
    826     ATResponse *p_response = NULL;
    827     int err;
    828     char *line;
    829     int count =0;
    830     int numofElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
    831     int response[numofElements];
    832 
    833     err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
    834 
    835     if (err < 0 || p_response->success == 0) {
    836         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    837         goto error;
    838     }
    839 
    840     line = p_response->p_intermediates->line;
    841 
    842     err = at_tok_start(&line);
    843     if (err < 0) goto error;
    844 
    845     for (count =0; count < numofElements; count ++) {
    846         err = at_tok_nextint(&line, &(response[count]));
    847         if (err < 0) goto error;
    848     }
    849 
    850     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
    851 
    852     at_response_free(p_response);
    853     return;
    854 
    855 error:
    856     ALOGE("requestSignalStrength must never return an error when radio is on");
    857     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    858     at_response_free(p_response);
    859 }
    860 
    861 /**
    862  * networkModePossible. Decides whether the network mode is appropriate for the
    863  * specified modem
    864  */
    865 static int networkModePossible(ModemInfo *mdm, int nm)
    866 {
    867     if ((net2modem[nm] & mdm->supportedTechs) == net2modem[nm]) {
    868        return 1;
    869     }
    870     return 0;
    871 }
    872 static void requestSetPreferredNetworkType( int request, void *data,
    873                                             size_t datalen, RIL_Token t )
    874 {
    875     ATResponse *p_response = NULL;
    876     char *cmd = NULL;
    877     int value = *(int *)data;
    878     int current, old;
    879     int err;
    880     int32_t preferred = net2pmask[value];
    881 
    882     ALOGD("requestSetPreferredNetworkType: current: %x. New: %x", PREFERRED_NETWORK(sMdmInfo), preferred);
    883     if (!networkModePossible(sMdmInfo, value)) {
    884         RIL_onRequestComplete(t, RIL_E_MODE_NOT_SUPPORTED, NULL, 0);
    885         return;
    886     }
    887     if (query_ctec(sMdmInfo, &current, NULL) < 0) {
    888         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    889         return;
    890     }
    891     old = PREFERRED_NETWORK(sMdmInfo);
    892     ALOGD("old != preferred: %d", old != preferred);
    893     if (old != preferred) {
    894         asprintf(&cmd, "AT+CTEC=%d,\"%x\"", current, preferred);
    895         ALOGD("Sending command: <%s>", cmd);
    896         err = at_send_command_singleline(cmd, "+CTEC:", &p_response);
    897         free(cmd);
    898         if (err || !p_response->success) {
    899             RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    900             return;
    901         }
    902         PREFERRED_NETWORK(sMdmInfo) = value;
    903         if (!strstr( p_response->p_intermediates->line, "DONE") ) {
    904             int current;
    905             int res = parse_technology_response(p_response->p_intermediates->line, &current, NULL);
    906             switch (res) {
    907                 case -1: // Error or unable to parse
    908                     break;
    909                 case 1: // Only able to parse current
    910                 case 0: // Both current and preferred were parsed
    911                     setRadioTechnology(sMdmInfo, current);
    912                     break;
    913             }
    914         }
    915     }
    916     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
    917 }
    918 
    919 static void requestGetPreferredNetworkType(int request, void *data,
    920                                    size_t datalen, RIL_Token t)
    921 {
    922     int preferred;
    923     unsigned i;
    924 
    925     switch ( query_ctec(sMdmInfo, NULL, &preferred) ) {
    926         case -1: // Error or unable to parse
    927         case 1: // Only able to parse current
    928             RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    929             break;
    930         case 0: // Both current and preferred were parsed
    931             for ( i = 0 ; i < sizeof(net2pmask) / sizeof(int32_t) ; i++ ) {
    932                 if (preferred == net2pmask[i]) {
    933                     RIL_onRequestComplete(t, RIL_E_SUCCESS, &i, sizeof(int));
    934                     return;
    935                 }
    936             }
    937             ALOGE("Unknown preferred mode received from modem: %d", preferred);
    938             RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    939             break;
    940     }
    941 
    942 }
    943 
    944 static void requestCdmaPrlVersion(int request, void *data,
    945                                    size_t datalen, RIL_Token t)
    946 {
    947     int err;
    948     char * responseStr;
    949     ATResponse *p_response = NULL;
    950     const char *cmd;
    951     char *line;
    952 
    953     err = at_send_command_singleline("AT+WPRL?", "+WPRL:", &p_response);
    954     if (err < 0 || !p_response->success) goto error;
    955     line = p_response->p_intermediates->line;
    956     err = at_tok_start(&line);
    957     if (err < 0) goto error;
    958     err = at_tok_nextstr(&line, &responseStr);
    959     if (err < 0 || !responseStr) goto error;
    960     RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, strlen(responseStr));
    961     at_response_free(p_response);
    962     return;
    963 error:
    964     at_response_free(p_response);
    965     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    966 }
    967 
    968 static void requestCdmaBaseBandVersion(int request, void *data,
    969                                    size_t datalen, RIL_Token t)
    970 {
    971     int err;
    972     char * responseStr;
    973     ATResponse *p_response = NULL;
    974     const char *cmd;
    975     const char *prefix;
    976     char *line, *p;
    977     int commas;
    978     int skip;
    979     int count = 4;
    980 
    981     // Fixed values. TODO: query modem
    982     responseStr = strdup("1.0.0.0");
    983     RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, sizeof(responseStr));
    984     free(responseStr);
    985 }
    986 
    987 static void requestCdmaDeviceIdentity(int request, void *data,
    988                                         size_t datalen, RIL_Token t)
    989 {
    990     int err;
    991     int response[4];
    992     char * responseStr[4];
    993     ATResponse *p_response = NULL;
    994     const char *cmd;
    995     const char *prefix;
    996     char *line, *p;
    997     int commas;
    998     int skip;
    999     int count = 4;
   1000 
   1001     // Fixed values. TODO: Query modem
   1002     responseStr[0] = "----";
   1003     responseStr[1] = "----";
   1004     responseStr[2] = "77777777";
   1005 
   1006     err = at_send_command_numeric("AT+CGSN", &p_response);
   1007     if (err < 0 || p_response->success == 0) {
   1008         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1009         return;
   1010     } else {
   1011         responseStr[3] = p_response->p_intermediates->line;
   1012     }
   1013 
   1014     RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
   1015     at_response_free(p_response);
   1016 
   1017     return;
   1018 error:
   1019     ALOGE("requestCdmaDeviceIdentity must never return an error when radio is on");
   1020     at_response_free(p_response);
   1021     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1022 }
   1023 
   1024 static void requestCdmaGetSubscriptionSource(int request, void *data,
   1025                                         size_t datalen, RIL_Token t)
   1026 {
   1027     int err;
   1028     int *ss = (int *)data;
   1029     ATResponse *p_response = NULL;
   1030     char *cmd = NULL;
   1031     char *line = NULL;
   1032     int response;
   1033 
   1034     asprintf(&cmd, "AT+CCSS?");
   1035     if (!cmd) goto error;
   1036 
   1037     err = at_send_command_singleline(cmd, "+CCSS:", &p_response);
   1038     if (err < 0 || !p_response->success)
   1039         goto error;
   1040 
   1041     line = p_response->p_intermediates->line;
   1042     err = at_tok_start(&line);
   1043     if (err < 0) goto error;
   1044 
   1045     err = at_tok_nextint(&line, &response);
   1046     free(cmd);
   1047     cmd = NULL;
   1048 
   1049     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
   1050 
   1051     return;
   1052 error:
   1053     free(cmd);
   1054     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1055 }
   1056 
   1057 static void requestCdmaSetSubscriptionSource(int request, void *data,
   1058                                         size_t datalen, RIL_Token t)
   1059 {
   1060     int err;
   1061     int *ss = (int *)data;
   1062     ATResponse *p_response = NULL;
   1063     char *cmd = NULL;
   1064 
   1065     if (!ss || !datalen) {
   1066         ALOGE("RIL_REQUEST_CDMA_SET_SUBSCRIPTION without data!");
   1067         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1068         return;
   1069     }
   1070     asprintf(&cmd, "AT+CCSS=%d", ss[0]);
   1071     if (!cmd) goto error;
   1072 
   1073     err = at_send_command(cmd, &p_response);
   1074     if (err < 0 || !p_response->success)
   1075         goto error;
   1076     free(cmd);
   1077     cmd = NULL;
   1078 
   1079     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1080 
   1081     RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, ss, sizeof(ss[0]));
   1082 
   1083     return;
   1084 error:
   1085     free(cmd);
   1086     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1087 }
   1088 
   1089 static void requestCdmaSubscription(int request, void *data,
   1090                                         size_t datalen, RIL_Token t)
   1091 {
   1092     int err;
   1093     int response[5];
   1094     char * responseStr[5];
   1095     ATResponse *p_response = NULL;
   1096     const char *cmd;
   1097     const char *prefix;
   1098     char *line, *p;
   1099     int commas;
   1100     int skip;
   1101     int count = 5;
   1102 
   1103     // Fixed values. TODO: Query modem
   1104     responseStr[0] = "8587777777"; // MDN
   1105     responseStr[1] = "1"; // SID
   1106     responseStr[2] = "1"; // NID
   1107     responseStr[3] = "8587777777"; // MIN
   1108     responseStr[4] = "1"; // PRL Version
   1109     RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
   1110 
   1111     return;
   1112 error:
   1113     ALOGE("requestRegistrationState must never return an error when radio is on");
   1114     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1115 }
   1116 
   1117 static void requestCdmaGetRoamingPreference(int request, void *data,
   1118                                                  size_t datalen, RIL_Token t)
   1119 {
   1120     int roaming_pref = -1;
   1121     ATResponse *p_response = NULL;
   1122     char *line;
   1123     int res;
   1124 
   1125     res = at_send_command_singleline("AT+WRMP?", "+WRMP:", &p_response);
   1126     if (res < 0 || !p_response->success) {
   1127         goto error;
   1128     }
   1129     line = p_response->p_intermediates->line;
   1130 
   1131     res = at_tok_start(&line);
   1132     if (res < 0) goto error;
   1133 
   1134     res = at_tok_nextint(&line, &roaming_pref);
   1135     if (res < 0) goto error;
   1136 
   1137      RIL_onRequestComplete(t, RIL_E_SUCCESS, &roaming_pref, sizeof(roaming_pref));
   1138     return;
   1139 error:
   1140     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1141 }
   1142 
   1143 static void requestCdmaSetRoamingPreference(int request, void *data,
   1144                                                  size_t datalen, RIL_Token t)
   1145 {
   1146     int *pref = (int *)data;
   1147     ATResponse *p_response = NULL;
   1148     char *line;
   1149     int res;
   1150     char *cmd = NULL;
   1151 
   1152     asprintf(&cmd, "AT+WRMP=%d", *pref);
   1153     if (cmd == NULL) goto error;
   1154 
   1155     res = at_send_command(cmd, &p_response);
   1156     if (res < 0 || !p_response->success)
   1157         goto error;
   1158 
   1159     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1160     free(cmd);
   1161     return;
   1162 error:
   1163     free(cmd);
   1164     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1165 }
   1166 
   1167 static int parseRegistrationState(char *str, int *type, int *items, int **response)
   1168 {
   1169     int err;
   1170     char *line = str, *p;
   1171     int *resp = NULL;
   1172     int skip;
   1173     int count = 3;
   1174     int commas;
   1175 
   1176     ALOGD("parseRegistrationState. Parsing: %s",str);
   1177     err = at_tok_start(&line);
   1178     if (err < 0) goto error;
   1179 
   1180     /* Ok you have to be careful here
   1181      * The solicited version of the CREG response is
   1182      * +CREG: n, stat, [lac, cid]
   1183      * and the unsolicited version is
   1184      * +CREG: stat, [lac, cid]
   1185      * The <n> parameter is basically "is unsolicited creg on?"
   1186      * which it should always be
   1187      *
   1188      * Now we should normally get the solicited version here,
   1189      * but the unsolicited version could have snuck in
   1190      * so we have to handle both
   1191      *
   1192      * Also since the LAC and CID are only reported when registered,
   1193      * we can have 1, 2, 3, or 4 arguments here
   1194      *
   1195      * finally, a +CGREG: answer may have a fifth value that corresponds
   1196      * to the network type, as in;
   1197      *
   1198      *   +CGREG: n, stat [,lac, cid [,networkType]]
   1199      */
   1200 
   1201     /* count number of commas */
   1202     commas = 0;
   1203     for (p = line ; *p != '\0' ;p++) {
   1204         if (*p == ',') commas++;
   1205     }
   1206 
   1207     resp = (int *)calloc(commas + 1, sizeof(int));
   1208     if (!resp) goto error;
   1209     switch (commas) {
   1210         case 0: /* +CREG: <stat> */
   1211             err = at_tok_nextint(&line, &resp[0]);
   1212             if (err < 0) goto error;
   1213             resp[1] = -1;
   1214             resp[2] = -1;
   1215         break;
   1216 
   1217         case 1: /* +CREG: <n>, <stat> */
   1218             err = at_tok_nextint(&line, &skip);
   1219             if (err < 0) goto error;
   1220             err = at_tok_nextint(&line, &resp[0]);
   1221             if (err < 0) goto error;
   1222             resp[1] = -1;
   1223             resp[2] = -1;
   1224             if (err < 0) goto error;
   1225         break;
   1226 
   1227         case 2: /* +CREG: <stat>, <lac>, <cid> */
   1228             err = at_tok_nextint(&line, &resp[0]);
   1229             if (err < 0) goto error;
   1230             err = at_tok_nexthexint(&line, &resp[1]);
   1231             if (err < 0) goto error;
   1232             err = at_tok_nexthexint(&line, &resp[2]);
   1233             if (err < 0) goto error;
   1234         break;
   1235         case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
   1236             err = at_tok_nextint(&line, &skip);
   1237             if (err < 0) goto error;
   1238             err = at_tok_nextint(&line, &resp[0]);
   1239             if (err < 0) goto error;
   1240             err = at_tok_nexthexint(&line, &resp[1]);
   1241             if (err < 0) goto error;
   1242             err = at_tok_nexthexint(&line, &resp[2]);
   1243             if (err < 0) goto error;
   1244         break;
   1245         /* special case for CGREG, there is a fourth parameter
   1246          * that is the network type (unknown/gprs/edge/umts)
   1247          */
   1248         case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
   1249             err = at_tok_nextint(&line, &skip);
   1250             if (err < 0) goto error;
   1251             err = at_tok_nextint(&line, &resp[0]);
   1252             if (err < 0) goto error;
   1253             err = at_tok_nexthexint(&line, &resp[1]);
   1254             if (err < 0) goto error;
   1255             err = at_tok_nexthexint(&line, &resp[2]);
   1256             if (err < 0) goto error;
   1257             err = at_tok_nexthexint(&line, &resp[3]);
   1258             if (err < 0) goto error;
   1259             count = 4;
   1260         break;
   1261         default:
   1262             goto error;
   1263     }
   1264     if (response)
   1265         *response = resp;
   1266     if (items)
   1267         *items = commas + 1;
   1268     if (type)
   1269         *type = techFromModemType(TECH(sMdmInfo));
   1270     return 0;
   1271 error:
   1272     free(resp);
   1273     return -1;
   1274 }
   1275 
   1276 #define REG_STATE_LEN 15
   1277 #define REG_DATA_STATE_LEN 6
   1278 static void requestRegistrationState(int request, void *data,
   1279                                         size_t datalen, RIL_Token t)
   1280 {
   1281     int err;
   1282     int *registration;
   1283     char **responseStr = NULL;
   1284     ATResponse *p_response = NULL;
   1285     const char *cmd;
   1286     const char *prefix;
   1287     char *line;
   1288     int i = 0, j, numElements = 0;
   1289     int count = 3;
   1290     int type, startfrom;
   1291 
   1292     ALOGD("requestRegistrationState");
   1293     if (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
   1294         cmd = "AT+CREG?";
   1295         prefix = "+CREG:";
   1296         numElements = REG_STATE_LEN;
   1297     } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
   1298         cmd = "AT+CGREG?";
   1299         prefix = "+CGREG:";
   1300         numElements = REG_DATA_STATE_LEN;
   1301     } else {
   1302         assert(0);
   1303         goto error;
   1304     }
   1305 
   1306     err = at_send_command_singleline(cmd, prefix, &p_response);
   1307 
   1308     if (err != 0) goto error;
   1309 
   1310     line = p_response->p_intermediates->line;
   1311 
   1312     if (parseRegistrationState(line, &type, &count, &registration)) goto error;
   1313 
   1314     responseStr = malloc(numElements * sizeof(char *));
   1315     if (!responseStr) goto error;
   1316     memset(responseStr, 0, numElements * sizeof(char *));
   1317     /**
   1318      * The first '4' bytes for both registration states remain the same.
   1319      * But if the request is 'DATA_REGISTRATION_STATE',
   1320      * the 5th and 6th byte(s) are optional.
   1321      */
   1322     if (is3gpp2(type) == 1) {
   1323         ALOGD("registration state type: 3GPP2");
   1324         // TODO: Query modem
   1325         startfrom = 3;
   1326         if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
   1327             asprintf(&responseStr[3], "8");     // EvDo revA
   1328             asprintf(&responseStr[4], "1");     // BSID
   1329             asprintf(&responseStr[5], "123");   // Latitude
   1330             asprintf(&responseStr[6], "222");   // Longitude
   1331             asprintf(&responseStr[7], "0");     // CSS Indicator
   1332             asprintf(&responseStr[8], "4");     // SID
   1333             asprintf(&responseStr[9], "65535"); // NID
   1334             asprintf(&responseStr[10], "0");    // Roaming indicator
   1335             asprintf(&responseStr[11], "1");    // System is in PRL
   1336             asprintf(&responseStr[12], "0");    // Default Roaming indicator
   1337             asprintf(&responseStr[13], "0");    // Reason for denial
   1338             asprintf(&responseStr[14], "0");    // Primary Scrambling Code of Current cell
   1339       } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
   1340             asprintf(&responseStr[3], "8");   // Available data radio technology
   1341       }
   1342     } else { // type == RADIO_TECH_3GPP
   1343         ALOGD("registration state type: 3GPP");
   1344         startfrom = 0;
   1345         asprintf(&responseStr[1], "%x", registration[1]);
   1346         asprintf(&responseStr[2], "%x", registration[2]);
   1347         if (count > 3)
   1348             asprintf(&responseStr[3], "%d", registration[3]);
   1349     }
   1350     asprintf(&responseStr[0], "%d", registration[0]);
   1351 
   1352     /**
   1353      * Optional bytes for DATA_REGISTRATION_STATE request
   1354      * 4th byte : Registration denial code
   1355      * 5th byte : The max. number of simultaneous Data Calls
   1356      */
   1357     if(request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
   1358         // asprintf(&responseStr[4], "3");
   1359         // asprintf(&responseStr[5], "1");
   1360     }
   1361 
   1362     for (j = startfrom; j < numElements; j++) {
   1363         if (!responseStr[i]) goto error;
   1364     }
   1365     free(registration);
   1366     registration = NULL;
   1367 
   1368     RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, numElements*sizeof(responseStr));
   1369     for (j = 0; j < numElements; j++ ) {
   1370         free(responseStr[j]);
   1371         responseStr[j] = NULL;
   1372     }
   1373     free(responseStr);
   1374     responseStr = NULL;
   1375     at_response_free(p_response);
   1376 
   1377     return;
   1378 error:
   1379     if (responseStr) {
   1380         for (j = 0; j < numElements; j++) {
   1381             free(responseStr[j]);
   1382             responseStr[j] = NULL;
   1383         }
   1384         free(responseStr);
   1385         responseStr = NULL;
   1386     }
   1387     ALOGE("requestRegistrationState must never return an error when radio is on");
   1388     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1389     at_response_free(p_response);
   1390 }
   1391 
   1392 static void requestOperator(void *data, size_t datalen, RIL_Token t)
   1393 {
   1394     int err;
   1395     int i;
   1396     int skip;
   1397     ATLine *p_cur;
   1398     char *response[3];
   1399 
   1400     memset(response, 0, sizeof(response));
   1401 
   1402     ATResponse *p_response = NULL;
   1403 
   1404     err = at_send_command_multiline(
   1405         "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
   1406         "+COPS:", &p_response);
   1407 
   1408     /* we expect 3 lines here:
   1409      * +COPS: 0,0,"T - Mobile"
   1410      * +COPS: 0,1,"TMO"
   1411      * +COPS: 0,2,"310170"
   1412      */
   1413 
   1414     if (err != 0) goto error;
   1415 
   1416     for (i = 0, p_cur = p_response->p_intermediates
   1417             ; p_cur != NULL
   1418             ; p_cur = p_cur->p_next, i++
   1419     ) {
   1420         char *line = p_cur->line;
   1421 
   1422         err = at_tok_start(&line);
   1423         if (err < 0) goto error;
   1424 
   1425         err = at_tok_nextint(&line, &skip);
   1426         if (err < 0) goto error;
   1427 
   1428         // If we're unregistered, we may just get
   1429         // a "+COPS: 0" response
   1430         if (!at_tok_hasmore(&line)) {
   1431             response[i] = NULL;
   1432             continue;
   1433         }
   1434 
   1435         err = at_tok_nextint(&line, &skip);
   1436         if (err < 0) goto error;
   1437 
   1438         // a "+COPS: 0, n" response is also possible
   1439         if (!at_tok_hasmore(&line)) {
   1440             response[i] = NULL;
   1441             continue;
   1442         }
   1443 
   1444         err = at_tok_nextstr(&line, &(response[i]));
   1445         if (err < 0) goto error;
   1446     }
   1447 
   1448     if (i != 3) {
   1449         /* expect 3 lines exactly */
   1450         goto error;
   1451     }
   1452 
   1453     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
   1454     at_response_free(p_response);
   1455 
   1456     return;
   1457 error:
   1458     ALOGE("requestOperator must not return error when radio is on");
   1459     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1460     at_response_free(p_response);
   1461 }
   1462 
   1463 static void requestCdmaSendSMS(void *data, size_t datalen, RIL_Token t)
   1464 {
   1465     int err = 1; // Set to go to error:
   1466     RIL_SMS_Response response;
   1467     RIL_CDMA_SMS_Message* rcsm;
   1468 
   1469     ALOGD("requestCdmaSendSMS datalen=%d, sizeof(RIL_CDMA_SMS_Message)=%d",
   1470             datalen, sizeof(RIL_CDMA_SMS_Message));
   1471 
   1472     // verify data content to test marshalling/unmarshalling:
   1473     rcsm = (RIL_CDMA_SMS_Message*)data;
   1474     ALOGD("TeleserviceID=%d, bIsServicePresent=%d, \
   1475             uServicecategory=%d, sAddress.digit_mode=%d, \
   1476             sAddress.Number_mode=%d, sAddress.number_type=%d, ",
   1477             rcsm->uTeleserviceID,  rcsm->bIsServicePresent,
   1478             rcsm->uServicecategory,rcsm->sAddress.digit_mode,
   1479             rcsm->sAddress.number_mode,rcsm->sAddress.number_type);
   1480 
   1481     if (err != 0) goto error;
   1482 
   1483     // Cdma Send SMS implementation will go here:
   1484     // But it is not implemented yet.
   1485 
   1486     memset(&response, 0, sizeof(response));
   1487     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
   1488     return;
   1489 
   1490 error:
   1491     // Cdma Send SMS will always cause send retry error.
   1492     RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, NULL, 0);
   1493 }
   1494 
   1495 static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
   1496 {
   1497     int err;
   1498     const char *smsc;
   1499     const char *pdu;
   1500     int tpLayerLength;
   1501     char *cmd1, *cmd2;
   1502     RIL_SMS_Response response;
   1503     ATResponse *p_response = NULL;
   1504 
   1505     smsc = ((const char **)data)[0];
   1506     pdu = ((const char **)data)[1];
   1507 
   1508     tpLayerLength = strlen(pdu)/2;
   1509 
   1510     // "NULL for default SMSC"
   1511     if (smsc == NULL) {
   1512         smsc= "00";
   1513     }
   1514 
   1515     asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
   1516     asprintf(&cmd2, "%s%s", smsc, pdu);
   1517 
   1518     err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
   1519 
   1520     if (err != 0 || p_response->success == 0) goto error;
   1521 
   1522     memset(&response, 0, sizeof(response));
   1523 
   1524     /* FIXME fill in messageRef and ackPDU */
   1525 
   1526     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
   1527     at_response_free(p_response);
   1528 
   1529     return;
   1530 error:
   1531     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1532     at_response_free(p_response);
   1533 }
   1534 
   1535 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
   1536 {
   1537     const char *apn;
   1538     char *cmd;
   1539     int err;
   1540     ATResponse *p_response = NULL;
   1541 
   1542     apn = ((const char **)data)[2];
   1543 
   1544 #ifdef USE_TI_COMMANDS
   1545     // Config for multislot class 10 (probably default anyway eh?)
   1546     err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
   1547                         NULL);
   1548 
   1549     err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
   1550 #endif /* USE_TI_COMMANDS */
   1551 
   1552     int fd, qmistatus;
   1553     size_t cur = 0;
   1554     size_t len;
   1555     ssize_t written, rlen;
   1556     char status[32] = {0};
   1557     int retry = 10;
   1558     const char *pdp_type;
   1559 
   1560     ALOGD("requesting data connection to APN '%s'", apn);
   1561 
   1562     fd = open ("/dev/qmi", O_RDWR);
   1563     if (fd >= 0) { /* the device doesn't exist on the emulator */
   1564 
   1565         ALOGD("opened the qmi device\n");
   1566         asprintf(&cmd, "up:%s", apn);
   1567         len = strlen(cmd);
   1568 
   1569         while (cur < len) {
   1570             do {
   1571                 written = write (fd, cmd + cur, len - cur);
   1572             } while (written < 0 && errno == EINTR);
   1573 
   1574             if (written < 0) {
   1575                 ALOGE("### ERROR writing to /dev/qmi");
   1576                 close(fd);
   1577                 goto error;
   1578             }
   1579 
   1580             cur += written;
   1581         }
   1582 
   1583         // wait for interface to come online
   1584 
   1585         do {
   1586             sleep(1);
   1587             do {
   1588                 rlen = read(fd, status, 31);
   1589             } while (rlen < 0 && errno == EINTR);
   1590 
   1591             if (rlen < 0) {
   1592                 ALOGE("### ERROR reading from /dev/qmi");
   1593                 close(fd);
   1594                 goto error;
   1595             } else {
   1596                 status[rlen] = '\0';
   1597                 ALOGD("### status: %s", status);
   1598             }
   1599         } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
   1600 
   1601         close(fd);
   1602 
   1603         if (retry == 0) {
   1604             ALOGE("### Failed to get data connection up\n");
   1605             goto error;
   1606         }
   1607 
   1608         qmistatus = system("netcfg rmnet0 dhcp");
   1609 
   1610         ALOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus);
   1611 
   1612         if (qmistatus < 0) goto error;
   1613 
   1614     } else {
   1615 
   1616         if (datalen > 6 * sizeof(char *)) {
   1617             pdp_type = ((const char **)data)[6];
   1618         } else {
   1619             pdp_type = "IP";
   1620         }
   1621 
   1622         asprintf(&cmd, "AT+CGDCONT=1,\"%s\",\"%s\",,0,0", pdp_type, apn);
   1623         //FIXME check for error here
   1624         err = at_send_command(cmd, NULL);
   1625         free(cmd);
   1626 
   1627         // Set required QoS params to default
   1628         err = at_send_command("AT+CGQREQ=1", NULL);
   1629 
   1630         // Set minimum QoS params to default
   1631         err = at_send_command("AT+CGQMIN=1", NULL);
   1632 
   1633         // packet-domain event reporting
   1634         err = at_send_command("AT+CGEREP=1,0", NULL);
   1635 
   1636         // Hangup anything that's happening there now
   1637         err = at_send_command("AT+CGACT=1,0", NULL);
   1638 
   1639         // Start data on PDP context 1
   1640         err = at_send_command("ATD*99***1#", &p_response);
   1641 
   1642         if (err < 0 || p_response->success == 0) {
   1643             goto error;
   1644         }
   1645     }
   1646 
   1647     requestOrSendDataCallList(&t);
   1648 
   1649     at_response_free(p_response);
   1650 
   1651     return;
   1652 error:
   1653     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1654     at_response_free(p_response);
   1655 
   1656 }
   1657 
   1658 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
   1659 {
   1660     int ackSuccess;
   1661     int err;
   1662 
   1663     ackSuccess = ((int *)data)[0];
   1664 
   1665     if (ackSuccess == 1) {
   1666         err = at_send_command("AT+CNMA=1", NULL);
   1667     } else if (ackSuccess == 0)  {
   1668         err = at_send_command("AT+CNMA=2", NULL);
   1669     } else {
   1670         ALOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
   1671         goto error;
   1672     }
   1673 
   1674     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1675 error:
   1676     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1677 
   1678 }
   1679 
   1680 static void  requestSIM_IO(void *data, size_t datalen, RIL_Token t)
   1681 {
   1682     ATResponse *p_response = NULL;
   1683     RIL_SIM_IO_Response sr;
   1684     int err;
   1685     char *cmd = NULL;
   1686     RIL_SIM_IO_v6 *p_args;
   1687     char *line;
   1688 
   1689     memset(&sr, 0, sizeof(sr));
   1690 
   1691     p_args = (RIL_SIM_IO_v6 *)data;
   1692 
   1693     /* FIXME handle pin2 */
   1694 
   1695     if (p_args->data == NULL) {
   1696         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
   1697                     p_args->command, p_args->fileid,
   1698                     p_args->p1, p_args->p2, p_args->p3);
   1699     } else {
   1700         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
   1701                     p_args->command, p_args->fileid,
   1702                     p_args->p1, p_args->p2, p_args->p3, p_args->data);
   1703     }
   1704 
   1705     err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
   1706 
   1707     if (err < 0 || p_response->success == 0) {
   1708         goto error;
   1709     }
   1710 
   1711     line = p_response->p_intermediates->line;
   1712 
   1713     err = at_tok_start(&line);
   1714     if (err < 0) goto error;
   1715 
   1716     err = at_tok_nextint(&line, &(sr.sw1));
   1717     if (err < 0) goto error;
   1718 
   1719     err = at_tok_nextint(&line, &(sr.sw2));
   1720     if (err < 0) goto error;
   1721 
   1722     if (at_tok_hasmore(&line)) {
   1723         err = at_tok_nextstr(&line, &(sr.simResponse));
   1724         if (err < 0) goto error;
   1725     }
   1726 
   1727     RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
   1728     at_response_free(p_response);
   1729     free(cmd);
   1730 
   1731     return;
   1732 error:
   1733     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1734     at_response_free(p_response);
   1735     free(cmd);
   1736 
   1737 }
   1738 
   1739 static void  requestEnterSimPin(void*  data, size_t  datalen, RIL_Token  t)
   1740 {
   1741     ATResponse   *p_response = NULL;
   1742     int           err;
   1743     char*         cmd = NULL;
   1744     const char**  strings = (const char**)data;;
   1745 
   1746     if ( datalen == sizeof(char*) ) {
   1747         asprintf(&cmd, "AT+CPIN=%s", strings[0]);
   1748     } else if ( datalen == 2*sizeof(char*) ) {
   1749         asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
   1750     } else
   1751         goto error;
   1752 
   1753     err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
   1754     free(cmd);
   1755 
   1756     if (err < 0 || p_response->success == 0) {
   1757 error:
   1758         RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
   1759     } else {
   1760         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1761     }
   1762     at_response_free(p_response);
   1763 }
   1764 
   1765 
   1766 static void  requestSendUSSD(void *data, size_t datalen, RIL_Token t)
   1767 {
   1768     const char *ussdRequest;
   1769 
   1770     ussdRequest = (char *)(data);
   1771 
   1772 
   1773     RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
   1774 
   1775 // @@@ TODO
   1776 
   1777 }
   1778 
   1779 static void requestExitEmergencyMode(void *data, size_t datalen, RIL_Token t)
   1780 {
   1781     int err;
   1782     ATResponse *p_response = NULL;
   1783 
   1784     err = at_send_command("AT+WSOS=0", &p_response);
   1785 
   1786     if (err < 0 || p_response->success == 0) {
   1787         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1788         return;
   1789     }
   1790 
   1791     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1792 }
   1793 
   1794 // TODO: Use all radio types
   1795 static int techFromModemType(int mdmtype)
   1796 {
   1797     int ret = -1;
   1798     switch (1 << mdmtype) {
   1799         case MDM_CDMA:
   1800             ret = RADIO_TECH_1xRTT;
   1801             break;
   1802         case MDM_EVDO:
   1803             ret = RADIO_TECH_EVDO_A;
   1804             break;
   1805         case MDM_GSM:
   1806             ret = RADIO_TECH_GPRS;
   1807             break;
   1808         case MDM_WCDMA:
   1809             ret = RADIO_TECH_HSPA;
   1810             break;
   1811         case MDM_LTE:
   1812             ret = RADIO_TECH_LTE;
   1813             break;
   1814     }
   1815     return ret;
   1816 }
   1817 
   1818 /*** Callback methods from the RIL library to us ***/
   1819 
   1820 /**
   1821  * Call from RIL to us to make a RIL_REQUEST
   1822  *
   1823  * Must be completed with a call to RIL_onRequestComplete()
   1824  *
   1825  * RIL_onRequestComplete() may be called from any thread, before or after
   1826  * this function returns.
   1827  *
   1828  * Will always be called from the same thread, so returning here implies
   1829  * that the radio is ready to process another command (whether or not
   1830  * the previous command has completed).
   1831  */
   1832 static void
   1833 onRequest (int request, void *data, size_t datalen, RIL_Token t)
   1834 {
   1835     ATResponse *p_response;
   1836     int err;
   1837 
   1838     ALOGD("onRequest: %s", requestToString(request));
   1839 
   1840     /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
   1841      * when RADIO_STATE_UNAVAILABLE.
   1842      */
   1843     if (sState == RADIO_STATE_UNAVAILABLE
   1844         && request != RIL_REQUEST_GET_SIM_STATUS
   1845     ) {
   1846         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
   1847         return;
   1848     }
   1849 
   1850     /* Ignore all non-power requests when RADIO_STATE_OFF
   1851      * (except RIL_REQUEST_GET_SIM_STATUS)
   1852      */
   1853     if (sState == RADIO_STATE_OFF
   1854         && !(request == RIL_REQUEST_RADIO_POWER
   1855             || request == RIL_REQUEST_GET_SIM_STATUS)
   1856     ) {
   1857         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
   1858         return;
   1859     }
   1860 
   1861     switch (request) {
   1862         case RIL_REQUEST_GET_SIM_STATUS: {
   1863             RIL_CardStatus_v6 *p_card_status;
   1864             char *p_buffer;
   1865             int buffer_size;
   1866 
   1867             int result = getCardStatus(&p_card_status);
   1868             if (result == RIL_E_SUCCESS) {
   1869                 p_buffer = (char *)p_card_status;
   1870                 buffer_size = sizeof(*p_card_status);
   1871             } else {
   1872                 p_buffer = NULL;
   1873                 buffer_size = 0;
   1874             }
   1875             RIL_onRequestComplete(t, result, p_buffer, buffer_size);
   1876             freeCardStatus(p_card_status);
   1877             break;
   1878         }
   1879         case RIL_REQUEST_GET_CURRENT_CALLS:
   1880             requestGetCurrentCalls(data, datalen, t);
   1881             break;
   1882         case RIL_REQUEST_DIAL:
   1883             requestDial(data, datalen, t);
   1884             break;
   1885         case RIL_REQUEST_HANGUP:
   1886             requestHangup(data, datalen, t);
   1887             break;
   1888         case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
   1889             // 3GPP 22.030 6.5.5
   1890             // "Releases all held calls or sets User Determined User Busy
   1891             //  (UDUB) for a waiting call."
   1892             at_send_command("AT+CHLD=0", NULL);
   1893 
   1894             /* success or failure is ignored by the upper layer here.
   1895                it will call GET_CURRENT_CALLS and determine success that way */
   1896             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1897             break;
   1898         case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
   1899             // 3GPP 22.030 6.5.5
   1900             // "Releases all active calls (if any exist) and accepts
   1901             //  the other (held or waiting) call."
   1902             at_send_command("AT+CHLD=1", NULL);
   1903 
   1904             /* success or failure is ignored by the upper layer here.
   1905                it will call GET_CURRENT_CALLS and determine success that way */
   1906             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1907             break;
   1908         case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
   1909             // 3GPP 22.030 6.5.5
   1910             // "Places all active calls (if any exist) on hold and accepts
   1911             //  the other (held or waiting) call."
   1912             at_send_command("AT+CHLD=2", NULL);
   1913 
   1914 #ifdef WORKAROUND_ERRONEOUS_ANSWER
   1915             s_expectAnswer = 1;
   1916 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
   1917 
   1918             /* success or failure is ignored by the upper layer here.
   1919                it will call GET_CURRENT_CALLS and determine success that way */
   1920             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1921             break;
   1922         case RIL_REQUEST_ANSWER:
   1923             at_send_command("ATA", NULL);
   1924 
   1925 #ifdef WORKAROUND_ERRONEOUS_ANSWER
   1926             s_expectAnswer = 1;
   1927 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
   1928 
   1929             /* success or failure is ignored by the upper layer here.
   1930                it will call GET_CURRENT_CALLS and determine success that way */
   1931             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1932             break;
   1933         case RIL_REQUEST_CONFERENCE:
   1934             // 3GPP 22.030 6.5.5
   1935             // "Adds a held call to the conversation"
   1936             at_send_command("AT+CHLD=3", NULL);
   1937 
   1938             /* success or failure is ignored by the upper layer here.
   1939                it will call GET_CURRENT_CALLS and determine success that way */
   1940             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1941             break;
   1942         case RIL_REQUEST_UDUB:
   1943             /* user determined user busy */
   1944             /* sometimes used: ATH */
   1945             at_send_command("ATH", NULL);
   1946 
   1947             /* success or failure is ignored by the upper layer here.
   1948                it will call GET_CURRENT_CALLS and determine success that way */
   1949             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1950             break;
   1951 
   1952         case RIL_REQUEST_SEPARATE_CONNECTION:
   1953             {
   1954                 char  cmd[12];
   1955                 int   party = ((int*)data)[0];
   1956 
   1957                 // Make sure that party is in a valid range.
   1958                 // (Note: The Telephony middle layer imposes a range of 1 to 7.
   1959                 // It's sufficient for us to just make sure it's single digit.)
   1960                 if (party > 0 && party < 10) {
   1961                     sprintf(cmd, "AT+CHLD=2%d", party);
   1962                     at_send_command(cmd, NULL);
   1963                     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1964                 } else {
   1965                     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   1966                 }
   1967             }
   1968             break;
   1969 
   1970         case RIL_REQUEST_SIGNAL_STRENGTH:
   1971             requestSignalStrength(data, datalen, t);
   1972             break;
   1973         case RIL_REQUEST_VOICE_REGISTRATION_STATE:
   1974         case RIL_REQUEST_DATA_REGISTRATION_STATE:
   1975             requestRegistrationState(request, data, datalen, t);
   1976             break;
   1977         case RIL_REQUEST_OPERATOR:
   1978             requestOperator(data, datalen, t);
   1979             break;
   1980         case RIL_REQUEST_RADIO_POWER:
   1981             requestRadioPower(data, datalen, t);
   1982             break;
   1983         case RIL_REQUEST_DTMF: {
   1984             char c = ((char *)data)[0];
   1985             char *cmd;
   1986             asprintf(&cmd, "AT+VTS=%c", (int)c);
   1987             at_send_command(cmd, NULL);
   1988             free(cmd);
   1989             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   1990             break;
   1991         }
   1992         case RIL_REQUEST_SEND_SMS:
   1993             requestSendSMS(data, datalen, t);
   1994             break;
   1995         case RIL_REQUEST_CDMA_SEND_SMS:
   1996             requestCdmaSendSMS(data, datalen, t);
   1997             break;
   1998         case RIL_REQUEST_SETUP_DATA_CALL:
   1999             requestSetupDataCall(data, datalen, t);
   2000             break;
   2001         case RIL_REQUEST_SMS_ACKNOWLEDGE:
   2002             requestSMSAcknowledge(data, datalen, t);
   2003             break;
   2004 
   2005         case RIL_REQUEST_GET_IMSI:
   2006             p_response = NULL;
   2007             err = at_send_command_numeric("AT+CIMI", &p_response);
   2008 
   2009             if (err < 0 || p_response->success == 0) {
   2010                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   2011             } else {
   2012                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
   2013                     p_response->p_intermediates->line, sizeof(char *));
   2014             }
   2015             at_response_free(p_response);
   2016             break;
   2017 
   2018         case RIL_REQUEST_GET_IMEI:
   2019             p_response = NULL;
   2020             err = at_send_command_numeric("AT+CGSN", &p_response);
   2021 
   2022             if (err < 0 || p_response->success == 0) {
   2023                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   2024             } else {
   2025                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
   2026                     p_response->p_intermediates->line, sizeof(char *));
   2027             }
   2028             at_response_free(p_response);
   2029             break;
   2030 
   2031         case RIL_REQUEST_SIM_IO:
   2032             requestSIM_IO(data,datalen,t);
   2033             break;
   2034 
   2035         case RIL_REQUEST_SEND_USSD:
   2036             requestSendUSSD(data, datalen, t);
   2037             break;
   2038 
   2039         case RIL_REQUEST_CANCEL_USSD:
   2040             p_response = NULL;
   2041             err = at_send_command_numeric("AT+CUSD=2", &p_response);
   2042 
   2043             if (err < 0 || p_response->success == 0) {
   2044                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   2045             } else {
   2046                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
   2047                     p_response->p_intermediates->line, sizeof(char *));
   2048             }
   2049             at_response_free(p_response);
   2050             break;
   2051 
   2052         case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
   2053             at_send_command("AT+COPS=0", NULL);
   2054             break;
   2055 
   2056         case RIL_REQUEST_DATA_CALL_LIST:
   2057             requestDataCallList(data, datalen, t);
   2058             break;
   2059 
   2060         case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
   2061             requestQueryNetworkSelectionMode(data, datalen, t);
   2062             break;
   2063 
   2064         case RIL_REQUEST_OEM_HOOK_RAW:
   2065             // echo back data
   2066             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
   2067             break;
   2068 
   2069 
   2070         case RIL_REQUEST_OEM_HOOK_STRINGS: {
   2071             int i;
   2072             const char ** cur;
   2073 
   2074             ALOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
   2075 
   2076 
   2077             for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
   2078                     i > 0 ; cur++, i --) {
   2079                 ALOGD("> '%s'", *cur);
   2080             }
   2081 
   2082             // echo back strings
   2083             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
   2084             break;
   2085         }
   2086 
   2087         case RIL_REQUEST_WRITE_SMS_TO_SIM:
   2088             requestWriteSmsToSim(data, datalen, t);
   2089             break;
   2090 
   2091         case RIL_REQUEST_DELETE_SMS_ON_SIM: {
   2092             char * cmd;
   2093             p_response = NULL;
   2094             asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
   2095             err = at_send_command(cmd, &p_response);
   2096             free(cmd);
   2097             if (err < 0 || p_response->success == 0) {
   2098                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   2099             } else {
   2100                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
   2101             }
   2102             at_response_free(p_response);
   2103             break;
   2104         }
   2105 
   2106         case RIL_REQUEST_ENTER_SIM_PIN:
   2107         case RIL_REQUEST_ENTER_SIM_PUK:
   2108         case RIL_REQUEST_ENTER_SIM_PIN2:
   2109         case RIL_REQUEST_ENTER_SIM_PUK2:
   2110         case RIL_REQUEST_CHANGE_SIM_PIN:
   2111         case RIL_REQUEST_CHANGE_SIM_PIN2:
   2112             requestEnterSimPin(data, datalen, t);
   2113             break;
   2114 
   2115         case RIL_REQUEST_VOICE_RADIO_TECH:
   2116             {
   2117                 int tech = techFromModemType(TECH(sMdmInfo));
   2118                 if (tech < 0 )
   2119                     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
   2120                 else
   2121                     RIL_onRequestComplete(t, RIL_E_SUCCESS, &tech, sizeof(tech));
   2122             }
   2123             break;
   2124         case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
   2125             requestSetPreferredNetworkType(request, data, datalen, t);
   2126             break;
   2127 
   2128         case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
   2129             requestGetPreferredNetworkType(request, data, datalen, t);
   2130             break;
   2131 
   2132         /* CDMA Specific Requests */
   2133         case RIL_REQUEST_BASEBAND_VERSION:
   2134             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2135                 requestCdmaBaseBandVersion(request, data, datalen, t);
   2136                 break;
   2137             } // Fall-through if tech is not cdma
   2138 
   2139         case RIL_REQUEST_DEVICE_IDENTITY:
   2140             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2141                 requestCdmaDeviceIdentity(request, data, datalen, t);
   2142                 break;
   2143             } // Fall-through if tech is not cdma
   2144 
   2145         case RIL_REQUEST_CDMA_SUBSCRIPTION:
   2146             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2147                 requestCdmaSubscription(request, data, datalen, t);
   2148                 break;
   2149             } // Fall-through if tech is not cdma
   2150 
   2151         case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
   2152             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2153                 requestCdmaSetSubscriptionSource(request, data, datalen, t);
   2154                 break;
   2155             } // Fall-through if tech is not cdma
   2156 
   2157         case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
   2158             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2159                 requestCdmaGetSubscriptionSource(request, data, datalen, t);
   2160                 break;
   2161             } // Fall-through if tech is not cdma
   2162 
   2163         case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:
   2164             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2165                 requestCdmaGetRoamingPreference(request, data, datalen, t);
   2166                 break;
   2167             } // Fall-through if tech is not cdma
   2168 
   2169         case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
   2170             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2171                 requestCdmaSetRoamingPreference(request, data, datalen, t);
   2172                 break;
   2173             } // Fall-through if tech is not cdma
   2174 
   2175         case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
   2176             if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
   2177                 requestExitEmergencyMode(data, datalen, t);
   2178                 break;
   2179             } // Fall-through if tech is not cdma
   2180 
   2181         default:
   2182             ALOGD("Request not supported. Tech: %d",TECH(sMdmInfo));
   2183             RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
   2184             break;
   2185     }
   2186 }
   2187 
   2188 /**
   2189  * Synchronous call from the RIL to us to return current radio state.
   2190  * RADIO_STATE_UNAVAILABLE should be the initial state.
   2191  */
   2192 static RIL_RadioState
   2193 currentState()
   2194 {
   2195     return sState;
   2196 }
   2197 /**
   2198  * Call from RIL to us to find out whether a specific request code
   2199  * is supported by this implementation.
   2200  *
   2201  * Return 1 for "supported" and 0 for "unsupported"
   2202  */
   2203 
   2204 static int
   2205 onSupports (int requestCode)
   2206 {
   2207     //@@@ todo
   2208 
   2209     return 1;
   2210 }
   2211 
   2212 static void onCancel (RIL_Token t)
   2213 {
   2214     //@@@todo
   2215 
   2216 }
   2217 
   2218 static const char * getVersion(void)
   2219 {
   2220     return "android reference-ril 1.0";
   2221 }
   2222 
   2223 static void
   2224 setRadioTechnology(ModemInfo *mdm, int newtech)
   2225 {
   2226     ALOGD("setRadioTechnology(%d)", newtech);
   2227 
   2228     int oldtech = TECH(mdm);
   2229 
   2230     if (newtech != oldtech) {
   2231         ALOGD("Tech change (%d => %d)", oldtech, newtech);
   2232         TECH(mdm) = newtech;
   2233         if (techFromModemType(newtech) != techFromModemType(oldtech)) {
   2234             int tech = techFromModemType(TECH(sMdmInfo));
   2235             if (tech > 0 ) {
   2236                 RIL_onUnsolicitedResponse(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED,
   2237                                           &tech, sizeof(tech));
   2238             }
   2239         }
   2240     }
   2241 }
   2242 
   2243 static void
   2244 setRadioState(RIL_RadioState newState)
   2245 {
   2246     ALOGD("setRadioState(%d)", newState);
   2247     RIL_RadioState oldState;
   2248 
   2249     pthread_mutex_lock(&s_state_mutex);
   2250 
   2251     oldState = sState;
   2252 
   2253     if (s_closed > 0) {
   2254         // If we're closed, the only reasonable state is
   2255         // RADIO_STATE_UNAVAILABLE
   2256         // This is here because things on the main thread
   2257         // may attempt to change the radio state after the closed
   2258         // event happened in another thread
   2259         newState = RADIO_STATE_UNAVAILABLE;
   2260     }
   2261 
   2262     if (sState != newState || s_closed > 0) {
   2263         sState = newState;
   2264 
   2265         pthread_cond_broadcast (&s_state_cond);
   2266     }
   2267 
   2268     pthread_mutex_unlock(&s_state_mutex);
   2269 
   2270 
   2271     /* do these outside of the mutex */
   2272     if (sState != oldState) {
   2273         RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
   2274                                     NULL, 0);
   2275 
   2276         /* FIXME onSimReady() and onRadioPowerOn() cannot be called
   2277          * from the AT reader thread
   2278          * Currently, this doesn't happen, but if that changes then these
   2279          * will need to be dispatched on the request thread
   2280          */
   2281         if (sState == RADIO_STATE_ON) {
   2282             onRadioPowerOn();
   2283         }
   2284     }
   2285 }
   2286 
   2287 /** Returns RUIM_NOT_READY on error */
   2288 static SIM_Status
   2289 getRUIMStatus()
   2290 {
   2291     ATResponse *p_response = NULL;
   2292     int err;
   2293     int ret;
   2294     char *cpinLine;
   2295     char *cpinResult;
   2296 
   2297     if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
   2298         ret = SIM_NOT_READY;
   2299         goto done;
   2300     }
   2301 
   2302     err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
   2303 
   2304     if (err != 0) {
   2305         ret = SIM_NOT_READY;
   2306         goto done;
   2307     }
   2308 
   2309     switch (at_get_cme_error(p_response)) {
   2310         case CME_SUCCESS:
   2311             break;
   2312 
   2313         case CME_SIM_NOT_INSERTED:
   2314             ret = SIM_ABSENT;
   2315             goto done;
   2316 
   2317         default:
   2318             ret = SIM_NOT_READY;
   2319             goto done;
   2320     }
   2321 
   2322     /* CPIN? has succeeded, now look at the result */
   2323 
   2324     cpinLine = p_response->p_intermediates->line;
   2325     err = at_tok_start (&cpinLine);
   2326 
   2327     if (err < 0) {
   2328         ret = SIM_NOT_READY;
   2329         goto done;
   2330     }
   2331 
   2332     err = at_tok_nextstr(&cpinLine, &cpinResult);
   2333 
   2334     if (err < 0) {
   2335         ret = SIM_NOT_READY;
   2336         goto done;
   2337     }
   2338 
   2339     if (0 == strcmp (cpinResult, "SIM PIN")) {
   2340         ret = SIM_PIN;
   2341         goto done;
   2342     } else if (0 == strcmp (cpinResult, "SIM PUK")) {
   2343         ret = SIM_PUK;
   2344         goto done;
   2345     } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
   2346         return SIM_NETWORK_PERSONALIZATION;
   2347     } else if (0 != strcmp (cpinResult, "READY"))  {
   2348         /* we're treating unsupported lock types as "sim absent" */
   2349         ret = SIM_ABSENT;
   2350         goto done;
   2351     }
   2352 
   2353     at_response_free(p_response);
   2354     p_response = NULL;
   2355     cpinResult = NULL;
   2356 
   2357     ret = SIM_READY;
   2358 
   2359 done:
   2360     at_response_free(p_response);
   2361     return ret;
   2362 }
   2363 
   2364 /** Returns SIM_NOT_READY on error */
   2365 static SIM_Status
   2366 getSIMStatus()
   2367 {
   2368     ATResponse *p_response = NULL;
   2369     int err;
   2370     int ret;
   2371     char *cpinLine;
   2372     char *cpinResult;
   2373 
   2374     ALOGD("getSIMStatus(). sState: %d",sState);
   2375     if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
   2376         ret = SIM_NOT_READY;
   2377         goto done;
   2378     }
   2379 
   2380     err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
   2381 
   2382     if (err != 0) {
   2383         ret = SIM_NOT_READY;
   2384         goto done;
   2385     }
   2386 
   2387     switch (at_get_cme_error(p_response)) {
   2388         case CME_SUCCESS:
   2389             break;
   2390 
   2391         case CME_SIM_NOT_INSERTED:
   2392             ret = SIM_ABSENT;
   2393             goto done;
   2394 
   2395         default:
   2396             ret = SIM_NOT_READY;
   2397             goto done;
   2398     }
   2399 
   2400     /* CPIN? has succeeded, now look at the result */
   2401 
   2402     cpinLine = p_response->p_intermediates->line;
   2403     err = at_tok_start (&cpinLine);
   2404 
   2405     if (err < 0) {
   2406         ret = SIM_NOT_READY;
   2407         goto done;
   2408     }
   2409 
   2410     err = at_tok_nextstr(&cpinLine, &cpinResult);
   2411 
   2412     if (err < 0) {
   2413         ret = SIM_NOT_READY;
   2414         goto done;
   2415     }
   2416 
   2417     if (0 == strcmp (cpinResult, "SIM PIN")) {
   2418         ret = SIM_PIN;
   2419         goto done;
   2420     } else if (0 == strcmp (cpinResult, "SIM PUK")) {
   2421         ret = SIM_PUK;
   2422         goto done;
   2423     } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
   2424         return SIM_NETWORK_PERSONALIZATION;
   2425     } else if (0 != strcmp (cpinResult, "READY"))  {
   2426         /* we're treating unsupported lock types as "sim absent" */
   2427         ret = SIM_ABSENT;
   2428         goto done;
   2429     }
   2430 
   2431     at_response_free(p_response);
   2432     p_response = NULL;
   2433     cpinResult = NULL;
   2434 
   2435     ret = SIM_READY;
   2436 
   2437 done:
   2438     at_response_free(p_response);
   2439     return ret;
   2440 }
   2441 
   2442 
   2443 /**
   2444  * Get the current card status.
   2445  *
   2446  * This must be freed using freeCardStatus.
   2447  * @return: On success returns RIL_E_SUCCESS
   2448  */
   2449 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status) {
   2450     static RIL_AppStatus app_status_array[] = {
   2451         // SIM_ABSENT = 0
   2452         { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
   2453           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   2454         // SIM_NOT_READY = 1
   2455         { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
   2456           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   2457         // SIM_READY = 2
   2458         { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
   2459           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   2460         // SIM_PIN = 3
   2461         { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
   2462           NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
   2463         // SIM_PUK = 4
   2464         { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
   2465           NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
   2466         // SIM_NETWORK_PERSONALIZATION = 5
   2467         { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
   2468           NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
   2469         // RUIM_ABSENT = 6
   2470         { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
   2471           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   2472         // RUIM_NOT_READY = 7
   2473         { RIL_APPTYPE_RUIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
   2474           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   2475         // RUIM_READY = 8
   2476         { RIL_APPTYPE_RUIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
   2477           NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
   2478         // RUIM_PIN = 9
   2479         { RIL_APPTYPE_RUIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
   2480           NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
   2481         // RUIM_PUK = 10
   2482         { RIL_APPTYPE_RUIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
   2483           NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
   2484         // RUIM_NETWORK_PERSONALIZATION = 11
   2485         { RIL_APPTYPE_RUIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
   2486            NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }
   2487     };
   2488     RIL_CardState card_state;
   2489     int num_apps;
   2490 
   2491     int sim_status = getSIMStatus();
   2492     if (sim_status == SIM_ABSENT) {
   2493         card_state = RIL_CARDSTATE_ABSENT;
   2494         num_apps = 0;
   2495     } else {
   2496         card_state = RIL_CARDSTATE_PRESENT;
   2497         num_apps = 2;
   2498     }
   2499 
   2500     // Allocate and initialize base card status.
   2501     RIL_CardStatus_v6 *p_card_status = malloc(sizeof(RIL_CardStatus_v6));
   2502     p_card_status->card_state = card_state;
   2503     p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
   2504     p_card_status->gsm_umts_subscription_app_index = RIL_CARD_MAX_APPS;
   2505     p_card_status->cdma_subscription_app_index = RIL_CARD_MAX_APPS;
   2506     p_card_status->ims_subscription_app_index = RIL_CARD_MAX_APPS;
   2507     p_card_status->num_applications = num_apps;
   2508 
   2509     // Initialize application status
   2510     int i;
   2511     for (i = 0; i < RIL_CARD_MAX_APPS; i++) {
   2512         p_card_status->applications[i] = app_status_array[SIM_ABSENT];
   2513     }
   2514 
   2515     // Pickup the appropriate application status
   2516     // that reflects sim_status for gsm.
   2517     if (num_apps != 0) {
   2518         // Only support one app, gsm
   2519         p_card_status->num_applications = 2;
   2520         p_card_status->gsm_umts_subscription_app_index = 0;
   2521         p_card_status->cdma_subscription_app_index = 1;
   2522 
   2523         // Get the correct app status
   2524         p_card_status->applications[0] = app_status_array[sim_status];
   2525         p_card_status->applications[1] = app_status_array[sim_status + RUIM_ABSENT];
   2526     }
   2527 
   2528     *pp_card_status = p_card_status;
   2529     return RIL_E_SUCCESS;
   2530 }
   2531 
   2532 /**
   2533  * Free the card status returned by getCardStatus
   2534  */
   2535 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status) {
   2536     free(p_card_status);
   2537 }
   2538 
   2539 /**
   2540  * SIM ready means any commands that access the SIM will work, including:
   2541  *  AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
   2542  *  (all SMS-related commands)
   2543  */
   2544 
   2545 static void pollSIMState (void *param)
   2546 {
   2547     ATResponse *p_response;
   2548     int ret;
   2549 
   2550     if (sState != RADIO_STATE_SIM_NOT_READY) {
   2551         // no longer valid to poll
   2552         return;
   2553     }
   2554 
   2555     switch(getSIMStatus()) {
   2556         case SIM_ABSENT:
   2557         case SIM_PIN:
   2558         case SIM_PUK:
   2559         case SIM_NETWORK_PERSONALIZATION:
   2560         default:
   2561             ALOGI("SIM ABSENT or LOCKED");
   2562             RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
   2563         return;
   2564 
   2565         case SIM_NOT_READY:
   2566             RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
   2567         return;
   2568 
   2569         case SIM_READY:
   2570             ALOGI("SIM_READY");
   2571             onSIMReady();
   2572             RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
   2573         return;
   2574     }
   2575 }
   2576 
   2577 /** returns 1 if on, 0 if off, and -1 on error */
   2578 static int isRadioOn()
   2579 {
   2580     ATResponse *p_response = NULL;
   2581     int err;
   2582     char *line;
   2583     char ret;
   2584 
   2585     err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
   2586 
   2587     if (err < 0 || p_response->success == 0) {
   2588         // assume radio is off
   2589         goto error;
   2590     }
   2591 
   2592     line = p_response->p_intermediates->line;
   2593 
   2594     err = at_tok_start(&line);
   2595     if (err < 0) goto error;
   2596 
   2597     err = at_tok_nextbool(&line, &ret);
   2598     if (err < 0) goto error;
   2599 
   2600     at_response_free(p_response);
   2601 
   2602     return (int)ret;
   2603 
   2604 error:
   2605 
   2606     at_response_free(p_response);
   2607     return -1;
   2608 }
   2609 
   2610 /**
   2611  * Parse the response generated by a +CTEC AT command
   2612  * The values read from the response are stored in current and preferred.
   2613  * Both current and preferred may be null. The corresponding value is ignored in that case.
   2614  *
   2615  * @return: -1 if some error occurs (or if the modem doesn't understand the +CTEC command)
   2616  *          1 if the response includes the current technology only
   2617  *          0 if the response includes both current technology and preferred mode
   2618  */
   2619 int parse_technology_response( const char *response, int *current, int32_t *preferred )
   2620 {
   2621     int err;
   2622     char *line, *p;
   2623     int ct;
   2624     int32_t pt = 0;
   2625     char *str_pt;
   2626 
   2627     line = p = strdup(response);
   2628     ALOGD("Response: %s", line);
   2629     err = at_tok_start(&p);
   2630     if (err || !at_tok_hasmore(&p)) {
   2631         ALOGD("err: %d. p: %s", err, p);
   2632         free(line);
   2633         return -1;
   2634     }
   2635 
   2636     err = at_tok_nextint(&p, &ct);
   2637     if (err) {
   2638         free(line);
   2639         return -1;
   2640     }
   2641     if (current) *current = ct;
   2642 
   2643     ALOGD("line remaining after int: %s", p);
   2644 
   2645     err = at_tok_nexthexint(&p, &pt);
   2646     if (err) {
   2647         free(line);
   2648         return 1;
   2649     }
   2650     if (preferred) {
   2651         *preferred = pt;
   2652     }
   2653     free(line);
   2654 
   2655     return 0;
   2656 }
   2657 
   2658 int query_supported_techs( ModemInfo *mdm, int *supported )
   2659 {
   2660     ATResponse *p_response;
   2661     int err, val, techs = 0;
   2662     char *tok;
   2663     char *line;
   2664 
   2665     ALOGD("query_supported_techs");
   2666     err = at_send_command_singleline("AT+CTEC=?", "+CTEC:", &p_response);
   2667     if (err || !p_response->success)
   2668         goto error;
   2669     line = p_response->p_intermediates->line;
   2670     err = at_tok_start(&line);
   2671     if (err || !at_tok_hasmore(&line))
   2672         goto error;
   2673     while (!at_tok_nextint(&line, &val)) {
   2674         techs |= ( 1 << val );
   2675     }
   2676     if (supported) *supported = techs;
   2677     return 0;
   2678 error:
   2679     at_response_free(p_response);
   2680     return -1;
   2681 }
   2682 
   2683 /**
   2684  * query_ctec. Send the +CTEC AT command to the modem to query the current
   2685  * and preferred modes. It leaves values in the addresses pointed to by
   2686  * current and preferred. If any of those pointers are NULL, the corresponding value
   2687  * is ignored, but the return value will still reflect if retreiving and parsing of the
   2688  * values suceeded.
   2689  *
   2690  * @mdm Currently unused
   2691  * @current A pointer to store the current mode returned by the modem. May be null.
   2692  * @preferred A pointer to store the preferred mode returned by the modem. May be null.
   2693  * @return -1 on error (or failure to parse)
   2694  *         1 if only the current mode was returned by modem (or failed to parse preferred)
   2695  *         0 if both current and preferred were returned correctly
   2696  */
   2697 int query_ctec(ModemInfo *mdm, int *current, int32_t *preferred)
   2698 {
   2699     ATResponse *response = NULL;
   2700     int err;
   2701     int res;
   2702 
   2703     ALOGD("query_ctec. current: %d, preferred: %d", (int)current, (int) preferred);
   2704     err = at_send_command_singleline("AT+CTEC?", "+CTEC:", &response);
   2705     if (!err && response->success) {
   2706         res = parse_technology_response(response->p_intermediates->line, current, preferred);
   2707         at_response_free(response);
   2708         return res;
   2709     }
   2710     ALOGE("Error executing command: %d. response: %x. status: %d", err, (int)response, response? response->success : -1);
   2711     at_response_free(response);
   2712     return -1;
   2713 }
   2714 
   2715 int is_multimode_modem(ModemInfo *mdm)
   2716 {
   2717     ATResponse *response;
   2718     int err;
   2719     char *line;
   2720     int tech;
   2721     int32_t preferred;
   2722 
   2723     if (query_ctec(mdm, &tech, &preferred) == 0) {
   2724         mdm->currentTech = tech;
   2725         mdm->preferredNetworkMode = preferred;
   2726         if (query_supported_techs(mdm, &mdm->supportedTechs)) {
   2727             return 0;
   2728         }
   2729         return 1;
   2730     }
   2731     return 0;
   2732 }
   2733 
   2734 /**
   2735  * Find out if our modem is GSM, CDMA or both (Multimode)
   2736  */
   2737 static void probeForModemMode(ModemInfo *info)
   2738 {
   2739     ATResponse *response;
   2740     int err;
   2741     assert (info);
   2742     // Currently, our only known multimode modem is qemu's android modem,
   2743     // which implements the AT+CTEC command to query and set mode.
   2744     // Try that first
   2745 
   2746     if (is_multimode_modem(info)) {
   2747         ALOGI("Found Multimode Modem. Supported techs mask: %8.8x. Current tech: %d",
   2748             info->supportedTechs, info->currentTech);
   2749         return;
   2750     }
   2751 
   2752     /* Being here means that our modem is not multimode */
   2753     info->isMultimode = 0;
   2754 
   2755     /* CDMA Modems implement the AT+WNAM command */
   2756     err = at_send_command_singleline("AT+WNAM","+WNAM:", &response);
   2757     if (!err && response->success) {
   2758         at_response_free(response);
   2759         // TODO: find out if we really support EvDo
   2760         info->supportedTechs = MDM_CDMA | MDM_EVDO;
   2761         info->currentTech = MDM_CDMA;
   2762         ALOGI("Found CDMA Modem");
   2763         return;
   2764     }
   2765     if (!err) at_response_free(response);
   2766     // TODO: find out if modem really supports WCDMA/LTE
   2767     info->supportedTechs = MDM_GSM | MDM_WCDMA | MDM_LTE;
   2768     info->currentTech = MDM_GSM;
   2769     ALOGI("Found GSM Modem");
   2770 }
   2771 
   2772 /**
   2773  * Initialize everything that can be configured while we're still in
   2774  * AT+CFUN=0
   2775  */
   2776 static void initializeCallback(void *param)
   2777 {
   2778     ATResponse *p_response = NULL;
   2779     int err;
   2780 
   2781     setRadioState (RADIO_STATE_OFF);
   2782 
   2783     at_handshake();
   2784 
   2785     probeForModemMode(sMdmInfo);
   2786     /* note: we don't check errors here. Everything important will
   2787        be handled in onATTimeout and onATReaderClosed */
   2788 
   2789     /*  atchannel is tolerant of echo but it must */
   2790     /*  have verbose result codes */
   2791     at_send_command("ATE0Q0V1", NULL);
   2792 
   2793     /*  No auto-answer */
   2794     at_send_command("ATS0=0", NULL);
   2795 
   2796     /*  Extended errors */
   2797     at_send_command("AT+CMEE=1", NULL);
   2798 
   2799     /*  Network registration events */
   2800     err = at_send_command("AT+CREG=2", &p_response);
   2801 
   2802     /* some handsets -- in tethered mode -- don't support CREG=2 */
   2803     if (err < 0 || p_response->success == 0) {
   2804         at_send_command("AT+CREG=1", NULL);
   2805     }
   2806 
   2807     at_response_free(p_response);
   2808 
   2809     /*  GPRS registration events */
   2810     at_send_command("AT+CGREG=1", NULL);
   2811 
   2812     /*  Call Waiting notifications */
   2813     at_send_command("AT+CCWA=1", NULL);
   2814 
   2815     /*  Alternating voice/data off */
   2816     at_send_command("AT+CMOD=0", NULL);
   2817 
   2818     /*  Not muted */
   2819     at_send_command("AT+CMUT=0", NULL);
   2820 
   2821     /*  +CSSU unsolicited supp service notifications */
   2822     at_send_command("AT+CSSN=0,1", NULL);
   2823 
   2824     /*  no connected line identification */
   2825     at_send_command("AT+COLP=0", NULL);
   2826 
   2827     /*  HEX character set */
   2828     at_send_command("AT+CSCS=\"HEX\"", NULL);
   2829 
   2830     /*  USSD unsolicited */
   2831     at_send_command("AT+CUSD=1", NULL);
   2832 
   2833     /*  Enable +CGEV GPRS event notifications, but don't buffer */
   2834     at_send_command("AT+CGEREP=1,0", NULL);
   2835 
   2836     /*  SMS PDU mode */
   2837     at_send_command("AT+CMGF=0", NULL);
   2838 
   2839 #ifdef USE_TI_COMMANDS
   2840 
   2841     at_send_command("AT%CPI=3", NULL);
   2842 
   2843     /*  TI specific -- notifications when SMS is ready (currently ignored) */
   2844     at_send_command("AT%CSTAT=1", NULL);
   2845 
   2846 #endif /* USE_TI_COMMANDS */
   2847 
   2848 
   2849     /* assume radio is off on error */
   2850     if (isRadioOn() > 0) {
   2851         setRadioState (RADIO_STATE_ON);
   2852     }
   2853 }
   2854 
   2855 static void waitForClose()
   2856 {
   2857     pthread_mutex_lock(&s_state_mutex);
   2858 
   2859     while (s_closed == 0) {
   2860         pthread_cond_wait(&s_state_cond, &s_state_mutex);
   2861     }
   2862 
   2863     pthread_mutex_unlock(&s_state_mutex);
   2864 }
   2865 
   2866 /**
   2867  * Called by atchannel when an unsolicited line appears
   2868  * This is called on atchannel's reader thread. AT commands may
   2869  * not be issued here
   2870  */
   2871 static void onUnsolicited (const char *s, const char *sms_pdu)
   2872 {
   2873     char *line = NULL, *p;
   2874     int err;
   2875 
   2876     /* Ignore unsolicited responses until we're initialized.
   2877      * This is OK because the RIL library will poll for initial state
   2878      */
   2879     if (sState == RADIO_STATE_UNAVAILABLE) {
   2880         return;
   2881     }
   2882 
   2883     if (strStartsWith(s, "%CTZV:")) {
   2884         /* TI specific -- NITZ time */
   2885         char *response;
   2886 
   2887         line = p = strdup(s);
   2888         at_tok_start(&p);
   2889 
   2890         err = at_tok_nextstr(&p, &response);
   2891 
   2892         free(line);
   2893         if (err != 0) {
   2894             ALOGE("invalid NITZ line %s\n", s);
   2895         } else {
   2896             RIL_onUnsolicitedResponse (
   2897                 RIL_UNSOL_NITZ_TIME_RECEIVED,
   2898                 response, strlen(response));
   2899         }
   2900     } else if (strStartsWith(s,"+CRING:")
   2901                 || strStartsWith(s,"RING")
   2902                 || strStartsWith(s,"NO CARRIER")
   2903                 || strStartsWith(s,"+CCWA")
   2904     ) {
   2905         RIL_onUnsolicitedResponse (
   2906             RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
   2907             NULL, 0);
   2908 #ifdef WORKAROUND_FAKE_CGEV
   2909         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
   2910 #endif /* WORKAROUND_FAKE_CGEV */
   2911     } else if (strStartsWith(s,"+CREG:")
   2912                 || strStartsWith(s,"+CGREG:")
   2913     ) {
   2914         RIL_onUnsolicitedResponse (
   2915             RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
   2916             NULL, 0);
   2917 #ifdef WORKAROUND_FAKE_CGEV
   2918         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
   2919 #endif /* WORKAROUND_FAKE_CGEV */
   2920     } else if (strStartsWith(s, "+CMT:")) {
   2921         RIL_onUnsolicitedResponse (
   2922             RIL_UNSOL_RESPONSE_NEW_SMS,
   2923             sms_pdu, strlen(sms_pdu));
   2924     } else if (strStartsWith(s, "+CDS:")) {
   2925         RIL_onUnsolicitedResponse (
   2926             RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
   2927             sms_pdu, strlen(sms_pdu));
   2928     } else if (strStartsWith(s, "+CGEV:")) {
   2929         /* Really, we can ignore NW CLASS and ME CLASS events here,
   2930          * but right now we don't since extranous
   2931          * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
   2932          */
   2933         /* can't issue AT commands here -- call on main thread */
   2934         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
   2935 #ifdef WORKAROUND_FAKE_CGEV
   2936     } else if (strStartsWith(s, "+CME ERROR: 150")) {
   2937         RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
   2938 #endif /* WORKAROUND_FAKE_CGEV */
   2939     } else if (strStartsWith(s, "+CTEC: ")) {
   2940         int tech, mask;
   2941         switch (parse_technology_response(s, &tech, NULL))
   2942         {
   2943             case -1: // no argument could be parsed.
   2944                 ALOGE("invalid CTEC line %s\n", s);
   2945                 break;
   2946             case 1: // current mode correctly parsed
   2947             case 0: // preferred mode correctly parsed
   2948                 mask = 1 << tech;
   2949                 if (mask != MDM_GSM && mask != MDM_CDMA &&
   2950                      mask != MDM_WCDMA && mask != MDM_LTE) {
   2951                     ALOGE("Unknown technology %d\n", tech);
   2952                 } else {
   2953                     setRadioTechnology(sMdmInfo, tech);
   2954                 }
   2955                 break;
   2956         }
   2957     } else if (strStartsWith(s, "+CCSS: ")) {
   2958         int source = 0;
   2959         line = p = strdup(s);
   2960         if (!line) {
   2961             ALOGE("+CCSS: Unable to allocate memory");
   2962             return;
   2963         }
   2964         if (at_tok_start(&p) < 0) {
   2965             free(line);
   2966             return;
   2967         }
   2968         if (at_tok_nextint(&p, &source) < 0) {
   2969             ALOGE("invalid +CCSS response: %s", line);
   2970             free(line);
   2971             return;
   2972         }
   2973         SSOURCE(sMdmInfo) = source;
   2974         RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED,
   2975                                   &source, sizeof(source));
   2976     } else if (strStartsWith(s, "+WSOS: ")) {
   2977         char state = 0;
   2978         int unsol;
   2979         line = p = strdup(s);
   2980         if (!line) {
   2981             ALOGE("+WSOS: Unable to allocate memory");
   2982             return;
   2983         }
   2984         if (at_tok_start(&p) < 0) {
   2985             free(line);
   2986             return;
   2987         }
   2988         if (at_tok_nextbool(&p, &state) < 0) {
   2989             ALOGE("invalid +WSOS response: %s", line);
   2990             free(line);
   2991             return;
   2992         }
   2993         free(line);
   2994 
   2995         unsol = state ?
   2996                 RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE : RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE;
   2997 
   2998         RIL_onUnsolicitedResponse(unsol, NULL, 0);
   2999 
   3000     } else if (strStartsWith(s, "+WPRL: ")) {
   3001         int version = -1;
   3002         line = p = strdup(s);
   3003         if (!line) {
   3004             ALOGE("+WPRL: Unable to allocate memory");
   3005             return;
   3006         }
   3007         if (at_tok_start(&p) < 0) {
   3008             ALOGE("invalid +WPRL response: %s", s);
   3009             free(line);
   3010             return;
   3011         }
   3012         if (at_tok_nextint(&p, &version) < 0) {
   3013             ALOGE("invalid +WPRL response: %s", s);
   3014             free(line);
   3015             return;
   3016         }
   3017         free(line);
   3018         RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_PRL_CHANGED, &version, sizeof(version));
   3019     } else if (strStartsWith(s, "+CFUN: 0")) {
   3020         setRadioState(RADIO_STATE_OFF);
   3021     }
   3022 }
   3023 
   3024 /* Called on command or reader thread */
   3025 static void onATReaderClosed()
   3026 {
   3027     ALOGI("AT channel closed\n");
   3028     at_close();
   3029     s_closed = 1;
   3030 
   3031     setRadioState (RADIO_STATE_UNAVAILABLE);
   3032 }
   3033 
   3034 /* Called on command thread */
   3035 static void onATTimeout()
   3036 {
   3037     ALOGI("AT channel timeout; closing\n");
   3038     at_close();
   3039 
   3040     s_closed = 1;
   3041 
   3042     /* FIXME cause a radio reset here */
   3043 
   3044     setRadioState (RADIO_STATE_UNAVAILABLE);
   3045 }
   3046 
   3047 static void usage(char *s)
   3048 {
   3049 #ifdef RIL_SHLIB
   3050     fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
   3051 #else
   3052     fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
   3053     exit(-1);
   3054 #endif
   3055 }
   3056 
   3057 static void *
   3058 mainLoop(void *param)
   3059 {
   3060     int fd;
   3061     int ret;
   3062 
   3063     AT_DUMP("== ", "entering mainLoop()", -1 );
   3064     at_set_on_reader_closed(onATReaderClosed);
   3065     at_set_on_timeout(onATTimeout);
   3066 
   3067     for (;;) {
   3068         fd = -1;
   3069         while  (fd < 0) {
   3070             if (s_port > 0) {
   3071                 fd = socket_loopback_client(s_port, SOCK_STREAM);
   3072             } else if (s_device_socket) {
   3073                 if (!strcmp(s_device_path, "/dev/socket/qemud")) {
   3074                     /* Before trying to connect to /dev/socket/qemud (which is
   3075                      * now another "legacy" way of communicating with the
   3076                      * emulator), we will try to connecto to gsm service via
   3077                      * qemu pipe. */
   3078                     fd = qemu_pipe_open("qemud:gsm");
   3079                     if (fd < 0) {
   3080                         /* Qemu-specific control socket */
   3081                         fd = socket_local_client( "qemud",
   3082                                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
   3083                                                   SOCK_STREAM );
   3084                         if (fd >= 0 ) {
   3085                             char  answer[2];
   3086 
   3087                             if ( write(fd, "gsm", 3) != 3 ||
   3088                                  read(fd, answer, 2) != 2 ||
   3089                                  memcmp(answer, "OK", 2) != 0)
   3090                             {
   3091                                 close(fd);
   3092                                 fd = -1;
   3093                             }
   3094                        }
   3095                     }
   3096                 }
   3097                 else
   3098                     fd = socket_local_client( s_device_path,
   3099                                             ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
   3100                                             SOCK_STREAM );
   3101             } else if (s_device_path != NULL) {
   3102                 fd = open (s_device_path, O_RDWR);
   3103                 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
   3104                     /* disable echo on serial ports */
   3105                     struct termios  ios;
   3106                     tcgetattr( fd, &ios );
   3107                     ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
   3108                     tcsetattr( fd, TCSANOW, &ios );
   3109                 }
   3110             }
   3111 
   3112             if (fd < 0) {
   3113                 perror ("opening AT interface. retrying...");
   3114                 sleep(10);
   3115                 /* never returns */
   3116             }
   3117         }
   3118 
   3119         s_closed = 0;
   3120         ret = at_open(fd, onUnsolicited);
   3121 
   3122         if (ret < 0) {
   3123             ALOGE ("AT error %d on at_open\n", ret);
   3124             return 0;
   3125         }
   3126 
   3127         RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
   3128 
   3129         // Give initializeCallback a chance to dispatched, since
   3130         // we don't presently have a cancellation mechanism
   3131         sleep(1);
   3132 
   3133         waitForClose();
   3134         ALOGI("Re-opening after close");
   3135     }
   3136 }
   3137 
   3138 #ifdef RIL_SHLIB
   3139 
   3140 pthread_t s_tid_mainloop;
   3141 
   3142 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
   3143 {
   3144     int ret;
   3145     int fd = -1;
   3146     int opt;
   3147     pthread_attr_t attr;
   3148 
   3149     s_rilenv = env;
   3150 
   3151     while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
   3152         switch (opt) {
   3153             case 'p':
   3154                 s_port = atoi(optarg);
   3155                 if (s_port == 0) {
   3156                     usage(argv[0]);
   3157                     return NULL;
   3158                 }
   3159                 ALOGI("Opening loopback port %d\n", s_port);
   3160             break;
   3161 
   3162             case 'd':
   3163                 s_device_path = optarg;
   3164                 ALOGI("Opening tty device %s\n", s_device_path);
   3165             break;
   3166 
   3167             case 's':
   3168                 s_device_path   = optarg;
   3169                 s_device_socket = 1;
   3170                 ALOGI("Opening socket %s\n", s_device_path);
   3171             break;
   3172 
   3173             default:
   3174                 usage(argv[0]);
   3175                 return NULL;
   3176         }
   3177     }
   3178 
   3179     if (s_port < 0 && s_device_path == NULL) {
   3180         usage(argv[0]);
   3181         return NULL;
   3182     }
   3183 
   3184     sMdmInfo = calloc(1, sizeof(ModemInfo));
   3185     if (!sMdmInfo) {
   3186         ALOGE("Unable to alloc memory for ModemInfo");
   3187         return NULL;
   3188     }
   3189     pthread_attr_init (&attr);
   3190     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   3191     ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
   3192 
   3193     return &s_callbacks;
   3194 }
   3195 #else /* RIL_SHLIB */
   3196 int main (int argc, char **argv)
   3197 {
   3198     int ret;
   3199     int fd = -1;
   3200     int opt;
   3201 
   3202     while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
   3203         switch (opt) {
   3204             case 'p':
   3205                 s_port = atoi(optarg);
   3206                 if (s_port == 0) {
   3207                     usage(argv[0]);
   3208                 }
   3209                 ALOGI("Opening loopback port %d\n", s_port);
   3210             break;
   3211 
   3212             case 'd':
   3213                 s_device_path = optarg;
   3214                 ALOGI("Opening tty device %s\n", s_device_path);
   3215             break;
   3216 
   3217             case 's':
   3218                 s_device_path   = optarg;
   3219                 s_device_socket = 1;
   3220                 ALOGI("Opening socket %s\n", s_device_path);
   3221             break;
   3222 
   3223             default:
   3224                 usage(argv[0]);
   3225         }
   3226     }
   3227 
   3228     if (s_port < 0 && s_device_path == NULL) {
   3229         usage(argv[0]);
   3230     }
   3231 
   3232     RIL_register(&s_callbacks);
   3233 
   3234     mainLoop(NULL);
   3235 
   3236     return 0;
   3237 }
   3238 
   3239 #endif /* RIL_SHLIB */
   3240