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