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