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