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