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