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