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