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