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