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, ¤t, 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, ¤t, 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, ®istration)) 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