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