reference-ril.c revision 4a24d11778bff3f2b4b99eb03b0dfafa6c3c059c
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.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
37#define LOG_TAG "RIL"
38#include <utils/Log.h>
39
40#define MAX_AT_RESPONSE 0x1000
41
42/* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
43#define PPP_TTY_PATH "/dev/omap_csmi_tty1"
44
45#ifdef USE_TI_COMMANDS
46
47// Enable a workaround
48// 1) Make incoming call, do not answer
49// 2) Hangup remote end
50// Expected: call should disappear from CLCC line
51// Actual: Call shows as "ACTIVE" before disappearing
52#define WORKAROUND_ERRONEOUS_ANSWER 1
53
54// Some varients of the TI stack do not support the +CGEV unsolicited
55// response. However, they seem to send an unsolicited +CME ERROR: 150
56#define WORKAROUND_FAKE_CGEV 1
57#endif
58
59static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
60static RIL_RadioState currentState();
61static int onSupports (int requestCode);
62static void onCancel (RIL_Token t);
63static const char *getVersion();
64static int isRadioOn();
65static int getSIMStatus();
66static void onDataCallListChanged(void *param);
67
68extern const char * requestToString(int request);
69
70/*** Static Variables ***/
71static const RIL_RadioFunctions s_callbacks = {
72    RIL_VERSION,
73    onRequest,
74    currentState,
75    onSupports,
76    onCancel,
77    getVersion
78};
79
80#ifdef RIL_SHLIB
81static const struct RIL_Env *s_rilenv;
82
83#define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
84#define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
85#define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
86#endif
87
88static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
89
90static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
91static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
92
93static int s_port = -1;
94static const char * s_device_path = NULL;
95static int          s_device_socket = 0;
96
97/* trigger change to this with s_state_cond */
98static int s_closed = 0;
99
100static int sFD;     /* file desc of AT channel */
101static char sATBuffer[MAX_AT_RESPONSE+1];
102static char *sATBufferCur = NULL;
103
104static const struct timeval TIMEVAL_SIMPOLL = {1,0};
105static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
106static const struct timeval TIMEVAL_0 = {0,0};
107
108#ifdef WORKAROUND_ERRONEOUS_ANSWER
109// Max number of times we'll try to repoll when we think
110// we have a AT+CLCC race condition
111#define REPOLL_CALLS_COUNT_MAX 4
112
113// Line index that was incoming or waiting at last poll, or -1 for none
114static int s_incomingOrWaitingLine = -1;
115// Number of times we've asked for a repoll of AT+CLCC
116static int s_repollCallsCount = 0;
117// Should we expect a call to be answered in the next CLCC?
118static int s_expectAnswer = 0;
119#endif /* WORKAROUND_ERRONEOUS_ANSWER */
120
121static void pollSIMState (void *param);
122static void setRadioState(RIL_RadioState newState);
123
124static int clccStateToRILState(int state, RIL_CallState *p_state)
125
126{
127    switch(state) {
128        case 0: *p_state = RIL_CALL_ACTIVE;   return 0;
129        case 1: *p_state = RIL_CALL_HOLDING;  return 0;
130        case 2: *p_state = RIL_CALL_DIALING;  return 0;
131        case 3: *p_state = RIL_CALL_ALERTING; return 0;
132        case 4: *p_state = RIL_CALL_INCOMING; return 0;
133        case 5: *p_state = RIL_CALL_WAITING;  return 0;
134        default: return -1;
135    }
136}
137
138/**
139 * Note: directly modified line and has *p_call point directly into
140 * modified line
141 */
142static int callFromCLCCLine(char *line, RIL_CallOld *p_call)
143{
144        //+CLCC: 1,0,2,0,0,\"+18005551212\",145
145        //     index,isMT,state,mode,isMpty(,number,TOA)?
146
147    int err;
148    int state;
149    int mode;
150
151    err = at_tok_start(&line);
152    if (err < 0) goto error;
153
154    err = at_tok_nextint(&line, &(p_call->index));
155    if (err < 0) goto error;
156
157    err = at_tok_nextbool(&line, &(p_call->isMT));
158    if (err < 0) goto error;
159
160    err = at_tok_nextint(&line, &state);
161    if (err < 0) goto error;
162
163    err = clccStateToRILState(state, &(p_call->state));
164    if (err < 0) goto error;
165
166    err = at_tok_nextint(&line, &mode);
167    if (err < 0) goto error;
168
169    p_call->isVoice = (mode == 0);
170
171    err = at_tok_nextbool(&line, &(p_call->isMpty));
172    if (err < 0) goto error;
173
174    if (at_tok_hasmore(&line)) {
175        err = at_tok_nextstr(&line, &(p_call->number));
176
177        /* tolerate null here */
178        if (err < 0) return 0;
179
180        // Some lame implementations return strings
181        // like "NOT AVAILABLE" in the CLCC line
182        if (p_call->number != NULL
183            && 0 == strspn(p_call->number, "+0123456789")
184        ) {
185            p_call->number = NULL;
186        }
187
188        err = at_tok_nextint(&line, &p_call->toa);
189        if (err < 0) goto error;
190    }
191
192    return 0;
193
194error:
195    LOGE("invalid CLCC line\n");
196    return -1;
197}
198
199
200/** do post-AT+CFUN=1 initialization */
201static void onRadioPowerOn()
202{
203#ifdef USE_TI_COMMANDS
204    /*  Must be after CFUN=1 */
205    /*  TI specific -- notifications for CPHS things such */
206    /*  as CPHS message waiting indicator */
207
208    at_send_command("AT%CPHS=1", NULL);
209
210    /*  TI specific -- enable NITZ unsol notifs */
211    at_send_command("AT%CTZV=1", NULL);
212#endif
213
214    pollSIMState(NULL);
215}
216
217/** do post- SIM ready initialization */
218static void onSIMReady()
219{
220    at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
221    /*
222     * Always send SMS messages directly to the TE
223     *
224     * mode = 1 // discard when link is reserved (link should never be
225     *             reserved)
226     * mt = 2   // most messages routed to TE
227     * bm = 2   // new cell BM's routed to TE
228     * ds = 1   // Status reports routed to TE
229     * bfr = 1  // flush buffer
230     */
231    at_send_command("AT+CNMI=1,2,2,1,1", NULL);
232}
233
234static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
235{
236    int onOff;
237
238    int err;
239    ATResponse *p_response = NULL;
240
241    assert (datalen >= sizeof(int *));
242    onOff = ((int *)data)[0];
243
244    if (onOff == 0 && sState != RADIO_STATE_OFF) {
245        err = at_send_command("AT+CFUN=0", &p_response);
246       if (err < 0 || p_response->success == 0) goto error;
247        setRadioState(RADIO_STATE_OFF);
248    } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
249        err = at_send_command("AT+CFUN=1", &p_response);
250        if (err < 0|| p_response->success == 0) {
251            // Some stacks return an error when there is no SIM,
252            // but they really turn the RF portion on
253            // So, if we get an error, let's check to see if it
254            // turned on anyway
255
256            if (isRadioOn() != 1) {
257                goto error;
258            }
259        }
260        setRadioState(RADIO_STATE_SIM_NOT_READY);
261    }
262
263    at_response_free(p_response);
264    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
265    return;
266error:
267    at_response_free(p_response);
268    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
269}
270
271static void requestOrSendDataCallList(RIL_Token *t);
272
273static void onDataCallListChanged(void *param)
274{
275    requestOrSendDataCallList(NULL);
276}
277
278static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
279{
280    requestOrSendDataCallList(&t);
281}
282
283static void requestOrSendDataCallList(RIL_Token *t)
284{
285    ATResponse *p_response;
286    ATLine *p_cur;
287    int err;
288    int n = 0;
289    char *out;
290
291    err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
292    if (err != 0 || p_response->success == 0) {
293        if (t != NULL)
294            RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
295        else
296            RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
297                                      NULL, 0);
298        return;
299    }
300
301    for (p_cur = p_response->p_intermediates; p_cur != NULL;
302         p_cur = p_cur->p_next)
303        n++;
304
305    RIL_Data_Call_Response *responses =
306        alloca(n * sizeof(RIL_Data_Call_Response));
307
308    int i;
309    for (i = 0; i < n; i++) {
310        responses[i].cid = -1;
311        responses[i].active = -1;
312        responses[i].type = "";
313        responses[i].apn = "";
314        responses[i].address = "";
315    }
316
317    RIL_Data_Call_Response *response = responses;
318    for (p_cur = p_response->p_intermediates; p_cur != NULL;
319         p_cur = p_cur->p_next) {
320        char *line = p_cur->line;
321
322        err = at_tok_start(&line);
323        if (err < 0)
324            goto error;
325
326        err = at_tok_nextint(&line, &response->cid);
327        if (err < 0)
328            goto error;
329
330        err = at_tok_nextint(&line, &response->active);
331        if (err < 0)
332            goto error;
333
334        response++;
335    }
336
337    at_response_free(p_response);
338
339    err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
340    if (err != 0 || p_response->success == 0) {
341        if (t != NULL)
342            RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
343        else
344            RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
345                                      NULL, 0);
346        return;
347    }
348
349    for (p_cur = p_response->p_intermediates; p_cur != NULL;
350         p_cur = p_cur->p_next) {
351        char *line = p_cur->line;
352        int cid;
353        char *type;
354        char *apn;
355        char *address;
356
357
358        err = at_tok_start(&line);
359        if (err < 0)
360            goto error;
361
362        err = at_tok_nextint(&line, &cid);
363        if (err < 0)
364            goto error;
365
366        for (i = 0; i < n; i++) {
367            if (responses[i].cid == cid)
368                break;
369        }
370
371        if (i >= n) {
372            /* details for a context we didn't hear about in the last request */
373            continue;
374        }
375
376        err = at_tok_nextstr(&line, &out);
377        if (err < 0)
378            goto error;
379
380        responses[i].type = alloca(strlen(out) + 1);
381        strcpy(responses[i].type, out);
382
383        err = at_tok_nextstr(&line, &out);
384        if (err < 0)
385            goto error;
386
387        responses[i].apn = alloca(strlen(out) + 1);
388        strcpy(responses[i].apn, out);
389
390        err = at_tok_nextstr(&line, &out);
391        if (err < 0)
392            goto error;
393
394        responses[i].address = alloca(strlen(out) + 1);
395        strcpy(responses[i].address, out);
396    }
397
398    at_response_free(p_response);
399
400    if (t != NULL)
401        RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
402                              n * sizeof(RIL_Data_Call_Response));
403    else
404        RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
405                                  responses,
406                                  n * sizeof(RIL_Data_Call_Response));
407
408    return;
409
410error:
411    if (t != NULL)
412        RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
413    else
414        RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
415                                  NULL, 0);
416
417    at_response_free(p_response);
418}
419
420static void requestQueryNetworkSelectionMode(
421                void *data, size_t datalen, RIL_Token t)
422{
423    int err;
424    ATResponse *p_response = NULL;
425    int response = 0;
426    char *line;
427
428    err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
429
430    if (err < 0 || p_response->success == 0) {
431        goto error;
432    }
433
434    line = p_response->p_intermediates->line;
435
436    err = at_tok_start(&line);
437
438    if (err < 0) {
439        goto error;
440    }
441
442    err = at_tok_nextint(&line, &response);
443
444    if (err < 0) {
445        goto error;
446    }
447
448    RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
449    at_response_free(p_response);
450    return;
451error:
452    at_response_free(p_response);
453    LOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
454    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
455}
456
457static void sendCallStateChanged(void *param)
458{
459    RIL_onUnsolicitedResponse (
460        RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
461        NULL, 0);
462}
463
464static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
465{
466    int err;
467    ATResponse *p_response;
468    ATLine *p_cur;
469    int countCalls;
470    int countValidCalls;
471    RIL_CallOld *p_calls;
472    RIL_CallOld **pp_calls;
473    int i;
474    int needRepoll = 0;
475
476#ifdef WORKAROUND_ERRONEOUS_ANSWER
477    int prevIncomingOrWaitingLine;
478
479    prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
480    s_incomingOrWaitingLine = -1;
481#endif /*WORKAROUND_ERRONEOUS_ANSWER*/
482
483    err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
484
485    if (err != 0 || p_response->success == 0) {
486        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
487        return;
488    }
489
490    /* count the calls */
491    for (countCalls = 0, p_cur = p_response->p_intermediates
492            ; p_cur != NULL
493            ; p_cur = p_cur->p_next
494    ) {
495        countCalls++;
496    }
497
498    /* yes, there's an array of pointers and then an array of structures */
499
500    pp_calls = (RIL_CallOld **)alloca(countCalls * sizeof(RIL_CallOld *));
501    p_calls = (RIL_CallOld *)alloca(countCalls * sizeof(RIL_CallOld));
502    memset (p_calls, 0, countCalls * sizeof(RIL_CallOld));
503
504    /* init the pointer array */
505    for(i = 0; i < countCalls ; i++) {
506        pp_calls[i] = &(p_calls[i]);
507    }
508
509    for (countValidCalls = 0, p_cur = p_response->p_intermediates
510            ; p_cur != NULL
511            ; p_cur = p_cur->p_next
512    ) {
513        err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
514
515        if (err != 0) {
516            continue;
517        }
518
519#ifdef WORKAROUND_ERRONEOUS_ANSWER
520        if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
521            || p_calls[countValidCalls].state == RIL_CALL_WAITING
522        ) {
523            s_incomingOrWaitingLine = p_calls[countValidCalls].index;
524        }
525#endif /*WORKAROUND_ERRONEOUS_ANSWER*/
526
527        if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
528            && p_calls[countValidCalls].state != RIL_CALL_HOLDING
529        ) {
530            needRepoll = 1;
531        }
532
533        countValidCalls++;
534    }
535
536#ifdef WORKAROUND_ERRONEOUS_ANSWER
537    // Basically:
538    // A call was incoming or waiting
539    // Now it's marked as active
540    // But we never answered it
541    //
542    // This is probably a bug, and the call will probably
543    // disappear from the call list in the next poll
544    if (prevIncomingOrWaitingLine >= 0
545            && s_incomingOrWaitingLine < 0
546            && s_expectAnswer == 0
547    ) {
548        for (i = 0; i < countValidCalls ; i++) {
549
550            if (p_calls[i].index == prevIncomingOrWaitingLine
551                    && p_calls[i].state == RIL_CALL_ACTIVE
552                    && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
553            ) {
554                LOGI(
555                    "Hit WORKAROUND_ERRONOUS_ANSWER case."
556                    " Repoll count: %d\n", s_repollCallsCount);
557                s_repollCallsCount++;
558                goto error;
559            }
560        }
561    }
562
563    s_expectAnswer = 0;
564    s_repollCallsCount = 0;
565#endif /*WORKAROUND_ERRONEOUS_ANSWER*/
566
567    RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
568            countValidCalls * sizeof (RIL_CallOld *));
569
570    at_response_free(p_response);
571
572#ifdef POLL_CALL_STATE
573    if (countValidCalls) {  // We don't seem to get a "NO CARRIER" message from
574                            // smd, so we're forced to poll until the call ends.
575#else
576    if (needRepoll) {
577#endif
578        RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
579    }
580
581    return;
582error:
583    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
584    at_response_free(p_response);
585}
586
587static void requestDial(void *data, size_t datalen, RIL_Token t)
588{
589    RIL_Dial *p_dial;
590    char *cmd;
591    const char *clir;
592    int ret;
593
594    p_dial = (RIL_Dial *)data;
595
596    switch (p_dial->clir) {
597        case 1: clir = "I"; break;  /*invocation*/
598        case 2: clir = "i"; break;  /*suppression*/
599        default:
600        case 0: clir = ""; break;   /*subscription default*/
601    }
602
603    asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
604
605    ret = at_send_command(cmd, NULL);
606
607    free(cmd);
608
609    /* success or failure is ignored by the upper layer here.
610       it will call GET_CURRENT_CALLS and determine success that way */
611    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
612}
613
614static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
615{
616    RIL_SMS_WriteArgs *p_args;
617    char *cmd;
618    int length;
619    int err;
620    ATResponse *p_response = NULL;
621
622    p_args = (RIL_SMS_WriteArgs *)data;
623
624    length = strlen(p_args->pdu)/2;
625    asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
626
627    err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
628
629    if (err != 0 || p_response->success == 0) goto error;
630
631    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
632    at_response_free(p_response);
633
634    return;
635error:
636    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
637    at_response_free(p_response);
638}
639
640static void requestHangup(void *data, size_t datalen, RIL_Token t)
641{
642    int *p_line;
643
644    int ret;
645    char *cmd;
646
647    p_line = (int *)data;
648
649    // 3GPP 22.030 6.5.5
650    // "Releases a specific active call X"
651    asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
652
653    ret = at_send_command(cmd, NULL);
654
655    free(cmd);
656
657    /* success or failure is ignored by the upper layer here.
658       it will call GET_CURRENT_CALLS and determine success that way */
659    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
660}
661
662static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
663{
664    ATResponse *p_response = NULL;
665    int err;
666    int response[2];
667    char *line;
668
669    err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
670
671    if (err < 0 || p_response->success == 0) {
672        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
673        goto error;
674    }
675
676    line = p_response->p_intermediates->line;
677
678    err = at_tok_start(&line);
679    if (err < 0) goto error;
680
681    err = at_tok_nextint(&line, &(response[0]));
682    if (err < 0) goto error;
683
684    err = at_tok_nextint(&line, &(response[1]));
685    if (err < 0) goto error;
686
687    RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
688
689    at_response_free(p_response);
690    return;
691
692error:
693    LOGE("requestSignalStrength must never return an error when radio is on");
694    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
695    at_response_free(p_response);
696}
697
698static void requestRegistrationState(int request, void *data,
699                                        size_t datalen, RIL_Token t)
700{
701    int err;
702    int response[4];
703    char * responseStr[4];
704    ATResponse *p_response = NULL;
705    const char *cmd;
706    const char *prefix;
707    char *line, *p;
708    int commas;
709    int skip;
710    int count = 3;
711
712
713    if (request == RIL_REQUEST_REGISTRATION_STATE) {
714        cmd = "AT+CREG?";
715        prefix = "+CREG:";
716    } else if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
717        cmd = "AT+CGREG?";
718        prefix = "+CGREG:";
719    } else {
720        assert(0);
721        goto error;
722    }
723
724    err = at_send_command_singleline(cmd, prefix, &p_response);
725
726    if (err != 0) goto error;
727
728    line = p_response->p_intermediates->line;
729
730    err = at_tok_start(&line);
731    if (err < 0) goto error;
732
733    /* Ok you have to be careful here
734     * The solicited version of the CREG response is
735     * +CREG: n, stat, [lac, cid]
736     * and the unsolicited version is
737     * +CREG: stat, [lac, cid]
738     * The <n> parameter is basically "is unsolicited creg on?"
739     * which it should always be
740     *
741     * Now we should normally get the solicited version here,
742     * but the unsolicited version could have snuck in
743     * so we have to handle both
744     *
745     * Also since the LAC and CID are only reported when registered,
746     * we can have 1, 2, 3, or 4 arguments here
747     *
748     * finally, a +CGREG: answer may have a fifth value that corresponds
749     * to the network type, as in;
750     *
751     *   +CGREG: n, stat [,lac, cid [,networkType]]
752     */
753
754    /* count number of commas */
755    commas = 0;
756    for (p = line ; *p != '\0' ;p++) {
757        if (*p == ',') commas++;
758    }
759
760    switch (commas) {
761        case 0: /* +CREG: <stat> */
762            err = at_tok_nextint(&line, &response[0]);
763            if (err < 0) goto error;
764            response[1] = -1;
765            response[2] = -1;
766        break;
767
768        case 1: /* +CREG: <n>, <stat> */
769            err = at_tok_nextint(&line, &skip);
770            if (err < 0) goto error;
771            err = at_tok_nextint(&line, &response[0]);
772            if (err < 0) goto error;
773            response[1] = -1;
774            response[2] = -1;
775            if (err < 0) goto error;
776        break;
777
778        case 2: /* +CREG: <stat>, <lac>, <cid> */
779            err = at_tok_nextint(&line, &response[0]);
780            if (err < 0) goto error;
781            err = at_tok_nexthexint(&line, &response[1]);
782            if (err < 0) goto error;
783            err = at_tok_nexthexint(&line, &response[2]);
784            if (err < 0) goto error;
785        break;
786        case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
787            err = at_tok_nextint(&line, &skip);
788            if (err < 0) goto error;
789            err = at_tok_nextint(&line, &response[0]);
790            if (err < 0) goto error;
791            err = at_tok_nexthexint(&line, &response[1]);
792            if (err < 0) goto error;
793            err = at_tok_nexthexint(&line, &response[2]);
794            if (err < 0) goto error;
795        break;
796        /* special case for CGREG, there is a fourth parameter
797         * that is the network type (unknown/gprs/edge/umts)
798         */
799        case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
800            err = at_tok_nextint(&line, &skip);
801            if (err < 0) goto error;
802            err = at_tok_nextint(&line, &response[0]);
803            if (err < 0) goto error;
804            err = at_tok_nexthexint(&line, &response[1]);
805            if (err < 0) goto error;
806            err = at_tok_nexthexint(&line, &response[2]);
807            if (err < 0) goto error;
808            err = at_tok_nexthexint(&line, &response[3]);
809            if (err < 0) goto error;
810            count = 4;
811        break;
812        default:
813            goto error;
814    }
815
816    asprintf(&responseStr[0], "%d", response[0]);
817    asprintf(&responseStr[1], "%d", response[1]);
818    asprintf(&responseStr[2], "%d", response[2]);
819
820    if (count > 3)
821        asprintf(&responseStr[3], "%d", response[3]);
822
823    RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
824    at_response_free(p_response);
825
826    return;
827error:
828    LOGE("requestRegistrationState must never return an error when radio is on");
829    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
830    at_response_free(p_response);
831}
832
833static void requestOperator(void *data, size_t datalen, RIL_Token t)
834{
835    int err;
836    int i;
837    int skip;
838    ATLine *p_cur;
839    char *response[3];
840
841    memset(response, 0, sizeof(response));
842
843    ATResponse *p_response = NULL;
844
845    err = at_send_command_multiline(
846        "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
847        "+COPS:", &p_response);
848
849    /* we expect 3 lines here:
850     * +COPS: 0,0,"T - Mobile"
851     * +COPS: 0,1,"TMO"
852     * +COPS: 0,2,"310170"
853     */
854
855    if (err != 0) goto error;
856
857    for (i = 0, p_cur = p_response->p_intermediates
858            ; p_cur != NULL
859            ; p_cur = p_cur->p_next, i++
860    ) {
861        char *line = p_cur->line;
862
863        err = at_tok_start(&line);
864        if (err < 0) goto error;
865
866        err = at_tok_nextint(&line, &skip);
867        if (err < 0) goto error;
868
869        // If we're unregistered, we may just get
870        // a "+COPS: 0" response
871        if (!at_tok_hasmore(&line)) {
872            response[i] = NULL;
873            continue;
874        }
875
876        err = at_tok_nextint(&line, &skip);
877        if (err < 0) goto error;
878
879        // a "+COPS: 0, n" response is also possible
880        if (!at_tok_hasmore(&line)) {
881            response[i] = NULL;
882            continue;
883        }
884
885        err = at_tok_nextstr(&line, &(response[i]));
886        if (err < 0) goto error;
887    }
888
889    if (i != 3) {
890        /* expect 3 lines exactly */
891        goto error;
892    }
893
894    RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
895    at_response_free(p_response);
896
897    return;
898error:
899    LOGE("requestOperator must not return error when radio is on");
900    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
901    at_response_free(p_response);
902}
903
904static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
905{
906    int err;
907    const char *smsc;
908    const char *pdu;
909    int tpLayerLength;
910    char *cmd1, *cmd2;
911    RIL_SMS_Response response;
912    ATResponse *p_response = NULL;
913
914    smsc = ((const char **)data)[0];
915    pdu = ((const char **)data)[1];
916
917    tpLayerLength = strlen(pdu)/2;
918
919    // "NULL for default SMSC"
920    if (smsc == NULL) {
921        smsc= "00";
922    }
923
924    asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
925    asprintf(&cmd2, "%s%s", smsc, pdu);
926
927    err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
928
929    if (err != 0 || p_response->success == 0) goto error;
930
931    memset(&response, 0, sizeof(response));
932
933    /* FIXME fill in messageRef and ackPDU */
934
935    RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
936    at_response_free(p_response);
937
938    return;
939error:
940    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
941    at_response_free(p_response);
942}
943
944static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
945{
946    const char *apn;
947    char *cmd;
948    int err;
949    ATResponse *p_response = NULL;
950    char *response[2] = { "1", PPP_TTY_PATH };
951
952    apn = ((const char **)data)[2];
953
954#ifdef USE_TI_COMMANDS
955    // Config for multislot class 10 (probably default anyway eh?)
956    err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
957                        NULL);
958
959    err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
960#endif /* USE_TI_COMMANDS */
961
962    int fd, qmistatus;
963    size_t cur = 0;
964    size_t len;
965    ssize_t written, rlen;
966    char status[32] = {0};
967    int retry = 10;
968
969    LOGD("requesting data connection to APN '%s'", apn);
970
971    fd = open ("/dev/qmi", O_RDWR);
972    if (fd >= 0) { /* the device doesn't exist on the emulator */
973
974	    LOGD("opened the qmi device\n");
975	    asprintf(&cmd, "up:%s", apn);
976	    len = strlen(cmd);
977
978	    while (cur < len) {
979		    do {
980	            written = write (fd, cmd + cur, len - cur);
981	        } while (written < 0 && errno == EINTR);
982
983	        if (written < 0) {
984                LOGE("### ERROR writing to /dev/qmi");
985                close(fd);
986                goto error;
987            }
988
989            cur += written;
990        }
991
992        // wait for interface to come online
993
994        do {
995            sleep(1);
996            do {
997                rlen = read(fd, status, 31);
998            } while (rlen < 0 && errno == EINTR);
999
1000            if (rlen < 0) {
1001                LOGE("### ERROR reading from /dev/qmi");
1002                close(fd);
1003                goto error;
1004            } else {
1005                status[rlen] = '\0';
1006                LOGD("### status: %s", status);
1007            }
1008        } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
1009
1010        close(fd);
1011
1012        if (retry == 0) {
1013            LOGE("### Failed to get data connection up\n");
1014	        goto error;
1015		}
1016
1017        qmistatus = system("netcfg rmnet0 dhcp");
1018
1019        LOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus);
1020
1021	    if (qmistatus < 0) goto error;
1022
1023	} else {
1024
1025        asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
1026	    //FIXME check for error here
1027	    err = at_send_command(cmd, NULL);
1028	    free(cmd);
1029
1030	    // Set required QoS params to default
1031	    err = at_send_command("AT+CGQREQ=1", NULL);
1032
1033	    // Set minimum QoS params to default
1034	    err = at_send_command("AT+CGQMIN=1", NULL);
1035
1036	    // packet-domain event reporting
1037	    err = at_send_command("AT+CGEREP=1,0", NULL);
1038
1039	    // Hangup anything that's happening there now
1040	    err = at_send_command("AT+CGACT=1,0", NULL);
1041
1042	    // Start data on PDP context 1
1043	    err = at_send_command("ATD*99***1#", &p_response);
1044
1045	    if (err < 0 || p_response->success == 0) {
1046	        goto error;
1047	    }
1048    }
1049
1050    RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1051    at_response_free(p_response);
1052
1053    return;
1054error:
1055    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1056    at_response_free(p_response);
1057
1058}
1059
1060static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
1061{
1062    int ackSuccess;
1063    int err;
1064
1065    ackSuccess = ((int *)data)[0];
1066
1067    if (ackSuccess == 1) {
1068        err = at_send_command("AT+CNMA=1", NULL);
1069    } else if (ackSuccess == 0)  {
1070        err = at_send_command("AT+CNMA=2", NULL);
1071    } else {
1072        LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
1073        goto error;
1074    }
1075
1076    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1077error:
1078    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1079
1080}
1081
1082static void  requestSIM_IO(void *data, size_t datalen, RIL_Token t)
1083{
1084    ATResponse *p_response = NULL;
1085    RIL_SIM_IO_Response sr;
1086    int err;
1087    char *cmd = NULL;
1088    RIL_SIM_IO *p_args;
1089    char *line;
1090
1091    memset(&sr, 0, sizeof(sr));
1092
1093    p_args = (RIL_SIM_IO *)data;
1094
1095    /* FIXME handle pin2 */
1096
1097    if (p_args->data == NULL) {
1098        asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
1099                    p_args->command, p_args->fileid,
1100                    p_args->p1, p_args->p2, p_args->p3);
1101    } else {
1102        asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
1103                    p_args->command, p_args->fileid,
1104                    p_args->p1, p_args->p2, p_args->p3, p_args->data);
1105    }
1106
1107    err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
1108
1109    if (err < 0 || p_response->success == 0) {
1110        goto error;
1111    }
1112
1113    line = p_response->p_intermediates->line;
1114
1115    err = at_tok_start(&line);
1116    if (err < 0) goto error;
1117
1118    err = at_tok_nextint(&line, &(sr.sw1));
1119    if (err < 0) goto error;
1120
1121    err = at_tok_nextint(&line, &(sr.sw2));
1122    if (err < 0) goto error;
1123
1124    if (at_tok_hasmore(&line)) {
1125        err = at_tok_nextstr(&line, &(sr.simResponse));
1126        if (err < 0) goto error;
1127    }
1128
1129    RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
1130    at_response_free(p_response);
1131    free(cmd);
1132
1133    return;
1134error:
1135    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1136    at_response_free(p_response);
1137    free(cmd);
1138
1139}
1140
1141static void  requestEnterSimPin(void*  data, size_t  datalen, RIL_Token  t)
1142{
1143    ATResponse   *p_response = NULL;
1144    int           err;
1145    char*         cmd = NULL;
1146    const char**  strings = (const char**)data;;
1147
1148    if ( datalen == sizeof(char*) ) {
1149        asprintf(&cmd, "AT+CPIN=%s", strings[0]);
1150    } else if ( datalen == 2*sizeof(char*) ) {
1151        asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
1152    } else
1153        goto error;
1154
1155    err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
1156    free(cmd);
1157
1158    if (err < 0 || p_response->success == 0) {
1159error:
1160        RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
1161    } else {
1162        RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1163    }
1164    at_response_free(p_response);
1165}
1166
1167
1168static void  requestSendUSSD(void *data, size_t datalen, RIL_Token t)
1169{
1170    const char *ussdRequest;
1171
1172    ussdRequest = (char *)(data);
1173
1174
1175    RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1176
1177// @@@ TODO
1178
1179}
1180
1181
1182/*** Callback methods from the RIL library to us ***/
1183
1184/**
1185 * Call from RIL to us to make a RIL_REQUEST
1186 *
1187 * Must be completed with a call to RIL_onRequestComplete()
1188 *
1189 * RIL_onRequestComplete() may be called from any thread, before or after
1190 * this function returns.
1191 *
1192 * Will always be called from the same thread, so returning here implies
1193 * that the radio is ready to process another command (whether or not
1194 * the previous command has completed).
1195 */
1196static void
1197onRequest (int request, void *data, size_t datalen, RIL_Token t)
1198{
1199    ATResponse *p_response;
1200    int err;
1201
1202    LOGD("onRequest: %s", requestToString(request));
1203
1204    /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
1205     * when RADIO_STATE_UNAVAILABLE.
1206     */
1207    if (sState == RADIO_STATE_UNAVAILABLE
1208        && request != RIL_REQUEST_GET_SIM_STATUS
1209    ) {
1210        RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1211        return;
1212    }
1213
1214    /* Ignore all non-power requests when RADIO_STATE_OFF
1215     * (except RIL_REQUEST_GET_SIM_STATUS)
1216     */
1217    if (sState == RADIO_STATE_OFF
1218        && !(request == RIL_REQUEST_RADIO_POWER
1219            || request == RIL_REQUEST_GET_SIM_STATUS)
1220    ) {
1221        RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1222        return;
1223    }
1224
1225    switch (request) {
1226        case RIL_REQUEST_GET_SIM_STATUS: {
1227            int simStatus;
1228
1229            simStatus = getSIMStatus();
1230
1231            RIL_onRequestComplete(t, RIL_E_SUCCESS, &simStatus, sizeof(simStatus));
1232            break;
1233        }
1234        case RIL_REQUEST_GET_CURRENT_CALLS:
1235            requestGetCurrentCalls(data, datalen, t);
1236            break;
1237        case RIL_REQUEST_DIAL:
1238            requestDial(data, datalen, t);
1239            break;
1240        case RIL_REQUEST_HANGUP:
1241            requestHangup(data, datalen, t);
1242            break;
1243        case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
1244            // 3GPP 22.030 6.5.5
1245            // "Releases all held calls or sets User Determined User Busy
1246            //  (UDUB) for a waiting call."
1247            at_send_command("AT+CHLD=0", NULL);
1248
1249            /* success or failure is ignored by the upper layer here.
1250               it will call GET_CURRENT_CALLS and determine success that way */
1251            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1252            break;
1253        case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
1254            // 3GPP 22.030 6.5.5
1255            // "Releases all active calls (if any exist) and accepts
1256            //  the other (held or waiting) call."
1257            at_send_command("AT+CHLD=1", NULL);
1258
1259            /* success or failure is ignored by the upper layer here.
1260               it will call GET_CURRENT_CALLS and determine success that way */
1261            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1262            break;
1263        case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
1264            // 3GPP 22.030 6.5.5
1265            // "Places all active calls (if any exist) on hold and accepts
1266            //  the other (held or waiting) call."
1267            at_send_command("AT+CHLD=2", NULL);
1268
1269#ifdef WORKAROUND_ERRONEOUS_ANSWER
1270            s_expectAnswer = 1;
1271#endif /* WORKAROUND_ERRONEOUS_ANSWER */
1272
1273            /* success or failure is ignored by the upper layer here.
1274               it will call GET_CURRENT_CALLS and determine success that way */
1275            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1276            break;
1277        case RIL_REQUEST_ANSWER:
1278            at_send_command("ATA", NULL);
1279
1280#ifdef WORKAROUND_ERRONEOUS_ANSWER
1281            s_expectAnswer = 1;
1282#endif /* WORKAROUND_ERRONEOUS_ANSWER */
1283
1284            /* success or failure is ignored by the upper layer here.
1285               it will call GET_CURRENT_CALLS and determine success that way */
1286            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1287            break;
1288        case RIL_REQUEST_CONFERENCE:
1289            // 3GPP 22.030 6.5.5
1290            // "Adds a held call to the conversation"
1291            at_send_command("AT+CHLD=3", NULL);
1292
1293            /* success or failure is ignored by the upper layer here.
1294               it will call GET_CURRENT_CALLS and determine success that way */
1295            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1296            break;
1297        case RIL_REQUEST_UDUB:
1298            /* user determined user busy */
1299            /* sometimes used: ATH */
1300            at_send_command("ATH", NULL);
1301
1302            /* success or failure is ignored by the upper layer here.
1303               it will call GET_CURRENT_CALLS and determine success that way */
1304            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1305            break;
1306
1307        case RIL_REQUEST_SEPARATE_CONNECTION:
1308            {
1309                char  cmd[12];
1310                int   party = ((int*)data)[0];
1311
1312                // Make sure that party is in a valid range.
1313                // (Note: The Telephony middle layer imposes a range of 1 to 7.
1314                // It's sufficient for us to just make sure it's single digit.)
1315                if (party > 0 && party < 10) {
1316                    sprintf(cmd, "AT+CHLD=2%d", party);
1317                    at_send_command(cmd, NULL);
1318                    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1319                } else {
1320                    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1321                }
1322            }
1323            break;
1324
1325        case RIL_REQUEST_SIGNAL_STRENGTH:
1326            requestSignalStrength(data, datalen, t);
1327            break;
1328        case RIL_REQUEST_REGISTRATION_STATE:
1329        case RIL_REQUEST_GPRS_REGISTRATION_STATE:
1330            requestRegistrationState(request, data, datalen, t);
1331            break;
1332        case RIL_REQUEST_OPERATOR:
1333            requestOperator(data, datalen, t);
1334            break;
1335        case RIL_REQUEST_RADIO_POWER:
1336            requestRadioPower(data, datalen, t);
1337            break;
1338        case RIL_REQUEST_DTMF: {
1339            char c = ((char *)data)[0];
1340            char *cmd;
1341            asprintf(&cmd, "AT+VTS=%c", (int)c);
1342            at_send_command(cmd, NULL);
1343            free(cmd);
1344            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1345            break;
1346        }
1347        case RIL_REQUEST_SEND_SMS:
1348            requestSendSMS(data, datalen, t);
1349            break;
1350        case RIL_REQUEST_SETUP_DATA_CALL:
1351            requestSetupDataCall(data, datalen, t);
1352            break;
1353        case RIL_REQUEST_SMS_ACKNOWLEDGE:
1354            requestSMSAcknowledge(data, datalen, t);
1355            break;
1356
1357        case RIL_REQUEST_GET_IMSI:
1358            p_response = NULL;
1359            err = at_send_command_numeric("AT+CIMI", &p_response);
1360
1361            if (err < 0 || p_response->success == 0) {
1362                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1363            } else {
1364                RIL_onRequestComplete(t, RIL_E_SUCCESS,
1365                    p_response->p_intermediates->line, sizeof(char *));
1366            }
1367            at_response_free(p_response);
1368            break;
1369
1370        case RIL_REQUEST_GET_IMEI:
1371            p_response = NULL;
1372            err = at_send_command_numeric("AT+CGSN", &p_response);
1373
1374            if (err < 0 || p_response->success == 0) {
1375                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1376            } else {
1377                RIL_onRequestComplete(t, RIL_E_SUCCESS,
1378                    p_response->p_intermediates->line, sizeof(char *));
1379            }
1380            at_response_free(p_response);
1381            break;
1382
1383        case RIL_REQUEST_SIM_IO:
1384            requestSIM_IO(data,datalen,t);
1385            break;
1386
1387        case RIL_REQUEST_SEND_USSD:
1388            requestSendUSSD(data, datalen, t);
1389            break;
1390
1391        case RIL_REQUEST_CANCEL_USSD:
1392            p_response = NULL;
1393            err = at_send_command_numeric("AT+CUSD=2", &p_response);
1394
1395            if (err < 0 || p_response->success == 0) {
1396                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1397            } else {
1398                RIL_onRequestComplete(t, RIL_E_SUCCESS,
1399                    p_response->p_intermediates->line, sizeof(char *));
1400            }
1401            at_response_free(p_response);
1402            break;
1403
1404        case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
1405            at_send_command("AT+COPS=0", NULL);
1406            break;
1407
1408        case RIL_REQUEST_DATA_CALL_LIST:
1409            requestDataCallList(data, datalen, t);
1410            break;
1411
1412        case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
1413            requestQueryNetworkSelectionMode(data, datalen, t);
1414            break;
1415
1416        case RIL_REQUEST_OEM_HOOK_RAW:
1417            // echo back data
1418            RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1419            break;
1420
1421
1422        case RIL_REQUEST_OEM_HOOK_STRINGS: {
1423            int i;
1424            const char ** cur;
1425
1426            LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
1427
1428
1429            for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
1430                    i > 0 ; cur++, i --) {
1431                LOGD("> '%s'", *cur);
1432            }
1433
1434            // echo back strings
1435            RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1436            break;
1437        }
1438
1439        case RIL_REQUEST_WRITE_SMS_TO_SIM:
1440            requestWriteSmsToSim(data, datalen, t);
1441            break;
1442
1443        case RIL_REQUEST_DELETE_SMS_ON_SIM: {
1444            char * cmd;
1445            p_response = NULL;
1446            asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
1447            err = at_send_command(cmd, &p_response);
1448            free(cmd);
1449            if (err < 0 || p_response->success == 0) {
1450                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1451            } else {
1452                RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1453            }
1454            at_response_free(p_response);
1455            break;
1456        }
1457
1458        case RIL_REQUEST_ENTER_SIM_PIN:
1459        case RIL_REQUEST_ENTER_SIM_PUK:
1460        case RIL_REQUEST_ENTER_SIM_PIN2:
1461        case RIL_REQUEST_ENTER_SIM_PUK2:
1462        case RIL_REQUEST_CHANGE_SIM_PIN:
1463        case RIL_REQUEST_CHANGE_SIM_PIN2:
1464            requestEnterSimPin(data, datalen, t);
1465            break;
1466
1467        default:
1468            RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1469            break;
1470    }
1471}
1472
1473/**
1474 * Synchronous call from the RIL to us to return current radio state.
1475 * RADIO_STATE_UNAVAILABLE should be the initial state.
1476 */
1477static RIL_RadioState
1478currentState()
1479{
1480    return sState;
1481}
1482/**
1483 * Call from RIL to us to find out whether a specific request code
1484 * is supported by this implementation.
1485 *
1486 * Return 1 for "supported" and 0 for "unsupported"
1487 */
1488
1489static int
1490onSupports (int requestCode)
1491{
1492    //@@@ todo
1493
1494    return 1;
1495}
1496
1497static void onCancel (RIL_Token t)
1498{
1499    //@@@todo
1500
1501}
1502
1503static const char * getVersion(void)
1504{
1505    return "android reference-ril 1.0";
1506}
1507
1508static void
1509setRadioState(RIL_RadioState newState)
1510{
1511    RIL_RadioState oldState;
1512
1513    pthread_mutex_lock(&s_state_mutex);
1514
1515    oldState = sState;
1516
1517    if (s_closed > 0) {
1518        // If we're closed, the only reasonable state is
1519        // RADIO_STATE_UNAVAILABLE
1520        // This is here because things on the main thread
1521        // may attempt to change the radio state after the closed
1522        // event happened in another thread
1523        newState = RADIO_STATE_UNAVAILABLE;
1524    }
1525
1526    if (sState != newState || s_closed > 0) {
1527        sState = newState;
1528
1529        pthread_cond_broadcast (&s_state_cond);
1530    }
1531
1532    pthread_mutex_unlock(&s_state_mutex);
1533
1534
1535    /* do these outside of the mutex */
1536    if (sState != oldState) {
1537        RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
1538                                    NULL, 0);
1539
1540        /* FIXME onSimReady() and onRadioPowerOn() cannot be called
1541         * from the AT reader thread
1542         * Currently, this doesn't happen, but if that changes then these
1543         * will need to be dispatched on the request thread
1544         */
1545        if (sState == RADIO_STATE_SIM_READY) {
1546            onSIMReady();
1547        } else if (sState == RADIO_STATE_SIM_NOT_READY) {
1548            onRadioPowerOn();
1549        }
1550    }
1551}
1552
1553/** returns one of RIM_SIM_*. Returns RIL_SIM_NOT_READY on error */
1554static int
1555getSIMStatus()
1556{
1557    ATResponse *p_response = NULL;
1558    int err;
1559    int ret;
1560    char *cpinLine;
1561    char *cpinResult;
1562
1563    if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
1564        ret = RIL_SIM_NOT_READY;
1565        goto done;
1566    }
1567
1568    err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
1569
1570    if (err != 0) {
1571        ret = RIL_SIM_NOT_READY;
1572        goto done;
1573    }
1574
1575    switch (at_get_cme_error(p_response)) {
1576        case CME_SUCCESS:
1577            break;
1578
1579        case CME_SIM_NOT_INSERTED:
1580            ret = RIL_SIM_ABSENT;
1581            goto done;
1582
1583        default:
1584            ret = RIL_SIM_NOT_READY;
1585            goto done;
1586    }
1587
1588    /* CPIN? has succeeded, now look at the result */
1589
1590    cpinLine = p_response->p_intermediates->line;
1591    err = at_tok_start (&cpinLine);
1592
1593    if (err < 0) {
1594        ret = RIL_SIM_NOT_READY;
1595        goto done;
1596    }
1597
1598    err = at_tok_nextstr(&cpinLine, &cpinResult);
1599
1600    if (err < 0) {
1601        ret = RIL_SIM_NOT_READY;
1602        goto done;
1603    }
1604
1605    if (0 == strcmp (cpinResult, "SIM PIN")) {
1606        ret = RIL_SIM_PIN;
1607        goto done;
1608    } else if (0 == strcmp (cpinResult, "SIM PUK")) {
1609        ret = RIL_SIM_PUK;
1610        goto done;
1611    } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
1612        return RIL_SIM_NETWORK_PERSONALIZATION;
1613    } else if (0 != strcmp (cpinResult, "READY"))  {
1614        /* we're treating unsupported lock types as "sim absent" */
1615        ret = RIL_SIM_ABSENT;
1616        goto done;
1617    }
1618
1619    at_response_free(p_response);
1620    p_response = NULL;
1621    cpinResult = NULL;
1622
1623    ret = RIL_SIM_READY;
1624
1625done:
1626    at_response_free(p_response);
1627    return ret;
1628}
1629
1630
1631/**
1632 * SIM ready means any commands that access the SIM will work, including:
1633 *  AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
1634 *  (all SMS-related commands)
1635 */
1636
1637static void pollSIMState (void *param)
1638{
1639    ATResponse *p_response;
1640    int ret;
1641
1642    if (sState != RADIO_STATE_SIM_NOT_READY) {
1643        // no longer valid to poll
1644        return;
1645    }
1646
1647    switch(getSIMStatus()) {
1648        case RIL_SIM_ABSENT:
1649        case RIL_SIM_PIN:
1650        case RIL_SIM_PUK:
1651        case RIL_SIM_NETWORK_PERSONALIZATION:
1652        default:
1653            setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
1654        return;
1655
1656        case RIL_SIM_NOT_READY:
1657            RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
1658        return;
1659
1660        case RIL_SIM_READY:
1661            setRadioState(RADIO_STATE_SIM_READY);
1662        return;
1663    }
1664}
1665
1666/** returns 1 if on, 0 if off, and -1 on error */
1667static int isRadioOn()
1668{
1669    ATResponse *p_response = NULL;
1670    int err;
1671    char *line;
1672    char ret;
1673
1674    err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
1675
1676    if (err < 0 || p_response->success == 0) {
1677        // assume radio is off
1678        goto error;
1679    }
1680
1681    line = p_response->p_intermediates->line;
1682
1683    err = at_tok_start(&line);
1684    if (err < 0) goto error;
1685
1686    err = at_tok_nextbool(&line, &ret);
1687    if (err < 0) goto error;
1688
1689    at_response_free(p_response);
1690
1691    return (int)ret;
1692
1693error:
1694
1695    at_response_free(p_response);
1696    return -1;
1697}
1698
1699/**
1700 * Initialize everything that can be configured while we're still in
1701 * AT+CFUN=0
1702 */
1703static void initializeCallback(void *param)
1704{
1705    ATResponse *p_response = NULL;
1706    int err;
1707
1708    setRadioState (RADIO_STATE_OFF);
1709
1710    at_handshake();
1711
1712    /* note: we don't check errors here. Everything important will
1713       be handled in onATTimeout and onATReaderClosed */
1714
1715    /*  atchannel is tolerant of echo but it must */
1716    /*  have verbose result codes */
1717    at_send_command("ATE0Q0V1", NULL);
1718
1719    /*  No auto-answer */
1720    at_send_command("ATS0=0", NULL);
1721
1722    /*  Extended errors */
1723    at_send_command("AT+CMEE=1", NULL);
1724
1725    /*  Network registration events */
1726    err = at_send_command("AT+CREG=2", &p_response);
1727
1728    /* some handsets -- in tethered mode -- don't support CREG=2 */
1729    if (err < 0 || p_response->success == 0) {
1730        at_send_command("AT+CREG=1", NULL);
1731    }
1732
1733    at_response_free(p_response);
1734
1735    /*  GPRS registration events */
1736    at_send_command("AT+CGREG=1", NULL);
1737
1738    /*  Call Waiting notifications */
1739    at_send_command("AT+CCWA=1", NULL);
1740
1741    /*  Alternating voice/data off */
1742    at_send_command("AT+CMOD=0", NULL);
1743
1744    /*  Not muted */
1745    at_send_command("AT+CMUT=0", NULL);
1746
1747    /*  +CSSU unsolicited supp service notifications */
1748    at_send_command("AT+CSSN=0,1", NULL);
1749
1750    /*  no connected line identification */
1751    at_send_command("AT+COLP=0", NULL);
1752
1753    /*  HEX character set */
1754    at_send_command("AT+CSCS=\"HEX\"", NULL);
1755
1756    /*  USSD unsolicited */
1757    at_send_command("AT+CUSD=1", NULL);
1758
1759    /*  Enable +CGEV GPRS event notifications, but don't buffer */
1760    at_send_command("AT+CGEREP=1,0", NULL);
1761
1762    /*  SMS PDU mode */
1763    at_send_command("AT+CMGF=0", NULL);
1764
1765#ifdef USE_TI_COMMANDS
1766
1767    at_send_command("AT%CPI=3", NULL);
1768
1769    /*  TI specific -- notifications when SMS is ready (currently ignored) */
1770    at_send_command("AT%CSTAT=1", NULL);
1771
1772#endif /* USE_TI_COMMANDS */
1773
1774
1775    /* assume radio is off on error */
1776    if (isRadioOn() > 0) {
1777        setRadioState (RADIO_STATE_SIM_NOT_READY);
1778    }
1779}
1780
1781static void waitForClose()
1782{
1783    pthread_mutex_lock(&s_state_mutex);
1784
1785    while (s_closed == 0) {
1786        pthread_cond_wait(&s_state_cond, &s_state_mutex);
1787    }
1788
1789    pthread_mutex_unlock(&s_state_mutex);
1790}
1791
1792/**
1793 * Called by atchannel when an unsolicited line appears
1794 * This is called on atchannel's reader thread. AT commands may
1795 * not be issued here
1796 */
1797static void onUnsolicited (const char *s, const char *sms_pdu)
1798{
1799    char *line = NULL;
1800    int err;
1801
1802    /* Ignore unsolicited responses until we're initialized.
1803     * This is OK because the RIL library will poll for initial state
1804     */
1805    if (sState == RADIO_STATE_UNAVAILABLE) {
1806        return;
1807    }
1808
1809    if (strStartsWith(s, "%CTZV:")) {
1810        /* TI specific -- NITZ time */
1811        char *response;
1812
1813        line = strdup(s);
1814        at_tok_start(&line);
1815
1816        err = at_tok_nextstr(&line, &response);
1817
1818        if (err != 0) {
1819            LOGE("invalid NITZ line %s\n", s);
1820        } else {
1821            RIL_onUnsolicitedResponse (
1822                RIL_UNSOL_NITZ_TIME_RECEIVED,
1823                response, strlen(response));
1824        }
1825    } else if (strStartsWith(s,"+CRING:")
1826                || strStartsWith(s,"RING")
1827                || strStartsWith(s,"NO CARRIER")
1828                || strStartsWith(s,"+CCWA")
1829    ) {
1830        RIL_onUnsolicitedResponse (
1831            RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
1832            NULL, 0);
1833#ifdef WORKAROUND_FAKE_CGEV
1834        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
1835#endif /* WORKAROUND_FAKE_CGEV */
1836    } else if (strStartsWith(s,"+CREG:")
1837                || strStartsWith(s,"+CGREG:")
1838    ) {
1839        RIL_onUnsolicitedResponse (
1840            RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
1841            NULL, 0);
1842#ifdef WORKAROUND_FAKE_CGEV
1843        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1844#endif /* WORKAROUND_FAKE_CGEV */
1845    } else if (strStartsWith(s, "+CMT:")) {
1846        RIL_onUnsolicitedResponse (
1847            RIL_UNSOL_RESPONSE_NEW_SMS,
1848            sms_pdu, strlen(sms_pdu));
1849    } else if (strStartsWith(s, "+CDS:")) {
1850        RIL_onUnsolicitedResponse (
1851            RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
1852            sms_pdu, strlen(sms_pdu));
1853    } else if (strStartsWith(s, "+CGEV:")) {
1854        /* Really, we can ignore NW CLASS and ME CLASS events here,
1855         * but right now we don't since extranous
1856         * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
1857         */
1858        /* can't issue AT commands here -- call on main thread */
1859        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1860#ifdef WORKAROUND_FAKE_CGEV
1861    } else if (strStartsWith(s, "+CME ERROR: 150")) {
1862        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1863#endif /* WORKAROUND_FAKE_CGEV */
1864    }
1865}
1866
1867/* Called on command or reader thread */
1868static void onATReaderClosed()
1869{
1870    LOGI("AT channel closed\n");
1871    at_close();
1872    s_closed = 1;
1873
1874    setRadioState (RADIO_STATE_UNAVAILABLE);
1875}
1876
1877/* Called on command thread */
1878static void onATTimeout()
1879{
1880    LOGI("AT channel timeout; closing\n");
1881    at_close();
1882
1883    s_closed = 1;
1884
1885    /* FIXME cause a radio reset here */
1886
1887    setRadioState (RADIO_STATE_UNAVAILABLE);
1888}
1889
1890static void usage(char *s)
1891{
1892#ifdef RIL_SHLIB
1893    fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
1894#else
1895    fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
1896    exit(-1);
1897#endif
1898}
1899
1900static void *
1901mainLoop(void *param)
1902{
1903    int fd;
1904    int ret;
1905
1906    AT_DUMP("== ", "entering mainLoop()", -1 );
1907    at_set_on_reader_closed(onATReaderClosed);
1908    at_set_on_timeout(onATTimeout);
1909
1910    for (;;) {
1911        fd = -1;
1912        while  (fd < 0) {
1913            if (s_port > 0) {
1914                fd = socket_loopback_client(s_port, SOCK_STREAM);
1915            } else if (s_device_socket) {
1916                if (!strcmp(s_device_path, "/dev/socket/qemud")) {
1917                    /* Qemu-specific control socket */
1918                    fd = socket_local_client( "qemud",
1919                                              ANDROID_SOCKET_NAMESPACE_RESERVED,
1920                                              SOCK_STREAM );
1921                    if (fd >= 0 ) {
1922                        char  answer[2];
1923
1924                        if ( write(fd, "gsm", 3) != 3 ||
1925                             read(fd, answer, 2) != 2 ||
1926                             memcmp(answer, "OK", 2) != 0)
1927                        {
1928                            close(fd);
1929                            fd = -1;
1930                        }
1931                   }
1932                }
1933                else
1934                    fd = socket_local_client( s_device_path,
1935                                            ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
1936                                            SOCK_STREAM );
1937            } else if (s_device_path != NULL) {
1938                fd = open (s_device_path, O_RDWR);
1939                if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
1940                    /* disable echo on serial ports */
1941                    struct termios  ios;
1942                    tcgetattr( fd, &ios );
1943                    ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
1944                    tcsetattr( fd, TCSANOW, &ios );
1945                }
1946            }
1947
1948            if (fd < 0) {
1949                perror ("opening AT interface. retrying...");
1950                sleep(10);
1951                /* never returns */
1952            }
1953        }
1954
1955        s_closed = 0;
1956        ret = at_open(fd, onUnsolicited);
1957
1958        if (ret < 0) {
1959            LOGE ("AT error %d on at_open\n", ret);
1960            return 0;
1961        }
1962
1963        RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
1964
1965        // Give initializeCallback a chance to dispatched, since
1966        // we don't presently have a cancellation mechanism
1967        sleep(1);
1968
1969        waitForClose();
1970        LOGI("Re-opening after close");
1971    }
1972}
1973
1974#ifdef RIL_SHLIB
1975
1976pthread_t s_tid_mainloop;
1977
1978const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
1979{
1980    int ret;
1981    int fd = -1;
1982    int opt;
1983    pthread_attr_t attr;
1984
1985    s_rilenv = env;
1986
1987    while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
1988        switch (opt) {
1989            case 'p':
1990                s_port = atoi(optarg);
1991                if (s_port == 0) {
1992                    usage(argv[0]);
1993                    return NULL;
1994                }
1995                LOGI("Opening loopback port %d\n", s_port);
1996            break;
1997
1998            case 'd':
1999                s_device_path = optarg;
2000                LOGI("Opening tty device %s\n", s_device_path);
2001            break;
2002
2003            case 's':
2004                s_device_path   = optarg;
2005                s_device_socket = 1;
2006                LOGI("Opening socket %s\n", s_device_path);
2007            break;
2008
2009            default:
2010                usage(argv[0]);
2011                return NULL;
2012        }
2013    }
2014
2015    if (s_port < 0 && s_device_path == NULL) {
2016        usage(argv[0]);
2017        return NULL;
2018    }
2019
2020    pthread_attr_init (&attr);
2021    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2022    ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
2023
2024    return &s_callbacks;
2025}
2026#else /* RIL_SHLIB */
2027int main (int argc, char **argv)
2028{
2029    int ret;
2030    int fd = -1;
2031    int opt;
2032
2033    while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
2034        switch (opt) {
2035            case 'p':
2036                s_port = atoi(optarg);
2037                if (s_port == 0) {
2038                    usage(argv[0]);
2039                }
2040                LOGI("Opening loopback port %d\n", s_port);
2041            break;
2042
2043            case 'd':
2044                s_device_path = optarg;
2045                LOGI("Opening tty device %s\n", s_device_path);
2046            break;
2047
2048            case 's':
2049                s_device_path   = optarg;
2050                s_device_socket = 1;
2051                LOGI("Opening socket %s\n", s_device_path);
2052            break;
2053
2054            default:
2055                usage(argv[0]);
2056        }
2057    }
2058
2059    if (s_port < 0 && s_device_path == NULL) {
2060        usage(argv[0]);
2061    }
2062
2063    RIL_register(&s_callbacks);
2064
2065    mainLoop(NULL);
2066
2067    return 0;
2068}
2069
2070#endif /* RIL_SHLIB */
2071