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