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