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