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