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