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