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 <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 ISIM_ABSENT = 12, 170 ISIM_NOT_READY = 13, 171 ISIM_READY = 14, 172 ISIM_PIN = 15, 173 ISIM_PUK = 16, 174 ISIM_NETWORK_PERSONALIZATION = 17, 175 } SIM_Status; 176 177 static void onRequest (int request, void *data, size_t datalen, RIL_Token t); 178 static RIL_RadioState currentState(); 179 static int onSupports (int requestCode); 180 static void onCancel (RIL_Token t); 181 static const char *getVersion(); 182 static int isRadioOn(); 183 static SIM_Status getSIMStatus(); 184 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status); 185 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status); 186 static void onDataCallListChanged(void *param); 187 188 extern const char * requestToString(int request); 189 190 /*** Static Variables ***/ 191 static const RIL_RadioFunctions s_callbacks = { 192 RIL_VERSION, 193 onRequest, 194 currentState, 195 onSupports, 196 onCancel, 197 getVersion 198 }; 199 200 #ifdef RIL_SHLIB 201 static const struct RIL_Env *s_rilenv; 202 203 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen) 204 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c) 205 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c) 206 #endif 207 208 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE; 209 210 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER; 211 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER; 212 213 static int s_port = -1; 214 static const char * s_device_path = NULL; 215 static int s_device_socket = 0; 216 217 /* trigger change to this with s_state_cond */ 218 static int s_closed = 0; 219 220 static int sFD; /* file desc of AT channel */ 221 static char sATBuffer[MAX_AT_RESPONSE+1]; 222 static char *sATBufferCur = NULL; 223 224 static const struct timeval TIMEVAL_SIMPOLL = {1,0}; 225 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000}; 226 static const struct timeval TIMEVAL_0 = {0,0}; 227 228 static int s_ims_registered = 0; // 0==unregistered 229 static int s_ims_services = 1; // & 0x1 == sms over ims supported 230 static int s_ims_format = 1; // FORMAT_3GPP(1) vs FORMAT_3GPP2(2); 231 static int s_ims_cause_retry = 0; // 1==causes sms over ims to temp fail 232 static int s_ims_cause_perm_failure = 0; // 1==causes sms over ims to permanent fail 233 static int s_ims_gsm_retry = 0; // 1==causes sms over gsm to temp fail 234 static int s_ims_gsm_fail = 0; // 1==causes sms over gsm to permanent fail 235 236 #ifdef WORKAROUND_ERRONEOUS_ANSWER 237 // Max number of times we'll try to repoll when we think 238 // we have a AT+CLCC race condition 239 #define REPOLL_CALLS_COUNT_MAX 4 240 241 // Line index that was incoming or waiting at last poll, or -1 for none 242 static int s_incomingOrWaitingLine = -1; 243 // Number of times we've asked for a repoll of AT+CLCC 244 static int s_repollCallsCount = 0; 245 // Should we expect a call to be answered in the next CLCC? 246 static int s_expectAnswer = 0; 247 #endif /* WORKAROUND_ERRONEOUS_ANSWER */ 248 249 250 static int s_cell_info_rate_ms = INT_MAX; 251 static int s_mcc = 0; 252 static int s_mnc = 0; 253 static int s_lac = 0; 254 static int s_cid = 0; 255 256 static void pollSIMState (void *param); 257 static void setRadioState(RIL_RadioState newState); 258 static void setRadioTechnology(ModemInfo *mdm, int newtech); 259 static int query_ctec(ModemInfo *mdm, int *current, int32_t *preferred); 260 static int parse_technology_response(const char *response, int *current, int32_t *preferred); 261 static int techFromModemType(int mdmtype); 262 263 static int clccStateToRILState(int state, RIL_CallState *p_state) 264 265 { 266 switch(state) { 267 case 0: *p_state = RIL_CALL_ACTIVE; return 0; 268 case 1: *p_state = RIL_CALL_HOLDING; return 0; 269 case 2: *p_state = RIL_CALL_DIALING; return 0; 270 case 3: *p_state = RIL_CALL_ALERTING; return 0; 271 case 4: *p_state = RIL_CALL_INCOMING; return 0; 272 case 5: *p_state = RIL_CALL_WAITING; return 0; 273 default: return -1; 274 } 275 } 276 277 /** 278 * Note: directly modified line and has *p_call point directly into 279 * modified line 280 */ 281 static int callFromCLCCLine(char *line, RIL_Call *p_call) 282 { 283 //+CLCC: 1,0,2,0,0,\"+18005551212\",145 284 // index,isMT,state,mode,isMpty(,number,TOA)? 285 286 int err; 287 int state; 288 int mode; 289 290 err = at_tok_start(&line); 291 if (err < 0) goto error; 292 293 err = at_tok_nextint(&line, &(p_call->index)); 294 if (err < 0) goto error; 295 296 err = at_tok_nextbool(&line, &(p_call->isMT)); 297 if (err < 0) goto error; 298 299 err = at_tok_nextint(&line, &state); 300 if (err < 0) goto error; 301 302 err = clccStateToRILState(state, &(p_call->state)); 303 if (err < 0) goto error; 304 305 err = at_tok_nextint(&line, &mode); 306 if (err < 0) goto error; 307 308 p_call->isVoice = (mode == 0); 309 310 err = at_tok_nextbool(&line, &(p_call->isMpty)); 311 if (err < 0) goto error; 312 313 if (at_tok_hasmore(&line)) { 314 err = at_tok_nextstr(&line, &(p_call->number)); 315 316 /* tolerate null here */ 317 if (err < 0) return 0; 318 319 // Some lame implementations return strings 320 // like "NOT AVAILABLE" in the CLCC line 321 if (p_call->number != NULL 322 && 0 == strspn(p_call->number, "+0123456789") 323 ) { 324 p_call->number = NULL; 325 } 326 327 err = at_tok_nextint(&line, &p_call->toa); 328 if (err < 0) goto error; 329 } 330 331 p_call->uusInfo = NULL; 332 333 return 0; 334 335 error: 336 RLOGE("invalid CLCC line\n"); 337 return -1; 338 } 339 340 static int parseSimResponseLine(char* line, RIL_SIM_IO_Response* response) { 341 int err; 342 343 err = at_tok_start(&line); 344 if (err < 0) return err; 345 err = at_tok_nextint(&line, &response->sw1); 346 if (err < 0) return err; 347 err = at_tok_nextint(&line, &response->sw2); 348 if (err < 0) return err; 349 350 if (at_tok_hasmore(&line)) { 351 err = at_tok_nextstr(&line, &response->simResponse); 352 if (err < 0) return err; 353 } 354 return 0; 355 } 356 357 /** do post-AT+CFUN=1 initialization */ 358 static void onRadioPowerOn() 359 { 360 #ifdef USE_TI_COMMANDS 361 /* Must be after CFUN=1 */ 362 /* TI specific -- notifications for CPHS things such */ 363 /* as CPHS message waiting indicator */ 364 365 at_send_command("AT%CPHS=1", NULL); 366 367 /* TI specific -- enable NITZ unsol notifs */ 368 at_send_command("AT%CTZV=1", NULL); 369 #endif 370 371 pollSIMState(NULL); 372 } 373 374 /** do post- SIM ready initialization */ 375 static void onSIMReady() 376 { 377 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL); 378 /* 379 * Always send SMS messages directly to the TE 380 * 381 * mode = 1 // discard when link is reserved (link should never be 382 * reserved) 383 * mt = 2 // most messages routed to TE 384 * bm = 2 // new cell BM's routed to TE 385 * ds = 1 // Status reports routed to TE 386 * bfr = 1 // flush buffer 387 */ 388 at_send_command("AT+CNMI=1,2,2,1,1", NULL); 389 } 390 391 static void requestRadioPower(void *data, size_t datalen __unused, RIL_Token t) 392 { 393 int onOff; 394 395 int err; 396 ATResponse *p_response = NULL; 397 398 assert (datalen >= sizeof(int *)); 399 onOff = ((int *)data)[0]; 400 401 if (onOff == 0 && sState != RADIO_STATE_OFF) { 402 err = at_send_command("AT+CFUN=0", &p_response); 403 if (err < 0 || p_response->success == 0) goto error; 404 setRadioState(RADIO_STATE_OFF); 405 } else if (onOff > 0 && sState == RADIO_STATE_OFF) { 406 err = at_send_command("AT+CFUN=1", &p_response); 407 if (err < 0|| p_response->success == 0) { 408 // Some stacks return an error when there is no SIM, 409 // but they really turn the RF portion on 410 // So, if we get an error, let's check to see if it 411 // turned on anyway 412 413 if (isRadioOn() != 1) { 414 goto error; 415 } 416 } 417 setRadioState(RADIO_STATE_ON); 418 } 419 420 at_response_free(p_response); 421 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 422 return; 423 error: 424 at_response_free(p_response); 425 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 426 } 427 428 static void requestShutdown(RIL_Token t) 429 { 430 int onOff; 431 432 int err; 433 ATResponse *p_response = NULL; 434 435 if (sState != RADIO_STATE_OFF) { 436 err = at_send_command("AT+CFUN=0", &p_response); 437 setRadioState(RADIO_STATE_UNAVAILABLE); 438 } 439 440 at_response_free(p_response); 441 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 442 return; 443 } 444 445 static void requestOrSendDataCallList(RIL_Token *t); 446 447 static void onDataCallListChanged(void *param __unused) 448 { 449 requestOrSendDataCallList(NULL); 450 } 451 452 static void requestDataCallList(void *data __unused, size_t datalen __unused, RIL_Token t) 453 { 454 requestOrSendDataCallList(&t); 455 } 456 457 static void requestOrSendDataCallList(RIL_Token *t) 458 { 459 ATResponse *p_response; 460 ATLine *p_cur; 461 int err; 462 int n = 0; 463 char *out; 464 465 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response); 466 if (err != 0 || p_response->success == 0) { 467 if (t != NULL) 468 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); 469 else 470 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 471 NULL, 0); 472 return; 473 } 474 475 for (p_cur = p_response->p_intermediates; p_cur != NULL; 476 p_cur = p_cur->p_next) 477 n++; 478 479 RIL_Data_Call_Response_v11 *responses = 480 alloca(n * sizeof(RIL_Data_Call_Response_v11)); 481 482 int i; 483 for (i = 0; i < n; i++) { 484 responses[i].status = -1; 485 responses[i].suggestedRetryTime = -1; 486 responses[i].cid = -1; 487 responses[i].active = -1; 488 responses[i].type = ""; 489 responses[i].ifname = ""; 490 responses[i].addresses = ""; 491 responses[i].dnses = ""; 492 responses[i].gateways = ""; 493 responses[i].pcscf = ""; 494 responses[i].mtu = 0; 495 } 496 497 RIL_Data_Call_Response_v11 *response = responses; 498 for (p_cur = p_response->p_intermediates; p_cur != NULL; 499 p_cur = p_cur->p_next) { 500 char *line = p_cur->line; 501 502 err = at_tok_start(&line); 503 if (err < 0) 504 goto error; 505 506 err = at_tok_nextint(&line, &response->cid); 507 if (err < 0) 508 goto error; 509 510 err = at_tok_nextint(&line, &response->active); 511 if (err < 0) 512 goto error; 513 514 response++; 515 } 516 517 at_response_free(p_response); 518 519 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response); 520 if (err != 0 || p_response->success == 0) { 521 if (t != NULL) 522 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); 523 else 524 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 525 NULL, 0); 526 return; 527 } 528 529 for (p_cur = p_response->p_intermediates; p_cur != NULL; 530 p_cur = p_cur->p_next) { 531 char *line = p_cur->line; 532 int cid; 533 534 err = at_tok_start(&line); 535 if (err < 0) 536 goto error; 537 538 err = at_tok_nextint(&line, &cid); 539 if (err < 0) 540 goto error; 541 542 for (i = 0; i < n; i++) { 543 if (responses[i].cid == cid) 544 break; 545 } 546 547 if (i >= n) { 548 /* details for a context we didn't hear about in the last request */ 549 continue; 550 } 551 552 // Assume no error 553 responses[i].status = 0; 554 555 // type 556 err = at_tok_nextstr(&line, &out); 557 if (err < 0) 558 goto error; 559 560 int type_size = strlen(out) + 1; 561 responses[i].type = alloca(type_size); 562 strlcpy(responses[i].type, out, type_size); 563 564 // APN ignored for v5 565 err = at_tok_nextstr(&line, &out); 566 if (err < 0) 567 goto error; 568 569 int ifname_size = strlen(PPP_TTY_PATH) + 1; 570 responses[i].ifname = alloca(ifname_size); 571 strlcpy(responses[i].ifname, PPP_TTY_PATH, ifname_size); 572 573 err = at_tok_nextstr(&line, &out); 574 if (err < 0) 575 goto error; 576 577 int addresses_size = strlen(out) + 1; 578 responses[i].addresses = alloca(addresses_size); 579 strlcpy(responses[i].addresses, out, addresses_size); 580 581 if (isInEmulator()) { 582 /* We are in the emulator - the dns servers are listed 583 * by the following system properties, setup in 584 * /system/etc/init.goldfish.sh: 585 * - net.eth0.dns1 586 * - net.eth0.dns2 587 * - net.eth0.dns3 588 * - net.eth0.dns4 589 */ 590 const int dnslist_sz = 128; 591 char* dnslist = alloca(dnslist_sz); 592 const char* separator = ""; 593 int nn; 594 595 dnslist[0] = 0; 596 for (nn = 1; nn <= 4; nn++) { 597 /* Probe net.eth0.dns<n> */ 598 char propName[PROP_NAME_MAX]; 599 char propValue[PROP_VALUE_MAX]; 600 601 snprintf(propName, sizeof propName, "net.eth0.dns%d", nn); 602 603 /* Ignore if undefined */ 604 if (__system_property_get(propName, propValue) == 0) { 605 continue; 606 } 607 608 /* Append the DNS IP address */ 609 strlcat(dnslist, separator, dnslist_sz); 610 strlcat(dnslist, propValue, dnslist_sz); 611 separator = " "; 612 } 613 responses[i].dnses = dnslist; 614 615 responses[i].gateways = "10.0.2.2 fe80::2"; 616 responses[i].mtu = DEFAULT_MTU; 617 } 618 else { 619 /* I don't know where we are, so use the public Google DNS 620 * servers by default and no gateway. 621 */ 622 responses[i].dnses = "8.8.8.8 8.8.4.4"; 623 responses[i].gateways = ""; 624 } 625 } 626 627 at_response_free(p_response); 628 629 if (t != NULL) 630 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses, 631 n * sizeof(RIL_Data_Call_Response_v11)); 632 else 633 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 634 responses, 635 n * sizeof(RIL_Data_Call_Response_v11)); 636 637 return; 638 639 error: 640 if (t != NULL) 641 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); 642 else 643 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 644 NULL, 0); 645 646 at_response_free(p_response); 647 } 648 649 static void requestQueryNetworkSelectionMode( 650 void *data __unused, size_t datalen __unused, RIL_Token t) 651 { 652 int err; 653 ATResponse *p_response = NULL; 654 int response = 0; 655 char *line; 656 657 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response); 658 659 if (err < 0 || p_response->success == 0) { 660 goto error; 661 } 662 663 line = p_response->p_intermediates->line; 664 665 err = at_tok_start(&line); 666 667 if (err < 0) { 668 goto error; 669 } 670 671 err = at_tok_nextint(&line, &response); 672 673 if (err < 0) { 674 goto error; 675 } 676 677 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int)); 678 at_response_free(p_response); 679 return; 680 error: 681 at_response_free(p_response); 682 RLOGE("requestQueryNetworkSelectionMode must never return error when radio is on"); 683 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 684 } 685 686 static void sendCallStateChanged(void *param __unused) 687 { 688 RIL_onUnsolicitedResponse ( 689 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, 690 NULL, 0); 691 } 692 693 static void requestGetCurrentCalls(void *data __unused, size_t datalen __unused, RIL_Token t) 694 { 695 int err; 696 ATResponse *p_response; 697 ATLine *p_cur; 698 int countCalls; 699 int countValidCalls; 700 RIL_Call *p_calls; 701 RIL_Call **pp_calls; 702 int i; 703 int needRepoll = 0; 704 705 #ifdef WORKAROUND_ERRONEOUS_ANSWER 706 int prevIncomingOrWaitingLine; 707 708 prevIncomingOrWaitingLine = s_incomingOrWaitingLine; 709 s_incomingOrWaitingLine = -1; 710 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/ 711 712 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response); 713 714 if (err != 0 || p_response->success == 0) { 715 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 716 return; 717 } 718 719 /* count the calls */ 720 for (countCalls = 0, p_cur = p_response->p_intermediates 721 ; p_cur != NULL 722 ; p_cur = p_cur->p_next 723 ) { 724 countCalls++; 725 } 726 727 /* yes, there's an array of pointers and then an array of structures */ 728 729 pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *)); 730 p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call)); 731 memset (p_calls, 0, countCalls * sizeof(RIL_Call)); 732 733 /* init the pointer array */ 734 for(i = 0; i < countCalls ; i++) { 735 pp_calls[i] = &(p_calls[i]); 736 } 737 738 for (countValidCalls = 0, p_cur = p_response->p_intermediates 739 ; p_cur != NULL 740 ; p_cur = p_cur->p_next 741 ) { 742 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls); 743 744 if (err != 0) { 745 continue; 746 } 747 748 #ifdef WORKAROUND_ERRONEOUS_ANSWER 749 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING 750 || p_calls[countValidCalls].state == RIL_CALL_WAITING 751 ) { 752 s_incomingOrWaitingLine = p_calls[countValidCalls].index; 753 } 754 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/ 755 756 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE 757 && p_calls[countValidCalls].state != RIL_CALL_HOLDING 758 ) { 759 needRepoll = 1; 760 } 761 762 countValidCalls++; 763 } 764 765 #ifdef WORKAROUND_ERRONEOUS_ANSWER 766 // Basically: 767 // A call was incoming or waiting 768 // Now it's marked as active 769 // But we never answered it 770 // 771 // This is probably a bug, and the call will probably 772 // disappear from the call list in the next poll 773 if (prevIncomingOrWaitingLine >= 0 774 && s_incomingOrWaitingLine < 0 775 && s_expectAnswer == 0 776 ) { 777 for (i = 0; i < countValidCalls ; i++) { 778 779 if (p_calls[i].index == prevIncomingOrWaitingLine 780 && p_calls[i].state == RIL_CALL_ACTIVE 781 && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX 782 ) { 783 RLOGI( 784 "Hit WORKAROUND_ERRONOUS_ANSWER case." 785 " Repoll count: %d\n", s_repollCallsCount); 786 s_repollCallsCount++; 787 goto error; 788 } 789 } 790 } 791 792 s_expectAnswer = 0; 793 s_repollCallsCount = 0; 794 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/ 795 796 RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls, 797 countValidCalls * sizeof (RIL_Call *)); 798 799 at_response_free(p_response); 800 801 #ifdef POLL_CALL_STATE 802 if (countValidCalls) { // We don't seem to get a "NO CARRIER" message from 803 // smd, so we're forced to poll until the call ends. 804 #else 805 if (needRepoll) { 806 #endif 807 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL); 808 } 809 810 return; 811 #ifdef WORKAROUND_ERRONEOUS_ANSWER 812 error: 813 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 814 at_response_free(p_response); 815 #endif 816 } 817 818 static void requestDial(void *data, size_t datalen __unused, RIL_Token t) 819 { 820 RIL_Dial *p_dial; 821 char *cmd; 822 const char *clir; 823 int ret; 824 825 p_dial = (RIL_Dial *)data; 826 827 switch (p_dial->clir) { 828 case 1: clir = "I"; break; /*invocation*/ 829 case 2: clir = "i"; break; /*suppression*/ 830 default: 831 case 0: clir = ""; break; /*subscription default*/ 832 } 833 834 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir); 835 836 ret = at_send_command(cmd, NULL); 837 838 free(cmd); 839 840 /* success or failure is ignored by the upper layer here. 841 it will call GET_CURRENT_CALLS and determine success that way */ 842 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 843 } 844 845 static void requestWriteSmsToSim(void *data, size_t datalen __unused, RIL_Token t) 846 { 847 RIL_SMS_WriteArgs *p_args; 848 char *cmd; 849 int length; 850 int err; 851 ATResponse *p_response = NULL; 852 853 p_args = (RIL_SMS_WriteArgs *)data; 854 855 length = strlen(p_args->pdu)/2; 856 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status); 857 858 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response); 859 860 if (err != 0 || p_response->success == 0) goto error; 861 862 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 863 at_response_free(p_response); 864 865 return; 866 error: 867 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 868 at_response_free(p_response); 869 } 870 871 static void requestHangup(void *data, size_t datalen __unused, RIL_Token t) 872 { 873 int *p_line; 874 875 int ret; 876 char *cmd; 877 878 p_line = (int *)data; 879 880 // 3GPP 22.030 6.5.5 881 // "Releases a specific active call X" 882 asprintf(&cmd, "AT+CHLD=1%d", p_line[0]); 883 884 ret = at_send_command(cmd, NULL); 885 886 free(cmd); 887 888 /* success or failure is ignored by the upper layer here. 889 it will call GET_CURRENT_CALLS and determine success that way */ 890 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 891 } 892 893 static void requestSignalStrength(void *data __unused, size_t datalen __unused, RIL_Token t) 894 { 895 ATResponse *p_response = NULL; 896 int err; 897 char *line; 898 int count = 0; 899 // Accept a response that is at least v6, and up to v10 900 int minNumOfElements=sizeof(RIL_SignalStrength_v6)/sizeof(int); 901 int maxNumOfElements=sizeof(RIL_SignalStrength_v10)/sizeof(int); 902 int response[maxNumOfElements]; 903 904 memset(response, 0, sizeof(response)); 905 906 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response); 907 908 if (err < 0 || p_response->success == 0) { 909 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 910 goto error; 911 } 912 913 line = p_response->p_intermediates->line; 914 915 err = at_tok_start(&line); 916 if (err < 0) goto error; 917 918 for (count = 0; count < maxNumOfElements; count++) { 919 err = at_tok_nextint(&line, &(response[count])); 920 if (err < 0 && count < minNumOfElements) goto error; 921 } 922 923 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); 924 925 at_response_free(p_response); 926 return; 927 928 error: 929 RLOGE("requestSignalStrength must never return an error when radio is on"); 930 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 931 at_response_free(p_response); 932 } 933 934 /** 935 * networkModePossible. Decides whether the network mode is appropriate for the 936 * specified modem 937 */ 938 static int networkModePossible(ModemInfo *mdm, int nm) 939 { 940 if ((net2modem[nm] & mdm->supportedTechs) == net2modem[nm]) { 941 return 1; 942 } 943 return 0; 944 } 945 static void requestSetPreferredNetworkType( int request __unused, void *data, 946 size_t datalen __unused, RIL_Token t ) 947 { 948 ATResponse *p_response = NULL; 949 char *cmd = NULL; 950 int value = *(int *)data; 951 int current, old; 952 int err; 953 int32_t preferred = net2pmask[value]; 954 955 RLOGD("requestSetPreferredNetworkType: current: %x. New: %x", PREFERRED_NETWORK(sMdmInfo), preferred); 956 if (!networkModePossible(sMdmInfo, value)) { 957 RIL_onRequestComplete(t, RIL_E_MODE_NOT_SUPPORTED, NULL, 0); 958 return; 959 } 960 if (query_ctec(sMdmInfo, ¤t, NULL) < 0) { 961 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 962 return; 963 } 964 old = PREFERRED_NETWORK(sMdmInfo); 965 RLOGD("old != preferred: %d", old != preferred); 966 if (old != preferred) { 967 asprintf(&cmd, "AT+CTEC=%d,\"%x\"", current, preferred); 968 RLOGD("Sending command: <%s>", cmd); 969 err = at_send_command_singleline(cmd, "+CTEC:", &p_response); 970 free(cmd); 971 if (err || !p_response->success) { 972 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 973 return; 974 } 975 PREFERRED_NETWORK(sMdmInfo) = value; 976 if (!strstr( p_response->p_intermediates->line, "DONE") ) { 977 int current; 978 int res = parse_technology_response(p_response->p_intermediates->line, ¤t, NULL); 979 switch (res) { 980 case -1: // Error or unable to parse 981 break; 982 case 1: // Only able to parse current 983 case 0: // Both current and preferred were parsed 984 setRadioTechnology(sMdmInfo, current); 985 break; 986 } 987 } 988 } 989 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 990 } 991 992 static void requestGetPreferredNetworkType(int request __unused, void *data __unused, 993 size_t datalen __unused, RIL_Token t) 994 { 995 int preferred; 996 unsigned i; 997 998 switch ( query_ctec(sMdmInfo, NULL, &preferred) ) { 999 case -1: // Error or unable to parse 1000 case 1: // Only able to parse current 1001 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1002 break; 1003 case 0: // Both current and preferred were parsed 1004 for ( i = 0 ; i < sizeof(net2pmask) / sizeof(int32_t) ; i++ ) { 1005 if (preferred == net2pmask[i]) { 1006 RIL_onRequestComplete(t, RIL_E_SUCCESS, &i, sizeof(int)); 1007 return; 1008 } 1009 } 1010 RLOGE("Unknown preferred mode received from modem: %d", preferred); 1011 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1012 break; 1013 } 1014 1015 } 1016 1017 static void requestCdmaPrlVersion(int request __unused, void *data __unused, 1018 size_t datalen __unused, RIL_Token t) 1019 { 1020 int err; 1021 char * responseStr; 1022 ATResponse *p_response = NULL; 1023 const char *cmd; 1024 char *line; 1025 1026 err = at_send_command_singleline("AT+WPRL?", "+WPRL:", &p_response); 1027 if (err < 0 || !p_response->success) goto error; 1028 line = p_response->p_intermediates->line; 1029 err = at_tok_start(&line); 1030 if (err < 0) goto error; 1031 err = at_tok_nextstr(&line, &responseStr); 1032 if (err < 0 || !responseStr) goto error; 1033 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, strlen(responseStr)); 1034 at_response_free(p_response); 1035 return; 1036 error: 1037 at_response_free(p_response); 1038 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1039 } 1040 1041 static void requestCdmaBaseBandVersion(int request __unused, void *data __unused, 1042 size_t datalen __unused, RIL_Token t) 1043 { 1044 int err; 1045 char * responseStr; 1046 ATResponse *p_response = NULL; 1047 const char *cmd; 1048 const char *prefix; 1049 char *line, *p; 1050 int commas; 1051 int skip; 1052 int count = 4; 1053 1054 // Fixed values. TODO: query modem 1055 responseStr = strdup("1.0.0.0"); 1056 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, sizeof(responseStr)); 1057 free(responseStr); 1058 } 1059 1060 static void requestCdmaDeviceIdentity(int request __unused, void *data __unused, 1061 size_t datalen __unused, RIL_Token t) 1062 { 1063 int err; 1064 int response[4]; 1065 char * responseStr[4]; 1066 ATResponse *p_response = NULL; 1067 const char *cmd; 1068 const char *prefix; 1069 char *line, *p; 1070 int commas; 1071 int skip; 1072 int count = 4; 1073 1074 // Fixed values. TODO: Query modem 1075 responseStr[0] = "----"; 1076 responseStr[1] = "----"; 1077 responseStr[2] = "77777777"; 1078 1079 err = at_send_command_numeric("AT+CGSN", &p_response); 1080 if (err < 0 || p_response->success == 0) { 1081 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1082 return; 1083 } else { 1084 responseStr[3] = p_response->p_intermediates->line; 1085 } 1086 1087 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*)); 1088 at_response_free(p_response); 1089 } 1090 1091 static void requestCdmaGetSubscriptionSource(int request __unused, void *data, 1092 size_t datalen __unused, RIL_Token t) 1093 { 1094 int err; 1095 int *ss = (int *)data; 1096 ATResponse *p_response = NULL; 1097 char *cmd = NULL; 1098 char *line = NULL; 1099 int response; 1100 1101 asprintf(&cmd, "AT+CCSS?"); 1102 if (!cmd) goto error; 1103 1104 err = at_send_command_singleline(cmd, "+CCSS:", &p_response); 1105 if (err < 0 || !p_response->success) 1106 goto error; 1107 1108 line = p_response->p_intermediates->line; 1109 err = at_tok_start(&line); 1110 if (err < 0) goto error; 1111 1112 err = at_tok_nextint(&line, &response); 1113 free(cmd); 1114 cmd = NULL; 1115 1116 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response)); 1117 1118 return; 1119 error: 1120 free(cmd); 1121 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1122 } 1123 1124 static void requestCdmaSetSubscriptionSource(int request __unused, void *data, 1125 size_t datalen, RIL_Token t) 1126 { 1127 int err; 1128 int *ss = (int *)data; 1129 ATResponse *p_response = NULL; 1130 char *cmd = NULL; 1131 1132 if (!ss || !datalen) { 1133 RLOGE("RIL_REQUEST_CDMA_SET_SUBSCRIPTION without data!"); 1134 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1135 return; 1136 } 1137 asprintf(&cmd, "AT+CCSS=%d", ss[0]); 1138 if (!cmd) goto error; 1139 1140 err = at_send_command(cmd, &p_response); 1141 if (err < 0 || !p_response->success) 1142 goto error; 1143 free(cmd); 1144 cmd = NULL; 1145 1146 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1147 1148 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, ss, sizeof(ss[0])); 1149 1150 return; 1151 error: 1152 free(cmd); 1153 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1154 } 1155 1156 static void requestCdmaSubscription(int request __unused, void *data __unused, 1157 size_t datalen __unused, RIL_Token t) 1158 { 1159 int err; 1160 int response[5]; 1161 char * responseStr[5]; 1162 ATResponse *p_response = NULL; 1163 const char *cmd; 1164 const char *prefix; 1165 char *line, *p; 1166 int commas; 1167 int skip; 1168 int count = 5; 1169 1170 // Fixed values. TODO: Query modem 1171 responseStr[0] = "8587777777"; // MDN 1172 responseStr[1] = "1"; // SID 1173 responseStr[2] = "1"; // NID 1174 responseStr[3] = "8587777777"; // MIN 1175 responseStr[4] = "1"; // PRL Version 1176 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*)); 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 // ISIM_ABSENT = 12 2833 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN, 2834 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, 2835 // ISIM_NOT_READY = 13 2836 { RIL_APPTYPE_ISIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN, 2837 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, 2838 // ISIM_READY = 14 2839 { RIL_APPTYPE_ISIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY, 2840 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, 2841 // ISIM_PIN = 15 2842 { RIL_APPTYPE_ISIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN, 2843 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }, 2844 // ISIM_PUK = 16 2845 { RIL_APPTYPE_ISIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN, 2846 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN }, 2847 // ISIM_NETWORK_PERSONALIZATION = 17 2848 { RIL_APPTYPE_ISIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK, 2849 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }, 2850 2851 }; 2852 RIL_CardState card_state; 2853 int num_apps; 2854 2855 int sim_status = getSIMStatus(); 2856 if (sim_status == SIM_ABSENT) { 2857 card_state = RIL_CARDSTATE_ABSENT; 2858 num_apps = 0; 2859 } else { 2860 card_state = RIL_CARDSTATE_PRESENT; 2861 num_apps = 3; 2862 } 2863 2864 // Allocate and initialize base card status. 2865 RIL_CardStatus_v6 *p_card_status = malloc(sizeof(RIL_CardStatus_v6)); 2866 p_card_status->card_state = card_state; 2867 p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN; 2868 p_card_status->gsm_umts_subscription_app_index = -1; 2869 p_card_status->cdma_subscription_app_index = -1; 2870 p_card_status->ims_subscription_app_index = -1; 2871 p_card_status->num_applications = num_apps; 2872 2873 // Initialize application status 2874 int i; 2875 for (i = 0; i < RIL_CARD_MAX_APPS; i++) { 2876 p_card_status->applications[i] = app_status_array[SIM_ABSENT]; 2877 } 2878 2879 // Pickup the appropriate application status 2880 // that reflects sim_status for gsm. 2881 if (num_apps != 0) { 2882 p_card_status->num_applications = 3; 2883 p_card_status->gsm_umts_subscription_app_index = 0; 2884 p_card_status->cdma_subscription_app_index = 1; 2885 p_card_status->ims_subscription_app_index = 2; 2886 2887 // Get the correct app status 2888 p_card_status->applications[0] = app_status_array[sim_status]; 2889 p_card_status->applications[1] = app_status_array[sim_status + RUIM_ABSENT]; 2890 p_card_status->applications[2] = app_status_array[sim_status + ISIM_ABSENT]; 2891 } 2892 2893 *pp_card_status = p_card_status; 2894 return RIL_E_SUCCESS; 2895 } 2896 2897 /** 2898 * Free the card status returned by getCardStatus 2899 */ 2900 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status) { 2901 free(p_card_status); 2902 } 2903 2904 /** 2905 * SIM ready means any commands that access the SIM will work, including: 2906 * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM 2907 * (all SMS-related commands) 2908 */ 2909 2910 static void pollSIMState (void *param __unused) 2911 { 2912 ATResponse *p_response; 2913 int ret; 2914 2915 if (sState != RADIO_STATE_UNAVAILABLE) { 2916 // no longer valid to poll 2917 return; 2918 } 2919 2920 switch(getSIMStatus()) { 2921 case SIM_ABSENT: 2922 case SIM_PIN: 2923 case SIM_PUK: 2924 case SIM_NETWORK_PERSONALIZATION: 2925 default: 2926 RLOGI("SIM ABSENT or LOCKED"); 2927 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0); 2928 return; 2929 2930 case SIM_NOT_READY: 2931 RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL); 2932 return; 2933 2934 case SIM_READY: 2935 RLOGI("SIM_READY"); 2936 onSIMReady(); 2937 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0); 2938 return; 2939 } 2940 } 2941 2942 /** returns 1 if on, 0 if off, and -1 on error */ 2943 static int isRadioOn() 2944 { 2945 ATResponse *p_response = NULL; 2946 int err; 2947 char *line; 2948 char ret; 2949 2950 err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response); 2951 2952 if (err < 0 || p_response->success == 0) { 2953 // assume radio is off 2954 goto error; 2955 } 2956 2957 line = p_response->p_intermediates->line; 2958 2959 err = at_tok_start(&line); 2960 if (err < 0) goto error; 2961 2962 err = at_tok_nextbool(&line, &ret); 2963 if (err < 0) goto error; 2964 2965 at_response_free(p_response); 2966 2967 return (int)ret; 2968 2969 error: 2970 2971 at_response_free(p_response); 2972 return -1; 2973 } 2974 2975 /** 2976 * Parse the response generated by a +CTEC AT command 2977 * The values read from the response are stored in current and preferred. 2978 * Both current and preferred may be null. The corresponding value is ignored in that case. 2979 * 2980 * @return: -1 if some error occurs (or if the modem doesn't understand the +CTEC command) 2981 * 1 if the response includes the current technology only 2982 * 0 if the response includes both current technology and preferred mode 2983 */ 2984 int parse_technology_response( const char *response, int *current, int32_t *preferred ) 2985 { 2986 int err; 2987 char *line, *p; 2988 int ct; 2989 int32_t pt = 0; 2990 char *str_pt; 2991 2992 line = p = strdup(response); 2993 RLOGD("Response: %s", line); 2994 err = at_tok_start(&p); 2995 if (err || !at_tok_hasmore(&p)) { 2996 RLOGD("err: %d. p: %s", err, p); 2997 free(line); 2998 return -1; 2999 } 3000 3001 err = at_tok_nextint(&p, &ct); 3002 if (err) { 3003 free(line); 3004 return -1; 3005 } 3006 if (current) *current = ct; 3007 3008 RLOGD("line remaining after int: %s", p); 3009 3010 err = at_tok_nexthexint(&p, &pt); 3011 if (err) { 3012 free(line); 3013 return 1; 3014 } 3015 if (preferred) { 3016 *preferred = pt; 3017 } 3018 free(line); 3019 3020 return 0; 3021 } 3022 3023 int query_supported_techs( ModemInfo *mdm __unused, int *supported ) 3024 { 3025 ATResponse *p_response; 3026 int err, val, techs = 0; 3027 char *tok; 3028 char *line; 3029 3030 RLOGD("query_supported_techs"); 3031 err = at_send_command_singleline("AT+CTEC=?", "+CTEC:", &p_response); 3032 if (err || !p_response->success) 3033 goto error; 3034 line = p_response->p_intermediates->line; 3035 err = at_tok_start(&line); 3036 if (err || !at_tok_hasmore(&line)) 3037 goto error; 3038 while (!at_tok_nextint(&line, &val)) { 3039 techs |= ( 1 << val ); 3040 } 3041 if (supported) *supported = techs; 3042 return 0; 3043 error: 3044 at_response_free(p_response); 3045 return -1; 3046 } 3047 3048 /** 3049 * query_ctec. Send the +CTEC AT command to the modem to query the current 3050 * and preferred modes. It leaves values in the addresses pointed to by 3051 * current and preferred. If any of those pointers are NULL, the corresponding value 3052 * is ignored, but the return value will still reflect if retreiving and parsing of the 3053 * values suceeded. 3054 * 3055 * @mdm Currently unused 3056 * @current A pointer to store the current mode returned by the modem. May be null. 3057 * @preferred A pointer to store the preferred mode returned by the modem. May be null. 3058 * @return -1 on error (or failure to parse) 3059 * 1 if only the current mode was returned by modem (or failed to parse preferred) 3060 * 0 if both current and preferred were returned correctly 3061 */ 3062 int query_ctec(ModemInfo *mdm __unused, int *current, int32_t *preferred) 3063 { 3064 ATResponse *response = NULL; 3065 int err; 3066 int res; 3067 3068 RLOGD("query_ctec. current: %p, preferred: %p", current, preferred); 3069 err = at_send_command_singleline("AT+CTEC?", "+CTEC:", &response); 3070 if (!err && response->success) { 3071 res = parse_technology_response(response->p_intermediates->line, current, preferred); 3072 at_response_free(response); 3073 return res; 3074 } 3075 RLOGE("Error executing command: %d. response: %p. status: %d", err, response, response? response->success : -1); 3076 at_response_free(response); 3077 return -1; 3078 } 3079 3080 int is_multimode_modem(ModemInfo *mdm) 3081 { 3082 ATResponse *response; 3083 int err; 3084 char *line; 3085 int tech; 3086 int32_t preferred; 3087 3088 if (query_ctec(mdm, &tech, &preferred) == 0) { 3089 mdm->currentTech = tech; 3090 mdm->preferredNetworkMode = preferred; 3091 if (query_supported_techs(mdm, &mdm->supportedTechs)) { 3092 return 0; 3093 } 3094 return 1; 3095 } 3096 return 0; 3097 } 3098 3099 /** 3100 * Find out if our modem is GSM, CDMA or both (Multimode) 3101 */ 3102 static void probeForModemMode(ModemInfo *info) 3103 { 3104 ATResponse *response; 3105 int err; 3106 assert (info); 3107 // Currently, our only known multimode modem is qemu's android modem, 3108 // which implements the AT+CTEC command to query and set mode. 3109 // Try that first 3110 3111 if (is_multimode_modem(info)) { 3112 RLOGI("Found Multimode Modem. Supported techs mask: %8.8x. Current tech: %d", 3113 info->supportedTechs, info->currentTech); 3114 return; 3115 } 3116 3117 /* Being here means that our modem is not multimode */ 3118 info->isMultimode = 0; 3119 3120 /* CDMA Modems implement the AT+WNAM command */ 3121 err = at_send_command_singleline("AT+WNAM","+WNAM:", &response); 3122 if (!err && response->success) { 3123 at_response_free(response); 3124 // TODO: find out if we really support EvDo 3125 info->supportedTechs = MDM_CDMA | MDM_EVDO; 3126 info->currentTech = MDM_CDMA; 3127 RLOGI("Found CDMA Modem"); 3128 return; 3129 } 3130 if (!err) at_response_free(response); 3131 // TODO: find out if modem really supports WCDMA/LTE 3132 info->supportedTechs = MDM_GSM | MDM_WCDMA | MDM_LTE; 3133 info->currentTech = MDM_GSM; 3134 RLOGI("Found GSM Modem"); 3135 } 3136 3137 /** 3138 * Initialize everything that can be configured while we're still in 3139 * AT+CFUN=0 3140 */ 3141 static void initializeCallback(void *param __unused) 3142 { 3143 ATResponse *p_response = NULL; 3144 int err; 3145 3146 setRadioState (RADIO_STATE_OFF); 3147 3148 at_handshake(); 3149 3150 probeForModemMode(sMdmInfo); 3151 /* note: we don't check errors here. Everything important will 3152 be handled in onATTimeout and onATReaderClosed */ 3153 3154 /* atchannel is tolerant of echo but it must */ 3155 /* have verbose result codes */ 3156 at_send_command("ATE0Q0V1", NULL); 3157 3158 /* No auto-answer */ 3159 at_send_command("ATS0=0", NULL); 3160 3161 /* Extended errors */ 3162 at_send_command("AT+CMEE=1", NULL); 3163 3164 /* Network registration events */ 3165 err = at_send_command("AT+CREG=2", &p_response); 3166 3167 /* some handsets -- in tethered mode -- don't support CREG=2 */ 3168 if (err < 0 || p_response->success == 0) { 3169 at_send_command("AT+CREG=1", NULL); 3170 } 3171 3172 at_response_free(p_response); 3173 3174 /* GPRS registration events */ 3175 at_send_command("AT+CGREG=1", NULL); 3176 3177 /* Call Waiting notifications */ 3178 at_send_command("AT+CCWA=1", NULL); 3179 3180 /* Alternating voice/data off */ 3181 at_send_command("AT+CMOD=0", NULL); 3182 3183 /* Not muted */ 3184 at_send_command("AT+CMUT=0", NULL); 3185 3186 /* +CSSU unsolicited supp service notifications */ 3187 at_send_command("AT+CSSN=0,1", NULL); 3188 3189 /* no connected line identification */ 3190 at_send_command("AT+COLP=0", NULL); 3191 3192 /* HEX character set */ 3193 at_send_command("AT+CSCS=\"HEX\"", NULL); 3194 3195 /* USSD unsolicited */ 3196 at_send_command("AT+CUSD=1", NULL); 3197 3198 /* Enable +CGEV GPRS event notifications, but don't buffer */ 3199 at_send_command("AT+CGEREP=1,0", NULL); 3200 3201 /* SMS PDU mode */ 3202 at_send_command("AT+CMGF=0", NULL); 3203 3204 #ifdef USE_TI_COMMANDS 3205 3206 at_send_command("AT%CPI=3", NULL); 3207 3208 /* TI specific -- notifications when SMS is ready (currently ignored) */ 3209 at_send_command("AT%CSTAT=1", NULL); 3210 3211 #endif /* USE_TI_COMMANDS */ 3212 3213 3214 /* assume radio is off on error */ 3215 if (isRadioOn() > 0) { 3216 setRadioState (RADIO_STATE_ON); 3217 } 3218 } 3219 3220 static void waitForClose() 3221 { 3222 pthread_mutex_lock(&s_state_mutex); 3223 3224 while (s_closed == 0) { 3225 pthread_cond_wait(&s_state_cond, &s_state_mutex); 3226 } 3227 3228 pthread_mutex_unlock(&s_state_mutex); 3229 } 3230 3231 static void sendUnsolImsNetworkStateChanged() 3232 { 3233 #if 0 // to be used when unsol is changed to return data. 3234 int reply[2]; 3235 reply[0] = s_ims_registered; 3236 reply[1] = s_ims_services; 3237 reply[1] = s_ims_format; 3238 #endif 3239 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED, 3240 NULL, 0); 3241 } 3242 3243 /** 3244 * Called by atchannel when an unsolicited line appears 3245 * This is called on atchannel's reader thread. AT commands may 3246 * not be issued here 3247 */ 3248 static void onUnsolicited (const char *s, const char *sms_pdu) 3249 { 3250 char *line = NULL, *p; 3251 int err; 3252 3253 /* Ignore unsolicited responses until we're initialized. 3254 * This is OK because the RIL library will poll for initial state 3255 */ 3256 if (sState == RADIO_STATE_UNAVAILABLE) { 3257 return; 3258 } 3259 3260 if (strStartsWith(s, "%CTZV:")) { 3261 /* TI specific -- NITZ time */ 3262 char *response; 3263 3264 line = p = strdup(s); 3265 at_tok_start(&p); 3266 3267 err = at_tok_nextstr(&p, &response); 3268 3269 if (err != 0) { 3270 RLOGE("invalid NITZ line %s\n", s); 3271 } else { 3272 RIL_onUnsolicitedResponse ( 3273 RIL_UNSOL_NITZ_TIME_RECEIVED, 3274 response, strlen(response)); 3275 } 3276 free(line); 3277 } else if (strStartsWith(s,"+CRING:") 3278 || strStartsWith(s,"RING") 3279 || strStartsWith(s,"NO CARRIER") 3280 || strStartsWith(s,"+CCWA") 3281 ) { 3282 RIL_onUnsolicitedResponse ( 3283 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, 3284 NULL, 0); 3285 #ifdef WORKAROUND_FAKE_CGEV 3286 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function 3287 #endif /* WORKAROUND_FAKE_CGEV */ 3288 } else if (strStartsWith(s,"+CREG:") 3289 || strStartsWith(s,"+CGREG:") 3290 ) { 3291 RIL_onUnsolicitedResponse ( 3292 RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, 3293 NULL, 0); 3294 #ifdef WORKAROUND_FAKE_CGEV 3295 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); 3296 #endif /* WORKAROUND_FAKE_CGEV */ 3297 } else if (strStartsWith(s, "+CMT:")) { 3298 RIL_onUnsolicitedResponse ( 3299 RIL_UNSOL_RESPONSE_NEW_SMS, 3300 sms_pdu, strlen(sms_pdu)); 3301 } else if (strStartsWith(s, "+CDS:")) { 3302 RIL_onUnsolicitedResponse ( 3303 RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, 3304 sms_pdu, strlen(sms_pdu)); 3305 } else if (strStartsWith(s, "+CGEV:")) { 3306 /* Really, we can ignore NW CLASS and ME CLASS events here, 3307 * but right now we don't since extranous 3308 * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated 3309 */ 3310 /* can't issue AT commands here -- call on main thread */ 3311 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); 3312 #ifdef WORKAROUND_FAKE_CGEV 3313 } else if (strStartsWith(s, "+CME ERROR: 150")) { 3314 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); 3315 #endif /* WORKAROUND_FAKE_CGEV */ 3316 } else if (strStartsWith(s, "+CTEC: ")) { 3317 int tech, mask; 3318 switch (parse_technology_response(s, &tech, NULL)) 3319 { 3320 case -1: // no argument could be parsed. 3321 RLOGE("invalid CTEC line %s\n", s); 3322 break; 3323 case 1: // current mode correctly parsed 3324 case 0: // preferred mode correctly parsed 3325 mask = 1 << tech; 3326 if (mask != MDM_GSM && mask != MDM_CDMA && 3327 mask != MDM_WCDMA && mask != MDM_LTE) { 3328 RLOGE("Unknown technology %d\n", tech); 3329 } else { 3330 setRadioTechnology(sMdmInfo, tech); 3331 } 3332 break; 3333 } 3334 } else if (strStartsWith(s, "+CCSS: ")) { 3335 int source = 0; 3336 line = p = strdup(s); 3337 if (!line) { 3338 RLOGE("+CCSS: Unable to allocate memory"); 3339 return; 3340 } 3341 if (at_tok_start(&p) < 0) { 3342 free(line); 3343 return; 3344 } 3345 if (at_tok_nextint(&p, &source) < 0) { 3346 RLOGE("invalid +CCSS response: %s", line); 3347 free(line); 3348 return; 3349 } 3350 SSOURCE(sMdmInfo) = source; 3351 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, 3352 &source, sizeof(source)); 3353 } else if (strStartsWith(s, "+WSOS: ")) { 3354 char state = 0; 3355 int unsol; 3356 line = p = strdup(s); 3357 if (!line) { 3358 RLOGE("+WSOS: Unable to allocate memory"); 3359 return; 3360 } 3361 if (at_tok_start(&p) < 0) { 3362 free(line); 3363 return; 3364 } 3365 if (at_tok_nextbool(&p, &state) < 0) { 3366 RLOGE("invalid +WSOS response: %s", line); 3367 free(line); 3368 return; 3369 } 3370 free(line); 3371 3372 unsol = state ? 3373 RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE : RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE; 3374 3375 RIL_onUnsolicitedResponse(unsol, NULL, 0); 3376 3377 } else if (strStartsWith(s, "+WPRL: ")) { 3378 int version = -1; 3379 line = p = strdup(s); 3380 if (!line) { 3381 RLOGE("+WPRL: Unable to allocate memory"); 3382 return; 3383 } 3384 if (at_tok_start(&p) < 0) { 3385 RLOGE("invalid +WPRL response: %s", s); 3386 free(line); 3387 return; 3388 } 3389 if (at_tok_nextint(&p, &version) < 0) { 3390 RLOGE("invalid +WPRL response: %s", s); 3391 free(line); 3392 return; 3393 } 3394 free(line); 3395 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_PRL_CHANGED, &version, sizeof(version)); 3396 } else if (strStartsWith(s, "+CFUN: 0")) { 3397 setRadioState(RADIO_STATE_OFF); 3398 } 3399 } 3400 3401 /* Called on command or reader thread */ 3402 static void onATReaderClosed() 3403 { 3404 RLOGI("AT channel closed\n"); 3405 at_close(); 3406 s_closed = 1; 3407 3408 setRadioState (RADIO_STATE_UNAVAILABLE); 3409 } 3410 3411 /* Called on command thread */ 3412 static void onATTimeout() 3413 { 3414 RLOGI("AT channel timeout; closing\n"); 3415 at_close(); 3416 3417 s_closed = 1; 3418 3419 /* FIXME cause a radio reset here */ 3420 3421 setRadioState (RADIO_STATE_UNAVAILABLE); 3422 } 3423 3424 /* Called to pass hardware configuration information to telephony 3425 * framework. 3426 */ 3427 static void setHardwareConfiguration(int num, RIL_HardwareConfig *cfg) 3428 { 3429 RIL_onUnsolicitedResponse(RIL_UNSOL_HARDWARE_CONFIG_CHANGED, cfg, num*sizeof(*cfg)); 3430 } 3431 3432 static void usage(char *s __unused) 3433 { 3434 #ifdef RIL_SHLIB 3435 fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n"); 3436 #else 3437 fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s); 3438 exit(-1); 3439 #endif 3440 } 3441 3442 static void * 3443 mainLoop(void *param __unused) 3444 { 3445 int fd; 3446 int ret; 3447 3448 AT_DUMP("== ", "entering mainLoop()", -1 ); 3449 at_set_on_reader_closed(onATReaderClosed); 3450 at_set_on_timeout(onATTimeout); 3451 3452 for (;;) { 3453 fd = -1; 3454 while (fd < 0) { 3455 if (isInEmulator()) { 3456 fd = qemu_pipe_open("pipe:qemud:gsm"); 3457 } else if (s_port > 0) { 3458 fd = socket_network_client("localhost", s_port, SOCK_STREAM); 3459 } else if (s_device_socket) { 3460 fd = socket_local_client(s_device_path, 3461 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, 3462 SOCK_STREAM); 3463 } else if (s_device_path != NULL) { 3464 fd = open (s_device_path, O_RDWR); 3465 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) { 3466 /* disable echo on serial ports */ 3467 struct termios ios; 3468 tcgetattr( fd, &ios ); 3469 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ 3470 tcsetattr( fd, TCSANOW, &ios ); 3471 } 3472 } 3473 3474 if (fd < 0) { 3475 perror ("opening AT interface. retrying..."); 3476 sleep(10); 3477 /* never returns */ 3478 } 3479 } 3480 3481 s_closed = 0; 3482 ret = at_open(fd, onUnsolicited); 3483 3484 if (ret < 0) { 3485 RLOGE ("AT error %d on at_open\n", ret); 3486 return 0; 3487 } 3488 3489 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0); 3490 3491 // Give initializeCallback a chance to dispatched, since 3492 // we don't presently have a cancellation mechanism 3493 sleep(1); 3494 3495 waitForClose(); 3496 RLOGI("Re-opening after close"); 3497 } 3498 } 3499 3500 #ifdef RIL_SHLIB 3501 3502 pthread_t s_tid_mainloop; 3503 3504 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv) 3505 { 3506 int ret; 3507 int fd = -1; 3508 int opt; 3509 pthread_attr_t attr; 3510 3511 s_rilenv = env; 3512 3513 while ( -1 != (opt = getopt(argc, argv, "p:d:s:c:"))) { 3514 switch (opt) { 3515 case 'p': 3516 s_port = atoi(optarg); 3517 if (s_port == 0) { 3518 usage(argv[0]); 3519 return NULL; 3520 } 3521 RLOGI("Opening loopback port %d\n", s_port); 3522 break; 3523 3524 case 'd': 3525 s_device_path = optarg; 3526 RLOGI("Opening tty device %s\n", s_device_path); 3527 break; 3528 3529 case 's': 3530 s_device_path = optarg; 3531 s_device_socket = 1; 3532 RLOGI("Opening socket %s\n", s_device_path); 3533 break; 3534 3535 case 'c': 3536 RLOGI("Client id received %s\n", optarg); 3537 break; 3538 3539 default: 3540 usage(argv[0]); 3541 return NULL; 3542 } 3543 } 3544 3545 if (s_port < 0 && s_device_path == NULL && !isInEmulator()) { 3546 usage(argv[0]); 3547 return NULL; 3548 } 3549 3550 sMdmInfo = calloc(1, sizeof(ModemInfo)); 3551 if (!sMdmInfo) { 3552 RLOGE("Unable to alloc memory for ModemInfo"); 3553 return NULL; 3554 } 3555 pthread_attr_init (&attr); 3556 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 3557 ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL); 3558 3559 return &s_callbacks; 3560 } 3561 #else /* RIL_SHLIB */ 3562 int main (int argc, char **argv) 3563 { 3564 int ret; 3565 int fd = -1; 3566 int opt; 3567 3568 while ( -1 != (opt = getopt(argc, argv, "p:d:"))) { 3569 switch (opt) { 3570 case 'p': 3571 s_port = atoi(optarg); 3572 if (s_port == 0) { 3573 usage(argv[0]); 3574 } 3575 RLOGI("Opening loopback port %d\n", s_port); 3576 break; 3577 3578 case 'd': 3579 s_device_path = optarg; 3580 RLOGI("Opening tty device %s\n", s_device_path); 3581 break; 3582 3583 case 's': 3584 s_device_path = optarg; 3585 s_device_socket = 1; 3586 RLOGI("Opening socket %s\n", s_device_path); 3587 break; 3588 3589 default: 3590 usage(argv[0]); 3591 } 3592 } 3593 3594 if (s_port < 0 && s_device_path == NULL && !isInEmulator()) { 3595 usage(argv[0]); 3596 } 3597 3598 RIL_register(&s_callbacks); 3599 3600 mainLoop(NULL); 3601 3602 return 0; 3603 } 3604 3605 #endif /* RIL_SHLIB */ 3606