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