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