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 <stdio.h> 19 #include <assert.h> 20 #include <string.h> 21 #include <errno.h> 22 #include <unistd.h> 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 #include <fcntl.h> 26 #include <pthread.h> 27 #include <alloca.h> 28 #include "atchannel.h" 29 #include "at_tok.h" 30 #include "misc.h" 31 #include <getopt.h> 32 #include <sys/socket.h> 33 #include <cutils/sockets.h> 34 #include <termios.h> 35 #include <sys/system_properties.h> 36 37 #include "ril.h" 38 #include "hardware/qemu_pipe.h" 39 40 #define LOG_TAG "RIL" 41 #include <utils/Log.h> 42 43 #define MAX_AT_RESPONSE 0x1000 44 45 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */ 46 #define PPP_TTY_PATH "eth0" 47 48 #ifdef USE_TI_COMMANDS 49 50 // Enable a workaround 51 // 1) Make incoming call, do not answer 52 // 2) Hangup remote end 53 // Expected: call should disappear from CLCC line 54 // Actual: Call shows as "ACTIVE" before disappearing 55 #define WORKAROUND_ERRONEOUS_ANSWER 1 56 57 // Some varients of the TI stack do not support the +CGEV unsolicited 58 // response. However, they seem to send an unsolicited +CME ERROR: 150 59 #define WORKAROUND_FAKE_CGEV 1 60 #endif 61 62 typedef enum { 63 SIM_ABSENT = 0, 64 SIM_NOT_READY = 1, 65 SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */ 66 SIM_PIN = 3, 67 SIM_PUK = 4, 68 SIM_NETWORK_PERSONALIZATION = 5 69 } SIM_Status; 70 71 static void onRequest (int request, void *data, size_t datalen, RIL_Token t); 72 static RIL_RadioState currentState(); 73 static int onSupports (int requestCode); 74 static void onCancel (RIL_Token t); 75 static const char *getVersion(); 76 static int isRadioOn(); 77 static SIM_Status getSIMStatus(); 78 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status); 79 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status); 80 static void onDataCallListChanged(void *param); 81 82 extern const char * requestToString(int request); 83 84 /*** Static Variables ***/ 85 static const RIL_RadioFunctions s_callbacks = { 86 RIL_VERSION, 87 onRequest, 88 currentState, 89 onSupports, 90 onCancel, 91 getVersion 92 }; 93 94 #ifdef RIL_SHLIB 95 static const struct RIL_Env *s_rilenv; 96 97 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen) 98 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c) 99 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c) 100 #endif 101 102 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE; 103 104 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER; 105 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER; 106 107 static int s_port = -1; 108 static const char * s_device_path = NULL; 109 static int s_device_socket = 0; 110 111 /* trigger change to this with s_state_cond */ 112 static int s_closed = 0; 113 114 static int sFD; /* file desc of AT channel */ 115 static char sATBuffer[MAX_AT_RESPONSE+1]; 116 static char *sATBufferCur = NULL; 117 118 static const struct timeval TIMEVAL_SIMPOLL = {1,0}; 119 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000}; 120 static const struct timeval TIMEVAL_0 = {0,0}; 121 122 #ifdef WORKAROUND_ERRONEOUS_ANSWER 123 // Max number of times we'll try to repoll when we think 124 // we have a AT+CLCC race condition 125 #define REPOLL_CALLS_COUNT_MAX 4 126 127 // Line index that was incoming or waiting at last poll, or -1 for none 128 static int s_incomingOrWaitingLine = -1; 129 // Number of times we've asked for a repoll of AT+CLCC 130 static int s_repollCallsCount = 0; 131 // Should we expect a call to be answered in the next CLCC? 132 static int s_expectAnswer = 0; 133 #endif /* WORKAROUND_ERRONEOUS_ANSWER */ 134 135 static void pollSIMState (void *param); 136 static void setRadioState(RIL_RadioState newState); 137 138 static int clccStateToRILState(int state, RIL_CallState *p_state) 139 140 { 141 switch(state) { 142 case 0: *p_state = RIL_CALL_ACTIVE; return 0; 143 case 1: *p_state = RIL_CALL_HOLDING; return 0; 144 case 2: *p_state = RIL_CALL_DIALING; return 0; 145 case 3: *p_state = RIL_CALL_ALERTING; return 0; 146 case 4: *p_state = RIL_CALL_INCOMING; return 0; 147 case 5: *p_state = RIL_CALL_WAITING; return 0; 148 default: return -1; 149 } 150 } 151 152 /** 153 * Note: directly modified line and has *p_call point directly into 154 * modified line 155 */ 156 static int callFromCLCCLine(char *line, RIL_Call *p_call) 157 { 158 //+CLCC: 1,0,2,0,0,\"+18005551212\",145 159 // index,isMT,state,mode,isMpty(,number,TOA)? 160 161 int err; 162 int state; 163 int mode; 164 165 err = at_tok_start(&line); 166 if (err < 0) goto error; 167 168 err = at_tok_nextint(&line, &(p_call->index)); 169 if (err < 0) goto error; 170 171 err = at_tok_nextbool(&line, &(p_call->isMT)); 172 if (err < 0) goto error; 173 174 err = at_tok_nextint(&line, &state); 175 if (err < 0) goto error; 176 177 err = clccStateToRILState(state, &(p_call->state)); 178 if (err < 0) goto error; 179 180 err = at_tok_nextint(&line, &mode); 181 if (err < 0) goto error; 182 183 p_call->isVoice = (mode == 0); 184 185 err = at_tok_nextbool(&line, &(p_call->isMpty)); 186 if (err < 0) goto error; 187 188 if (at_tok_hasmore(&line)) { 189 err = at_tok_nextstr(&line, &(p_call->number)); 190 191 /* tolerate null here */ 192 if (err < 0) return 0; 193 194 // Some lame implementations return strings 195 // like "NOT AVAILABLE" in the CLCC line 196 if (p_call->number != NULL 197 && 0 == strspn(p_call->number, "+0123456789") 198 ) { 199 p_call->number = NULL; 200 } 201 202 err = at_tok_nextint(&line, &p_call->toa); 203 if (err < 0) goto error; 204 } 205 206 p_call->uusInfo = NULL; 207 208 return 0; 209 210 error: 211 LOGE("invalid CLCC line\n"); 212 return -1; 213 } 214 215 216 /** do post-AT+CFUN=1 initialization */ 217 static void onRadioPowerOn() 218 { 219 #ifdef USE_TI_COMMANDS 220 /* Must be after CFUN=1 */ 221 /* TI specific -- notifications for CPHS things such */ 222 /* as CPHS message waiting indicator */ 223 224 at_send_command("AT%CPHS=1", NULL); 225 226 /* TI specific -- enable NITZ unsol notifs */ 227 at_send_command("AT%CTZV=1", NULL); 228 #endif 229 230 pollSIMState(NULL); 231 } 232 233 /** do post- SIM ready initialization */ 234 static void onSIMReady() 235 { 236 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL); 237 /* 238 * Always send SMS messages directly to the TE 239 * 240 * mode = 1 // discard when link is reserved (link should never be 241 * reserved) 242 * mt = 2 // most messages routed to TE 243 * bm = 2 // new cell BM's routed to TE 244 * ds = 1 // Status reports routed to TE 245 * bfr = 1 // flush buffer 246 */ 247 at_send_command("AT+CNMI=1,2,2,1,1", NULL); 248 } 249 250 static void requestRadioPower(void *data, size_t datalen, RIL_Token t) 251 { 252 int onOff; 253 254 int err; 255 ATResponse *p_response = NULL; 256 257 assert (datalen >= sizeof(int *)); 258 onOff = ((int *)data)[0]; 259 260 if (onOff == 0 && sState != RADIO_STATE_OFF) { 261 err = at_send_command("AT+CFUN=0", &p_response); 262 if (err < 0 || p_response->success == 0) goto error; 263 setRadioState(RADIO_STATE_OFF); 264 } else if (onOff > 0 && sState == RADIO_STATE_OFF) { 265 err = at_send_command("AT+CFUN=1", &p_response); 266 if (err < 0|| p_response->success == 0) { 267 // Some stacks return an error when there is no SIM, 268 // but they really turn the RF portion on 269 // So, if we get an error, let's check to see if it 270 // turned on anyway 271 272 if (isRadioOn() != 1) { 273 goto error; 274 } 275 } 276 setRadioState(RADIO_STATE_SIM_NOT_READY); 277 } 278 279 at_response_free(p_response); 280 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 281 return; 282 error: 283 at_response_free(p_response); 284 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 285 } 286 287 static void requestOrSendDataCallList(RIL_Token *t); 288 289 static void onDataCallListChanged(void *param) 290 { 291 requestOrSendDataCallList(NULL); 292 } 293 294 static void requestDataCallList(void *data, size_t datalen, RIL_Token t) 295 { 296 requestOrSendDataCallList(&t); 297 } 298 299 static void requestOrSendDataCallList(RIL_Token *t) 300 { 301 ATResponse *p_response; 302 ATLine *p_cur; 303 int err; 304 int n = 0; 305 char *out; 306 307 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response); 308 if (err != 0 || p_response->success == 0) { 309 if (t != NULL) 310 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); 311 else 312 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 313 NULL, 0); 314 return; 315 } 316 317 for (p_cur = p_response->p_intermediates; p_cur != NULL; 318 p_cur = p_cur->p_next) 319 n++; 320 321 RIL_Data_Call_Response_v6 *responses = 322 alloca(n * sizeof(RIL_Data_Call_Response_v6)); 323 324 int i; 325 for (i = 0; i < n; i++) { 326 responses[i].status = -1; 327 responses[i].suggestedRetryTime = -1; 328 responses[i].cid = -1; 329 responses[i].active = -1; 330 responses[i].type = ""; 331 responses[i].ifname = ""; 332 responses[i].addresses = ""; 333 responses[i].dnses = ""; 334 responses[i].gateways = ""; 335 } 336 337 RIL_Data_Call_Response_v6 *response = responses; 338 for (p_cur = p_response->p_intermediates; p_cur != NULL; 339 p_cur = p_cur->p_next) { 340 char *line = p_cur->line; 341 342 err = at_tok_start(&line); 343 if (err < 0) 344 goto error; 345 346 err = at_tok_nextint(&line, &response->cid); 347 if (err < 0) 348 goto error; 349 350 err = at_tok_nextint(&line, &response->active); 351 if (err < 0) 352 goto error; 353 354 response++; 355 } 356 357 at_response_free(p_response); 358 359 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response); 360 if (err != 0 || p_response->success == 0) { 361 if (t != NULL) 362 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); 363 else 364 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 365 NULL, 0); 366 return; 367 } 368 369 for (p_cur = p_response->p_intermediates; p_cur != NULL; 370 p_cur = p_cur->p_next) { 371 char *line = p_cur->line; 372 int cid; 373 374 err = at_tok_start(&line); 375 if (err < 0) 376 goto error; 377 378 err = at_tok_nextint(&line, &cid); 379 if (err < 0) 380 goto error; 381 382 for (i = 0; i < n; i++) { 383 if (responses[i].cid == cid) 384 break; 385 } 386 387 if (i >= n) { 388 /* details for a context we didn't hear about in the last request */ 389 continue; 390 } 391 392 // Assume no error 393 responses[i].status = 0; 394 395 // type 396 err = at_tok_nextstr(&line, &out); 397 if (err < 0) 398 goto error; 399 responses[i].type = alloca(strlen(out) + 1); 400 strcpy(responses[i].type, out); 401 402 // APN ignored for v5 403 err = at_tok_nextstr(&line, &out); 404 if (err < 0) 405 goto error; 406 407 responses[i].ifname = alloca(strlen(PPP_TTY_PATH) + 1); 408 strcpy(responses[i].ifname, PPP_TTY_PATH); 409 410 err = at_tok_nextstr(&line, &out); 411 if (err < 0) 412 goto error; 413 414 responses[i].addresses = alloca(strlen(out) + 1); 415 strcpy(responses[i].addresses, out); 416 417 { 418 char propValue[PROP_VALUE_MAX]; 419 420 if (__system_property_get("ro.kernel.qemu", propValue) != 0) { 421 /* We are in the emulator - the dns servers are listed 422 * by the following system properties, setup in 423 * /system/etc/init.goldfish.sh: 424 * - net.eth0.dns1 425 * - net.eth0.dns2 426 * - net.eth0.dns3 427 * - net.eth0.dns4 428 */ 429 const int dnslist_sz = 128; 430 char* dnslist = alloca(dnslist_sz); 431 const char* separator = ""; 432 int nn; 433 434 dnslist[0] = 0; 435 for (nn = 1; nn <= 4; nn++) { 436 /* Probe net.eth0.dns<n> */ 437 char propName[PROP_NAME_MAX]; 438 snprintf(propName, sizeof propName, "net.eth0.dns%d", nn); 439 440 /* Ignore if undefined */ 441 if (__system_property_get(propName, propValue) == 0) { 442 continue; 443 } 444 445 /* Append the DNS IP address */ 446 strlcat(dnslist, separator, dnslist_sz); 447 strlcat(dnslist, propValue, dnslist_sz); 448 separator = " "; 449 } 450 responses[i].dnses = dnslist; 451 452 /* There is only on gateway in the emulator */ 453 responses[i].gateways = "10.0.2.2"; 454 } 455 else { 456 /* I don't know where we are, so use the public Google DNS 457 * servers by default and no gateway. 458 */ 459 responses[i].dnses = "8.8.8.8 8.8.4.4"; 460 responses[i].gateways = ""; 461 } 462 } 463 } 464 465 at_response_free(p_response); 466 467 if (t != NULL) 468 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses, 469 n * sizeof(RIL_Data_Call_Response_v6)); 470 else 471 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 472 responses, 473 n * sizeof(RIL_Data_Call_Response_v6)); 474 475 return; 476 477 error: 478 if (t != NULL) 479 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); 480 else 481 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, 482 NULL, 0); 483 484 at_response_free(p_response); 485 } 486 487 static void requestQueryNetworkSelectionMode( 488 void *data, size_t datalen, RIL_Token t) 489 { 490 int err; 491 ATResponse *p_response = NULL; 492 int response = 0; 493 char *line; 494 495 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response); 496 497 if (err < 0 || p_response->success == 0) { 498 goto error; 499 } 500 501 line = p_response->p_intermediates->line; 502 503 err = at_tok_start(&line); 504 505 if (err < 0) { 506 goto error; 507 } 508 509 err = at_tok_nextint(&line, &response); 510 511 if (err < 0) { 512 goto error; 513 } 514 515 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int)); 516 at_response_free(p_response); 517 return; 518 error: 519 at_response_free(p_response); 520 LOGE("requestQueryNetworkSelectionMode must never return error when radio is on"); 521 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 522 } 523 524 static void sendCallStateChanged(void *param) 525 { 526 RIL_onUnsolicitedResponse ( 527 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, 528 NULL, 0); 529 } 530 531 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t) 532 { 533 int err; 534 ATResponse *p_response; 535 ATLine *p_cur; 536 int countCalls; 537 int countValidCalls; 538 RIL_Call *p_calls; 539 RIL_Call **pp_calls; 540 int i; 541 int needRepoll = 0; 542 543 #ifdef WORKAROUND_ERRONEOUS_ANSWER 544 int prevIncomingOrWaitingLine; 545 546 prevIncomingOrWaitingLine = s_incomingOrWaitingLine; 547 s_incomingOrWaitingLine = -1; 548 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/ 549 550 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response); 551 552 if (err != 0 || p_response->success == 0) { 553 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 554 return; 555 } 556 557 /* count the calls */ 558 for (countCalls = 0, p_cur = p_response->p_intermediates 559 ; p_cur != NULL 560 ; p_cur = p_cur->p_next 561 ) { 562 countCalls++; 563 } 564 565 /* yes, there's an array of pointers and then an array of structures */ 566 567 pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *)); 568 p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call)); 569 memset (p_calls, 0, countCalls * sizeof(RIL_Call)); 570 571 /* init the pointer array */ 572 for(i = 0; i < countCalls ; i++) { 573 pp_calls[i] = &(p_calls[i]); 574 } 575 576 for (countValidCalls = 0, p_cur = p_response->p_intermediates 577 ; p_cur != NULL 578 ; p_cur = p_cur->p_next 579 ) { 580 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls); 581 582 if (err != 0) { 583 continue; 584 } 585 586 #ifdef WORKAROUND_ERRONEOUS_ANSWER 587 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING 588 || p_calls[countValidCalls].state == RIL_CALL_WAITING 589 ) { 590 s_incomingOrWaitingLine = p_calls[countValidCalls].index; 591 } 592 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/ 593 594 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE 595 && p_calls[countValidCalls].state != RIL_CALL_HOLDING 596 ) { 597 needRepoll = 1; 598 } 599 600 countValidCalls++; 601 } 602 603 #ifdef WORKAROUND_ERRONEOUS_ANSWER 604 // Basically: 605 // A call was incoming or waiting 606 // Now it's marked as active 607 // But we never answered it 608 // 609 // This is probably a bug, and the call will probably 610 // disappear from the call list in the next poll 611 if (prevIncomingOrWaitingLine >= 0 612 && s_incomingOrWaitingLine < 0 613 && s_expectAnswer == 0 614 ) { 615 for (i = 0; i < countValidCalls ; i++) { 616 617 if (p_calls[i].index == prevIncomingOrWaitingLine 618 && p_calls[i].state == RIL_CALL_ACTIVE 619 && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX 620 ) { 621 LOGI( 622 "Hit WORKAROUND_ERRONOUS_ANSWER case." 623 " Repoll count: %d\n", s_repollCallsCount); 624 s_repollCallsCount++; 625 goto error; 626 } 627 } 628 } 629 630 s_expectAnswer = 0; 631 s_repollCallsCount = 0; 632 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/ 633 634 RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls, 635 countValidCalls * sizeof (RIL_Call *)); 636 637 at_response_free(p_response); 638 639 #ifdef POLL_CALL_STATE 640 if (countValidCalls) { // We don't seem to get a "NO CARRIER" message from 641 // smd, so we're forced to poll until the call ends. 642 #else 643 if (needRepoll) { 644 #endif 645 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL); 646 } 647 648 return; 649 error: 650 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 651 at_response_free(p_response); 652 } 653 654 static void requestDial(void *data, size_t datalen, RIL_Token t) 655 { 656 RIL_Dial *p_dial; 657 char *cmd; 658 const char *clir; 659 int ret; 660 661 p_dial = (RIL_Dial *)data; 662 663 switch (p_dial->clir) { 664 case 1: clir = "I"; break; /*invocation*/ 665 case 2: clir = "i"; break; /*suppression*/ 666 default: 667 case 0: clir = ""; break; /*subscription default*/ 668 } 669 670 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir); 671 672 ret = at_send_command(cmd, NULL); 673 674 free(cmd); 675 676 /* success or failure is ignored by the upper layer here. 677 it will call GET_CURRENT_CALLS and determine success that way */ 678 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 679 } 680 681 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t) 682 { 683 RIL_SMS_WriteArgs *p_args; 684 char *cmd; 685 int length; 686 int err; 687 ATResponse *p_response = NULL; 688 689 p_args = (RIL_SMS_WriteArgs *)data; 690 691 length = strlen(p_args->pdu)/2; 692 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status); 693 694 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response); 695 696 if (err != 0 || p_response->success == 0) goto error; 697 698 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 699 at_response_free(p_response); 700 701 return; 702 error: 703 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 704 at_response_free(p_response); 705 } 706 707 static void requestHangup(void *data, size_t datalen, RIL_Token t) 708 { 709 int *p_line; 710 711 int ret; 712 char *cmd; 713 714 p_line = (int *)data; 715 716 // 3GPP 22.030 6.5.5 717 // "Releases a specific active call X" 718 asprintf(&cmd, "AT+CHLD=1%d", p_line[0]); 719 720 ret = at_send_command(cmd, NULL); 721 722 free(cmd); 723 724 /* success or failure is ignored by the upper layer here. 725 it will call GET_CURRENT_CALLS and determine success that way */ 726 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 727 } 728 729 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t) 730 { 731 ATResponse *p_response = NULL; 732 int err; 733 int response[2]; 734 char *line; 735 736 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response); 737 738 if (err < 0 || p_response->success == 0) { 739 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 740 goto error; 741 } 742 743 line = p_response->p_intermediates->line; 744 745 err = at_tok_start(&line); 746 if (err < 0) goto error; 747 748 err = at_tok_nextint(&line, &(response[0])); 749 if (err < 0) goto error; 750 751 err = at_tok_nextint(&line, &(response[1])); 752 if (err < 0) goto error; 753 754 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); 755 756 at_response_free(p_response); 757 return; 758 759 error: 760 LOGE("requestSignalStrength must never return an error when radio is on"); 761 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 762 at_response_free(p_response); 763 } 764 765 static void requestRegistrationState(int request, void *data, 766 size_t datalen, RIL_Token t) 767 { 768 int err; 769 int response[4]; 770 char * responseStr[4]; 771 ATResponse *p_response = NULL; 772 const char *cmd; 773 const char *prefix; 774 char *line, *p; 775 int commas; 776 int skip; 777 int count = 3; 778 779 780 if (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { 781 cmd = "AT+CREG?"; 782 prefix = "+CREG:"; 783 } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) { 784 cmd = "AT+CGREG?"; 785 prefix = "+CGREG:"; 786 } else { 787 assert(0); 788 goto error; 789 } 790 791 err = at_send_command_singleline(cmd, prefix, &p_response); 792 793 if (err != 0) goto error; 794 795 line = p_response->p_intermediates->line; 796 797 err = at_tok_start(&line); 798 if (err < 0) goto error; 799 800 /* Ok you have to be careful here 801 * The solicited version of the CREG response is 802 * +CREG: n, stat, [lac, cid] 803 * and the unsolicited version is 804 * +CREG: stat, [lac, cid] 805 * The <n> parameter is basically "is unsolicited creg on?" 806 * which it should always be 807 * 808 * Now we should normally get the solicited version here, 809 * but the unsolicited version could have snuck in 810 * so we have to handle both 811 * 812 * Also since the LAC and CID are only reported when registered, 813 * we can have 1, 2, 3, or 4 arguments here 814 * 815 * finally, a +CGREG: answer may have a fifth value that corresponds 816 * to the network type, as in; 817 * 818 * +CGREG: n, stat [,lac, cid [,networkType]] 819 */ 820 821 /* count number of commas */ 822 commas = 0; 823 for (p = line ; *p != '\0' ;p++) { 824 if (*p == ',') commas++; 825 } 826 827 switch (commas) { 828 case 0: /* +CREG: <stat> */ 829 err = at_tok_nextint(&line, &response[0]); 830 if (err < 0) goto error; 831 response[1] = -1; 832 response[2] = -1; 833 break; 834 835 case 1: /* +CREG: <n>, <stat> */ 836 err = at_tok_nextint(&line, &skip); 837 if (err < 0) goto error; 838 err = at_tok_nextint(&line, &response[0]); 839 if (err < 0) goto error; 840 response[1] = -1; 841 response[2] = -1; 842 if (err < 0) goto error; 843 break; 844 845 case 2: /* +CREG: <stat>, <lac>, <cid> */ 846 err = at_tok_nextint(&line, &response[0]); 847 if (err < 0) goto error; 848 err = at_tok_nexthexint(&line, &response[1]); 849 if (err < 0) goto error; 850 err = at_tok_nexthexint(&line, &response[2]); 851 if (err < 0) goto error; 852 break; 853 case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */ 854 err = at_tok_nextint(&line, &skip); 855 if (err < 0) goto error; 856 err = at_tok_nextint(&line, &response[0]); 857 if (err < 0) goto error; 858 err = at_tok_nexthexint(&line, &response[1]); 859 if (err < 0) goto error; 860 err = at_tok_nexthexint(&line, &response[2]); 861 if (err < 0) goto error; 862 break; 863 /* special case for CGREG, there is a fourth parameter 864 * that is the network type (unknown/gprs/edge/umts) 865 */ 866 case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */ 867 err = at_tok_nextint(&line, &skip); 868 if (err < 0) goto error; 869 err = at_tok_nextint(&line, &response[0]); 870 if (err < 0) goto error; 871 err = at_tok_nexthexint(&line, &response[1]); 872 if (err < 0) goto error; 873 err = at_tok_nexthexint(&line, &response[2]); 874 if (err < 0) goto error; 875 err = at_tok_nexthexint(&line, &response[3]); 876 if (err < 0) goto error; 877 count = 4; 878 break; 879 default: 880 goto error; 881 } 882 883 asprintf(&responseStr[0], "%d", response[0]); 884 asprintf(&responseStr[1], "%x", response[1]); 885 asprintf(&responseStr[2], "%x", response[2]); 886 887 if (count > 3) 888 asprintf(&responseStr[3], "%d", response[3]); 889 890 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*)); 891 at_response_free(p_response); 892 893 return; 894 error: 895 LOGE("requestRegistrationState must never return an error when radio is on"); 896 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 897 at_response_free(p_response); 898 } 899 900 static void requestOperator(void *data, size_t datalen, RIL_Token t) 901 { 902 int err; 903 int i; 904 int skip; 905 ATLine *p_cur; 906 char *response[3]; 907 908 memset(response, 0, sizeof(response)); 909 910 ATResponse *p_response = NULL; 911 912 err = at_send_command_multiline( 913 "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", 914 "+COPS:", &p_response); 915 916 /* we expect 3 lines here: 917 * +COPS: 0,0,"T - Mobile" 918 * +COPS: 0,1,"TMO" 919 * +COPS: 0,2,"310170" 920 */ 921 922 if (err != 0) goto error; 923 924 for (i = 0, p_cur = p_response->p_intermediates 925 ; p_cur != NULL 926 ; p_cur = p_cur->p_next, i++ 927 ) { 928 char *line = p_cur->line; 929 930 err = at_tok_start(&line); 931 if (err < 0) goto error; 932 933 err = at_tok_nextint(&line, &skip); 934 if (err < 0) goto error; 935 936 // If we're unregistered, we may just get 937 // a "+COPS: 0" response 938 if (!at_tok_hasmore(&line)) { 939 response[i] = NULL; 940 continue; 941 } 942 943 err = at_tok_nextint(&line, &skip); 944 if (err < 0) goto error; 945 946 // a "+COPS: 0, n" response is also possible 947 if (!at_tok_hasmore(&line)) { 948 response[i] = NULL; 949 continue; 950 } 951 952 err = at_tok_nextstr(&line, &(response[i])); 953 if (err < 0) goto error; 954 } 955 956 if (i != 3) { 957 /* expect 3 lines exactly */ 958 goto error; 959 } 960 961 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); 962 at_response_free(p_response); 963 964 return; 965 error: 966 LOGE("requestOperator must not return error when radio is on"); 967 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 968 at_response_free(p_response); 969 } 970 971 static void requestSendSMS(void *data, size_t datalen, RIL_Token t) 972 { 973 int err; 974 const char *smsc; 975 const char *pdu; 976 int tpLayerLength; 977 char *cmd1, *cmd2; 978 RIL_SMS_Response response; 979 ATResponse *p_response = NULL; 980 981 smsc = ((const char **)data)[0]; 982 pdu = ((const char **)data)[1]; 983 984 tpLayerLength = strlen(pdu)/2; 985 986 // "NULL for default SMSC" 987 if (smsc == NULL) { 988 smsc= "00"; 989 } 990 991 asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength); 992 asprintf(&cmd2, "%s%s", smsc, pdu); 993 994 err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response); 995 996 if (err != 0 || p_response->success == 0) goto error; 997 998 memset(&response, 0, sizeof(response)); 999 1000 /* FIXME fill in messageRef and ackPDU */ 1001 1002 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response)); 1003 at_response_free(p_response); 1004 1005 return; 1006 error: 1007 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1008 at_response_free(p_response); 1009 } 1010 1011 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t) 1012 { 1013 const char *apn; 1014 char *cmd; 1015 int err; 1016 ATResponse *p_response = NULL; 1017 1018 apn = ((const char **)data)[2]; 1019 1020 #ifdef USE_TI_COMMANDS 1021 // Config for multislot class 10 (probably default anyway eh?) 1022 err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"", 1023 NULL); 1024 1025 err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL); 1026 #endif /* USE_TI_COMMANDS */ 1027 1028 int fd, qmistatus; 1029 size_t cur = 0; 1030 size_t len; 1031 ssize_t written, rlen; 1032 char status[32] = {0}; 1033 int retry = 10; 1034 const char *pdp_type; 1035 1036 LOGD("requesting data connection to APN '%s'", apn); 1037 1038 fd = open ("/dev/qmi", O_RDWR); 1039 if (fd >= 0) { /* the device doesn't exist on the emulator */ 1040 1041 LOGD("opened the qmi device\n"); 1042 asprintf(&cmd, "up:%s", apn); 1043 len = strlen(cmd); 1044 1045 while (cur < len) { 1046 do { 1047 written = write (fd, cmd + cur, len - cur); 1048 } while (written < 0 && errno == EINTR); 1049 1050 if (written < 0) { 1051 LOGE("### ERROR writing to /dev/qmi"); 1052 close(fd); 1053 goto error; 1054 } 1055 1056 cur += written; 1057 } 1058 1059 // wait for interface to come online 1060 1061 do { 1062 sleep(1); 1063 do { 1064 rlen = read(fd, status, 31); 1065 } while (rlen < 0 && errno == EINTR); 1066 1067 if (rlen < 0) { 1068 LOGE("### ERROR reading from /dev/qmi"); 1069 close(fd); 1070 goto error; 1071 } else { 1072 status[rlen] = '\0'; 1073 LOGD("### status: %s", status); 1074 } 1075 } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry); 1076 1077 close(fd); 1078 1079 if (retry == 0) { 1080 LOGE("### Failed to get data connection up\n"); 1081 goto error; 1082 } 1083 1084 qmistatus = system("netcfg rmnet0 dhcp"); 1085 1086 LOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus); 1087 1088 if (qmistatus < 0) goto error; 1089 1090 } else { 1091 1092 if (datalen > 6 * sizeof(char *)) { 1093 pdp_type = ((const char **)data)[6]; 1094 } else { 1095 pdp_type = "IP"; 1096 } 1097 1098 asprintf(&cmd, "AT+CGDCONT=1,\"%s\",\"%s\",,0,0", pdp_type, apn); 1099 //FIXME check for error here 1100 err = at_send_command(cmd, NULL); 1101 free(cmd); 1102 1103 // Set required QoS params to default 1104 err = at_send_command("AT+CGQREQ=1", NULL); 1105 1106 // Set minimum QoS params to default 1107 err = at_send_command("AT+CGQMIN=1", NULL); 1108 1109 // packet-domain event reporting 1110 err = at_send_command("AT+CGEREP=1,0", NULL); 1111 1112 // Hangup anything that's happening there now 1113 err = at_send_command("AT+CGACT=1,0", NULL); 1114 1115 // Start data on PDP context 1 1116 err = at_send_command("ATD*99***1#", &p_response); 1117 1118 if (err < 0 || p_response->success == 0) { 1119 goto error; 1120 } 1121 } 1122 1123 requestOrSendDataCallList(&t); 1124 1125 at_response_free(p_response); 1126 1127 return; 1128 error: 1129 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1130 at_response_free(p_response); 1131 1132 } 1133 1134 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t) 1135 { 1136 int ackSuccess; 1137 int err; 1138 1139 ackSuccess = ((int *)data)[0]; 1140 1141 if (ackSuccess == 1) { 1142 err = at_send_command("AT+CNMA=1", NULL); 1143 } else if (ackSuccess == 0) { 1144 err = at_send_command("AT+CNMA=2", NULL); 1145 } else { 1146 LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n"); 1147 goto error; 1148 } 1149 1150 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1151 error: 1152 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1153 1154 } 1155 1156 static void requestSIM_IO(void *data, size_t datalen, RIL_Token t) 1157 { 1158 ATResponse *p_response = NULL; 1159 RIL_SIM_IO_Response sr; 1160 int err; 1161 char *cmd = NULL; 1162 RIL_SIM_IO_v6 *p_args; 1163 char *line; 1164 1165 memset(&sr, 0, sizeof(sr)); 1166 1167 p_args = (RIL_SIM_IO_v6 *)data; 1168 1169 /* FIXME handle pin2 */ 1170 1171 if (p_args->data == NULL) { 1172 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d", 1173 p_args->command, p_args->fileid, 1174 p_args->p1, p_args->p2, p_args->p3); 1175 } else { 1176 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s", 1177 p_args->command, p_args->fileid, 1178 p_args->p1, p_args->p2, p_args->p3, p_args->data); 1179 } 1180 1181 err = at_send_command_singleline(cmd, "+CRSM:", &p_response); 1182 1183 if (err < 0 || p_response->success == 0) { 1184 goto error; 1185 } 1186 1187 line = p_response->p_intermediates->line; 1188 1189 err = at_tok_start(&line); 1190 if (err < 0) goto error; 1191 1192 err = at_tok_nextint(&line, &(sr.sw1)); 1193 if (err < 0) goto error; 1194 1195 err = at_tok_nextint(&line, &(sr.sw2)); 1196 if (err < 0) goto error; 1197 1198 if (at_tok_hasmore(&line)) { 1199 err = at_tok_nextstr(&line, &(sr.simResponse)); 1200 if (err < 0) goto error; 1201 } 1202 1203 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr)); 1204 at_response_free(p_response); 1205 free(cmd); 1206 1207 return; 1208 error: 1209 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1210 at_response_free(p_response); 1211 free(cmd); 1212 1213 } 1214 1215 static void requestEnterSimPin(void* data, size_t datalen, RIL_Token t) 1216 { 1217 ATResponse *p_response = NULL; 1218 int err; 1219 char* cmd = NULL; 1220 const char** strings = (const char**)data;; 1221 1222 if ( datalen == sizeof(char*) ) { 1223 asprintf(&cmd, "AT+CPIN=%s", strings[0]); 1224 } else if ( datalen == 2*sizeof(char*) ) { 1225 asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]); 1226 } else 1227 goto error; 1228 1229 err = at_send_command_singleline(cmd, "+CPIN:", &p_response); 1230 free(cmd); 1231 1232 if (err < 0 || p_response->success == 0) { 1233 error: 1234 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0); 1235 } else { 1236 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1237 } 1238 at_response_free(p_response); 1239 } 1240 1241 1242 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t) 1243 { 1244 const char *ussdRequest; 1245 1246 ussdRequest = (char *)(data); 1247 1248 1249 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); 1250 1251 // @@@ TODO 1252 1253 } 1254 1255 1256 /*** Callback methods from the RIL library to us ***/ 1257 1258 /** 1259 * Call from RIL to us to make a RIL_REQUEST 1260 * 1261 * Must be completed with a call to RIL_onRequestComplete() 1262 * 1263 * RIL_onRequestComplete() may be called from any thread, before or after 1264 * this function returns. 1265 * 1266 * Will always be called from the same thread, so returning here implies 1267 * that the radio is ready to process another command (whether or not 1268 * the previous command has completed). 1269 */ 1270 static void 1271 onRequest (int request, void *data, size_t datalen, RIL_Token t) 1272 { 1273 ATResponse *p_response; 1274 int err; 1275 1276 LOGD("onRequest: %s", requestToString(request)); 1277 1278 /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS 1279 * when RADIO_STATE_UNAVAILABLE. 1280 */ 1281 if (sState == RADIO_STATE_UNAVAILABLE 1282 && request != RIL_REQUEST_GET_SIM_STATUS 1283 ) { 1284 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0); 1285 return; 1286 } 1287 1288 /* Ignore all non-power requests when RADIO_STATE_OFF 1289 * (except RIL_REQUEST_GET_SIM_STATUS) 1290 */ 1291 if (sState == RADIO_STATE_OFF 1292 && !(request == RIL_REQUEST_RADIO_POWER 1293 || request == RIL_REQUEST_GET_SIM_STATUS) 1294 ) { 1295 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0); 1296 return; 1297 } 1298 1299 switch (request) { 1300 case RIL_REQUEST_GET_SIM_STATUS: { 1301 RIL_CardStatus_v6 *p_card_status; 1302 char *p_buffer; 1303 int buffer_size; 1304 1305 int result = getCardStatus(&p_card_status); 1306 if (result == RIL_E_SUCCESS) { 1307 p_buffer = (char *)p_card_status; 1308 buffer_size = sizeof(*p_card_status); 1309 } else { 1310 p_buffer = NULL; 1311 buffer_size = 0; 1312 } 1313 RIL_onRequestComplete(t, result, p_buffer, buffer_size); 1314 freeCardStatus(p_card_status); 1315 break; 1316 } 1317 case RIL_REQUEST_GET_CURRENT_CALLS: 1318 requestGetCurrentCalls(data, datalen, t); 1319 break; 1320 case RIL_REQUEST_DIAL: 1321 requestDial(data, datalen, t); 1322 break; 1323 case RIL_REQUEST_HANGUP: 1324 requestHangup(data, datalen, t); 1325 break; 1326 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: 1327 // 3GPP 22.030 6.5.5 1328 // "Releases all held calls or sets User Determined User Busy 1329 // (UDUB) for a waiting call." 1330 at_send_command("AT+CHLD=0", NULL); 1331 1332 /* success or failure is ignored by the upper layer here. 1333 it will call GET_CURRENT_CALLS and determine success that way */ 1334 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1335 break; 1336 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: 1337 // 3GPP 22.030 6.5.5 1338 // "Releases all active calls (if any exist) and accepts 1339 // the other (held or waiting) call." 1340 at_send_command("AT+CHLD=1", NULL); 1341 1342 /* success or failure is ignored by the upper layer here. 1343 it will call GET_CURRENT_CALLS and determine success that way */ 1344 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1345 break; 1346 case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: 1347 // 3GPP 22.030 6.5.5 1348 // "Places all active calls (if any exist) on hold and accepts 1349 // the other (held or waiting) call." 1350 at_send_command("AT+CHLD=2", NULL); 1351 1352 #ifdef WORKAROUND_ERRONEOUS_ANSWER 1353 s_expectAnswer = 1; 1354 #endif /* WORKAROUND_ERRONEOUS_ANSWER */ 1355 1356 /* success or failure is ignored by the upper layer here. 1357 it will call GET_CURRENT_CALLS and determine success that way */ 1358 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1359 break; 1360 case RIL_REQUEST_ANSWER: 1361 at_send_command("ATA", NULL); 1362 1363 #ifdef WORKAROUND_ERRONEOUS_ANSWER 1364 s_expectAnswer = 1; 1365 #endif /* WORKAROUND_ERRONEOUS_ANSWER */ 1366 1367 /* success or failure is ignored by the upper layer here. 1368 it will call GET_CURRENT_CALLS and determine success that way */ 1369 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1370 break; 1371 case RIL_REQUEST_CONFERENCE: 1372 // 3GPP 22.030 6.5.5 1373 // "Adds a held call to the conversation" 1374 at_send_command("AT+CHLD=3", NULL); 1375 1376 /* success or failure is ignored by the upper layer here. 1377 it will call GET_CURRENT_CALLS and determine success that way */ 1378 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1379 break; 1380 case RIL_REQUEST_UDUB: 1381 /* user determined user busy */ 1382 /* sometimes used: ATH */ 1383 at_send_command("ATH", NULL); 1384 1385 /* success or failure is ignored by the upper layer here. 1386 it will call GET_CURRENT_CALLS and determine success that way */ 1387 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1388 break; 1389 1390 case RIL_REQUEST_SEPARATE_CONNECTION: 1391 { 1392 char cmd[12]; 1393 int party = ((int*)data)[0]; 1394 1395 // Make sure that party is in a valid range. 1396 // (Note: The Telephony middle layer imposes a range of 1 to 7. 1397 // It's sufficient for us to just make sure it's single digit.) 1398 if (party > 0 && party < 10) { 1399 sprintf(cmd, "AT+CHLD=2%d", party); 1400 at_send_command(cmd, NULL); 1401 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1402 } else { 1403 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1404 } 1405 } 1406 break; 1407 1408 case RIL_REQUEST_SIGNAL_STRENGTH: 1409 requestSignalStrength(data, datalen, t); 1410 break; 1411 case RIL_REQUEST_VOICE_REGISTRATION_STATE: 1412 case RIL_REQUEST_DATA_REGISTRATION_STATE: 1413 requestRegistrationState(request, data, datalen, t); 1414 break; 1415 case RIL_REQUEST_OPERATOR: 1416 requestOperator(data, datalen, t); 1417 break; 1418 case RIL_REQUEST_RADIO_POWER: 1419 requestRadioPower(data, datalen, t); 1420 break; 1421 case RIL_REQUEST_DTMF: { 1422 char c = ((char *)data)[0]; 1423 char *cmd; 1424 asprintf(&cmd, "AT+VTS=%c", (int)c); 1425 at_send_command(cmd, NULL); 1426 free(cmd); 1427 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1428 break; 1429 } 1430 case RIL_REQUEST_SEND_SMS: 1431 requestSendSMS(data, datalen, t); 1432 break; 1433 case RIL_REQUEST_SETUP_DATA_CALL: 1434 requestSetupDataCall(data, datalen, t); 1435 break; 1436 case RIL_REQUEST_SMS_ACKNOWLEDGE: 1437 requestSMSAcknowledge(data, datalen, t); 1438 break; 1439 1440 case RIL_REQUEST_GET_IMSI: 1441 p_response = NULL; 1442 err = at_send_command_numeric("AT+CIMI", &p_response); 1443 1444 if (err < 0 || p_response->success == 0) { 1445 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1446 } else { 1447 RIL_onRequestComplete(t, RIL_E_SUCCESS, 1448 p_response->p_intermediates->line, sizeof(char *)); 1449 } 1450 at_response_free(p_response); 1451 break; 1452 1453 case RIL_REQUEST_GET_IMEI: 1454 p_response = NULL; 1455 err = at_send_command_numeric("AT+CGSN", &p_response); 1456 1457 if (err < 0 || p_response->success == 0) { 1458 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1459 } else { 1460 RIL_onRequestComplete(t, RIL_E_SUCCESS, 1461 p_response->p_intermediates->line, sizeof(char *)); 1462 } 1463 at_response_free(p_response); 1464 break; 1465 1466 case RIL_REQUEST_SIM_IO: 1467 requestSIM_IO(data,datalen,t); 1468 break; 1469 1470 case RIL_REQUEST_SEND_USSD: 1471 requestSendUSSD(data, datalen, t); 1472 break; 1473 1474 case RIL_REQUEST_CANCEL_USSD: 1475 p_response = NULL; 1476 err = at_send_command_numeric("AT+CUSD=2", &p_response); 1477 1478 if (err < 0 || p_response->success == 0) { 1479 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1480 } else { 1481 RIL_onRequestComplete(t, RIL_E_SUCCESS, 1482 p_response->p_intermediates->line, sizeof(char *)); 1483 } 1484 at_response_free(p_response); 1485 break; 1486 1487 case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: 1488 at_send_command("AT+COPS=0", NULL); 1489 break; 1490 1491 case RIL_REQUEST_DATA_CALL_LIST: 1492 requestDataCallList(data, datalen, t); 1493 break; 1494 1495 case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: 1496 requestQueryNetworkSelectionMode(data, datalen, t); 1497 break; 1498 1499 case RIL_REQUEST_OEM_HOOK_RAW: 1500 // echo back data 1501 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen); 1502 break; 1503 1504 1505 case RIL_REQUEST_OEM_HOOK_STRINGS: { 1506 int i; 1507 const char ** cur; 1508 1509 LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen); 1510 1511 1512 for (i = (datalen / sizeof (char *)), cur = (const char **)data ; 1513 i > 0 ; cur++, i --) { 1514 LOGD("> '%s'", *cur); 1515 } 1516 1517 // echo back strings 1518 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen); 1519 break; 1520 } 1521 1522 case RIL_REQUEST_WRITE_SMS_TO_SIM: 1523 requestWriteSmsToSim(data, datalen, t); 1524 break; 1525 1526 case RIL_REQUEST_DELETE_SMS_ON_SIM: { 1527 char * cmd; 1528 p_response = NULL; 1529 asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]); 1530 err = at_send_command(cmd, &p_response); 1531 free(cmd); 1532 if (err < 0 || p_response->success == 0) { 1533 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); 1534 } else { 1535 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); 1536 } 1537 at_response_free(p_response); 1538 break; 1539 } 1540 1541 case RIL_REQUEST_ENTER_SIM_PIN: 1542 case RIL_REQUEST_ENTER_SIM_PUK: 1543 case RIL_REQUEST_ENTER_SIM_PIN2: 1544 case RIL_REQUEST_ENTER_SIM_PUK2: 1545 case RIL_REQUEST_CHANGE_SIM_PIN: 1546 case RIL_REQUEST_CHANGE_SIM_PIN2: 1547 requestEnterSimPin(data, datalen, t); 1548 break; 1549 1550 default: 1551 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); 1552 break; 1553 } 1554 } 1555 1556 /** 1557 * Synchronous call from the RIL to us to return current radio state. 1558 * RADIO_STATE_UNAVAILABLE should be the initial state. 1559 */ 1560 static RIL_RadioState 1561 currentState() 1562 { 1563 return sState; 1564 } 1565 /** 1566 * Call from RIL to us to find out whether a specific request code 1567 * is supported by this implementation. 1568 * 1569 * Return 1 for "supported" and 0 for "unsupported" 1570 */ 1571 1572 static int 1573 onSupports (int requestCode) 1574 { 1575 //@@@ todo 1576 1577 return 1; 1578 } 1579 1580 static void onCancel (RIL_Token t) 1581 { 1582 //@@@todo 1583 1584 } 1585 1586 static const char * getVersion(void) 1587 { 1588 return "android reference-ril 1.0"; 1589 } 1590 1591 static void 1592 setRadioState(RIL_RadioState newState) 1593 { 1594 RIL_RadioState oldState; 1595 1596 pthread_mutex_lock(&s_state_mutex); 1597 1598 oldState = sState; 1599 1600 if (s_closed > 0) { 1601 // If we're closed, the only reasonable state is 1602 // RADIO_STATE_UNAVAILABLE 1603 // This is here because things on the main thread 1604 // may attempt to change the radio state after the closed 1605 // event happened in another thread 1606 newState = RADIO_STATE_UNAVAILABLE; 1607 } 1608 1609 if (sState != newState || s_closed > 0) { 1610 sState = newState; 1611 1612 pthread_cond_broadcast (&s_state_cond); 1613 } 1614 1615 pthread_mutex_unlock(&s_state_mutex); 1616 1617 1618 /* do these outside of the mutex */ 1619 if (sState != oldState) { 1620 RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, 1621 NULL, 0); 1622 1623 /* FIXME onSimReady() and onRadioPowerOn() cannot be called 1624 * from the AT reader thread 1625 * Currently, this doesn't happen, but if that changes then these 1626 * will need to be dispatched on the request thread 1627 */ 1628 if (sState == RADIO_STATE_SIM_READY) { 1629 onSIMReady(); 1630 } else if (sState == RADIO_STATE_SIM_NOT_READY) { 1631 onRadioPowerOn(); 1632 } 1633 } 1634 } 1635 1636 /** Returns SIM_NOT_READY on error */ 1637 static SIM_Status 1638 getSIMStatus() 1639 { 1640 ATResponse *p_response = NULL; 1641 int err; 1642 int ret; 1643 char *cpinLine; 1644 char *cpinResult; 1645 1646 if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) { 1647 ret = SIM_NOT_READY; 1648 goto done; 1649 } 1650 1651 err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response); 1652 1653 if (err != 0) { 1654 ret = SIM_NOT_READY; 1655 goto done; 1656 } 1657 1658 switch (at_get_cme_error(p_response)) { 1659 case CME_SUCCESS: 1660 break; 1661 1662 case CME_SIM_NOT_INSERTED: 1663 ret = SIM_ABSENT; 1664 goto done; 1665 1666 default: 1667 ret = SIM_NOT_READY; 1668 goto done; 1669 } 1670 1671 /* CPIN? has succeeded, now look at the result */ 1672 1673 cpinLine = p_response->p_intermediates->line; 1674 err = at_tok_start (&cpinLine); 1675 1676 if (err < 0) { 1677 ret = SIM_NOT_READY; 1678 goto done; 1679 } 1680 1681 err = at_tok_nextstr(&cpinLine, &cpinResult); 1682 1683 if (err < 0) { 1684 ret = SIM_NOT_READY; 1685 goto done; 1686 } 1687 1688 if (0 == strcmp (cpinResult, "SIM PIN")) { 1689 ret = SIM_PIN; 1690 goto done; 1691 } else if (0 == strcmp (cpinResult, "SIM PUK")) { 1692 ret = SIM_PUK; 1693 goto done; 1694 } else if (0 == strcmp (cpinResult, "PH-NET PIN")) { 1695 return SIM_NETWORK_PERSONALIZATION; 1696 } else if (0 != strcmp (cpinResult, "READY")) { 1697 /* we're treating unsupported lock types as "sim absent" */ 1698 ret = SIM_ABSENT; 1699 goto done; 1700 } 1701 1702 at_response_free(p_response); 1703 p_response = NULL; 1704 cpinResult = NULL; 1705 1706 ret = SIM_READY; 1707 1708 done: 1709 at_response_free(p_response); 1710 return ret; 1711 } 1712 1713 1714 /** 1715 * Get the current card status. 1716 * 1717 * This must be freed using freeCardStatus. 1718 * @return: On success returns RIL_E_SUCCESS 1719 */ 1720 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status) { 1721 static RIL_AppStatus app_status_array[] = { 1722 // SIM_ABSENT = 0 1723 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN, 1724 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, 1725 // SIM_NOT_READY = 1 1726 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN, 1727 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, 1728 // SIM_READY = 2 1729 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY, 1730 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, 1731 // SIM_PIN = 3 1732 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN, 1733 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }, 1734 // SIM_PUK = 4 1735 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN, 1736 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN }, 1737 // SIM_NETWORK_PERSONALIZATION = 5 1738 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK, 1739 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN } 1740 }; 1741 RIL_CardState card_state; 1742 int num_apps; 1743 1744 int sim_status = getSIMStatus(); 1745 if (sim_status == SIM_ABSENT) { 1746 card_state = RIL_CARDSTATE_ABSENT; 1747 num_apps = 0; 1748 } else { 1749 card_state = RIL_CARDSTATE_PRESENT; 1750 num_apps = 1; 1751 } 1752 1753 // Allocate and initialize base card status. 1754 RIL_CardStatus_v6 *p_card_status = malloc(sizeof(RIL_CardStatus_v6)); 1755 p_card_status->card_state = card_state; 1756 p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN; 1757 p_card_status->gsm_umts_subscription_app_index = RIL_CARD_MAX_APPS; 1758 p_card_status->cdma_subscription_app_index = RIL_CARD_MAX_APPS; 1759 p_card_status->ims_subscription_app_index = RIL_CARD_MAX_APPS; 1760 p_card_status->num_applications = num_apps; 1761 1762 // Initialize application status 1763 int i; 1764 for (i = 0; i < RIL_CARD_MAX_APPS; i++) { 1765 p_card_status->applications[i] = app_status_array[SIM_ABSENT]; 1766 } 1767 1768 // Pickup the appropriate application status 1769 // that reflects sim_status for gsm. 1770 if (num_apps != 0) { 1771 // Only support one app, gsm 1772 p_card_status->num_applications = 1; 1773 p_card_status->gsm_umts_subscription_app_index = 0; 1774 1775 // Get the correct app status 1776 p_card_status->applications[0] = app_status_array[sim_status]; 1777 } 1778 1779 *pp_card_status = p_card_status; 1780 return RIL_E_SUCCESS; 1781 } 1782 1783 /** 1784 * Free the card status returned by getCardStatus 1785 */ 1786 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status) { 1787 free(p_card_status); 1788 } 1789 1790 /** 1791 * SIM ready means any commands that access the SIM will work, including: 1792 * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM 1793 * (all SMS-related commands) 1794 */ 1795 1796 static void pollSIMState (void *param) 1797 { 1798 ATResponse *p_response; 1799 int ret; 1800 1801 if (sState != RADIO_STATE_SIM_NOT_READY) { 1802 // no longer valid to poll 1803 return; 1804 } 1805 1806 switch(getSIMStatus()) { 1807 case SIM_ABSENT: 1808 case SIM_PIN: 1809 case SIM_PUK: 1810 case SIM_NETWORK_PERSONALIZATION: 1811 default: 1812 setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT); 1813 return; 1814 1815 case SIM_NOT_READY: 1816 RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL); 1817 return; 1818 1819 case SIM_READY: 1820 setRadioState(RADIO_STATE_SIM_READY); 1821 return; 1822 } 1823 } 1824 1825 /** returns 1 if on, 0 if off, and -1 on error */ 1826 static int isRadioOn() 1827 { 1828 ATResponse *p_response = NULL; 1829 int err; 1830 char *line; 1831 char ret; 1832 1833 err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response); 1834 1835 if (err < 0 || p_response->success == 0) { 1836 // assume radio is off 1837 goto error; 1838 } 1839 1840 line = p_response->p_intermediates->line; 1841 1842 err = at_tok_start(&line); 1843 if (err < 0) goto error; 1844 1845 err = at_tok_nextbool(&line, &ret); 1846 if (err < 0) goto error; 1847 1848 at_response_free(p_response); 1849 1850 return (int)ret; 1851 1852 error: 1853 1854 at_response_free(p_response); 1855 return -1; 1856 } 1857 1858 /** 1859 * Initialize everything that can be configured while we're still in 1860 * AT+CFUN=0 1861 */ 1862 static void initializeCallback(void *param) 1863 { 1864 ATResponse *p_response = NULL; 1865 int err; 1866 1867 setRadioState (RADIO_STATE_OFF); 1868 1869 at_handshake(); 1870 1871 /* note: we don't check errors here. Everything important will 1872 be handled in onATTimeout and onATReaderClosed */ 1873 1874 /* atchannel is tolerant of echo but it must */ 1875 /* have verbose result codes */ 1876 at_send_command("ATE0Q0V1", NULL); 1877 1878 /* No auto-answer */ 1879 at_send_command("ATS0=0", NULL); 1880 1881 /* Extended errors */ 1882 at_send_command("AT+CMEE=1", NULL); 1883 1884 /* Network registration events */ 1885 err = at_send_command("AT+CREG=2", &p_response); 1886 1887 /* some handsets -- in tethered mode -- don't support CREG=2 */ 1888 if (err < 0 || p_response->success == 0) { 1889 at_send_command("AT+CREG=1", NULL); 1890 } 1891 1892 at_response_free(p_response); 1893 1894 /* GPRS registration events */ 1895 at_send_command("AT+CGREG=1", NULL); 1896 1897 /* Call Waiting notifications */ 1898 at_send_command("AT+CCWA=1", NULL); 1899 1900 /* Alternating voice/data off */ 1901 at_send_command("AT+CMOD=0", NULL); 1902 1903 /* Not muted */ 1904 at_send_command("AT+CMUT=0", NULL); 1905 1906 /* +CSSU unsolicited supp service notifications */ 1907 at_send_command("AT+CSSN=0,1", NULL); 1908 1909 /* no connected line identification */ 1910 at_send_command("AT+COLP=0", NULL); 1911 1912 /* HEX character set */ 1913 at_send_command("AT+CSCS=\"HEX\"", NULL); 1914 1915 /* USSD unsolicited */ 1916 at_send_command("AT+CUSD=1", NULL); 1917 1918 /* Enable +CGEV GPRS event notifications, but don't buffer */ 1919 at_send_command("AT+CGEREP=1,0", NULL); 1920 1921 /* SMS PDU mode */ 1922 at_send_command("AT+CMGF=0", NULL); 1923 1924 #ifdef USE_TI_COMMANDS 1925 1926 at_send_command("AT%CPI=3", NULL); 1927 1928 /* TI specific -- notifications when SMS is ready (currently ignored) */ 1929 at_send_command("AT%CSTAT=1", NULL); 1930 1931 #endif /* USE_TI_COMMANDS */ 1932 1933 1934 /* assume radio is off on error */ 1935 if (isRadioOn() > 0) { 1936 setRadioState (RADIO_STATE_SIM_NOT_READY); 1937 } 1938 } 1939 1940 static void waitForClose() 1941 { 1942 pthread_mutex_lock(&s_state_mutex); 1943 1944 while (s_closed == 0) { 1945 pthread_cond_wait(&s_state_cond, &s_state_mutex); 1946 } 1947 1948 pthread_mutex_unlock(&s_state_mutex); 1949 } 1950 1951 /** 1952 * Called by atchannel when an unsolicited line appears 1953 * This is called on atchannel's reader thread. AT commands may 1954 * not be issued here 1955 */ 1956 static void onUnsolicited (const char *s, const char *sms_pdu) 1957 { 1958 char *line = NULL; 1959 int err; 1960 1961 /* Ignore unsolicited responses until we're initialized. 1962 * This is OK because the RIL library will poll for initial state 1963 */ 1964 if (sState == RADIO_STATE_UNAVAILABLE) { 1965 return; 1966 } 1967 1968 if (strStartsWith(s, "%CTZV:")) { 1969 /* TI specific -- NITZ time */ 1970 char *response; 1971 1972 line = strdup(s); 1973 at_tok_start(&line); 1974 1975 err = at_tok_nextstr(&line, &response); 1976 1977 if (err != 0) { 1978 LOGE("invalid NITZ line %s\n", s); 1979 } else { 1980 RIL_onUnsolicitedResponse ( 1981 RIL_UNSOL_NITZ_TIME_RECEIVED, 1982 response, strlen(response)); 1983 } 1984 } else if (strStartsWith(s,"+CRING:") 1985 || strStartsWith(s,"RING") 1986 || strStartsWith(s,"NO CARRIER") 1987 || strStartsWith(s,"+CCWA") 1988 ) { 1989 RIL_onUnsolicitedResponse ( 1990 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, 1991 NULL, 0); 1992 #ifdef WORKAROUND_FAKE_CGEV 1993 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function 1994 #endif /* WORKAROUND_FAKE_CGEV */ 1995 } else if (strStartsWith(s,"+CREG:") 1996 || strStartsWith(s,"+CGREG:") 1997 ) { 1998 RIL_onUnsolicitedResponse ( 1999 RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, 2000 NULL, 0); 2001 #ifdef WORKAROUND_FAKE_CGEV 2002 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); 2003 #endif /* WORKAROUND_FAKE_CGEV */ 2004 } else if (strStartsWith(s, "+CMT:")) { 2005 RIL_onUnsolicitedResponse ( 2006 RIL_UNSOL_RESPONSE_NEW_SMS, 2007 sms_pdu, strlen(sms_pdu)); 2008 } else if (strStartsWith(s, "+CDS:")) { 2009 RIL_onUnsolicitedResponse ( 2010 RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, 2011 sms_pdu, strlen(sms_pdu)); 2012 } else if (strStartsWith(s, "+CGEV:")) { 2013 /* Really, we can ignore NW CLASS and ME CLASS events here, 2014 * but right now we don't since extranous 2015 * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated 2016 */ 2017 /* can't issue AT commands here -- call on main thread */ 2018 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); 2019 #ifdef WORKAROUND_FAKE_CGEV 2020 } else if (strStartsWith(s, "+CME ERROR: 150")) { 2021 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); 2022 #endif /* WORKAROUND_FAKE_CGEV */ 2023 } 2024 } 2025 2026 /* Called on command or reader thread */ 2027 static void onATReaderClosed() 2028 { 2029 LOGI("AT channel closed\n"); 2030 at_close(); 2031 s_closed = 1; 2032 2033 setRadioState (RADIO_STATE_UNAVAILABLE); 2034 } 2035 2036 /* Called on command thread */ 2037 static void onATTimeout() 2038 { 2039 LOGI("AT channel timeout; closing\n"); 2040 at_close(); 2041 2042 s_closed = 1; 2043 2044 /* FIXME cause a radio reset here */ 2045 2046 setRadioState (RADIO_STATE_UNAVAILABLE); 2047 } 2048 2049 static void usage(char *s) 2050 { 2051 #ifdef RIL_SHLIB 2052 fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n"); 2053 #else 2054 fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s); 2055 exit(-1); 2056 #endif 2057 } 2058 2059 static void * 2060 mainLoop(void *param) 2061 { 2062 int fd; 2063 int ret; 2064 2065 AT_DUMP("== ", "entering mainLoop()", -1 ); 2066 at_set_on_reader_closed(onATReaderClosed); 2067 at_set_on_timeout(onATTimeout); 2068 2069 for (;;) { 2070 fd = -1; 2071 while (fd < 0) { 2072 if (s_port > 0) { 2073 fd = socket_loopback_client(s_port, SOCK_STREAM); 2074 } else if (s_device_socket) { 2075 if (!strcmp(s_device_path, "/dev/socket/qemud")) { 2076 /* Before trying to connect to /dev/socket/qemud (which is 2077 * now another "legacy" way of communicating with the 2078 * emulator), we will try to connecto to gsm service via 2079 * qemu pipe. */ 2080 fd = qemu_pipe_open("qemud:gsm"); 2081 if (fd < 0) { 2082 /* Qemu-specific control socket */ 2083 fd = socket_local_client( "qemud", 2084 ANDROID_SOCKET_NAMESPACE_RESERVED, 2085 SOCK_STREAM ); 2086 if (fd >= 0 ) { 2087 char answer[2]; 2088 2089 if ( write(fd, "gsm", 3) != 3 || 2090 read(fd, answer, 2) != 2 || 2091 memcmp(answer, "OK", 2) != 0) 2092 { 2093 close(fd); 2094 fd = -1; 2095 } 2096 } 2097 } 2098 } 2099 else 2100 fd = socket_local_client( s_device_path, 2101 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, 2102 SOCK_STREAM ); 2103 } else if (s_device_path != NULL) { 2104 fd = open (s_device_path, O_RDWR); 2105 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) { 2106 /* disable echo on serial ports */ 2107 struct termios ios; 2108 tcgetattr( fd, &ios ); 2109 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ 2110 tcsetattr( fd, TCSANOW, &ios ); 2111 } 2112 } 2113 2114 if (fd < 0) { 2115 perror ("opening AT interface. retrying..."); 2116 sleep(10); 2117 /* never returns */ 2118 } 2119 } 2120 2121 s_closed = 0; 2122 ret = at_open(fd, onUnsolicited); 2123 2124 if (ret < 0) { 2125 LOGE ("AT error %d on at_open\n", ret); 2126 return 0; 2127 } 2128 2129 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0); 2130 2131 // Give initializeCallback a chance to dispatched, since 2132 // we don't presently have a cancellation mechanism 2133 sleep(1); 2134 2135 waitForClose(); 2136 LOGI("Re-opening after close"); 2137 } 2138 } 2139 2140 #ifdef RIL_SHLIB 2141 2142 pthread_t s_tid_mainloop; 2143 2144 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv) 2145 { 2146 int ret; 2147 int fd = -1; 2148 int opt; 2149 pthread_attr_t attr; 2150 2151 s_rilenv = env; 2152 2153 while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) { 2154 switch (opt) { 2155 case 'p': 2156 s_port = atoi(optarg); 2157 if (s_port == 0) { 2158 usage(argv[0]); 2159 return NULL; 2160 } 2161 LOGI("Opening loopback port %d\n", s_port); 2162 break; 2163 2164 case 'd': 2165 s_device_path = optarg; 2166 LOGI("Opening tty device %s\n", s_device_path); 2167 break; 2168 2169 case 's': 2170 s_device_path = optarg; 2171 s_device_socket = 1; 2172 LOGI("Opening socket %s\n", s_device_path); 2173 break; 2174 2175 default: 2176 usage(argv[0]); 2177 return NULL; 2178 } 2179 } 2180 2181 if (s_port < 0 && s_device_path == NULL) { 2182 usage(argv[0]); 2183 return NULL; 2184 } 2185 2186 pthread_attr_init (&attr); 2187 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 2188 ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL); 2189 2190 return &s_callbacks; 2191 } 2192 #else /* RIL_SHLIB */ 2193 int main (int argc, char **argv) 2194 { 2195 int ret; 2196 int fd = -1; 2197 int opt; 2198 2199 while ( -1 != (opt = getopt(argc, argv, "p:d:"))) { 2200 switch (opt) { 2201 case 'p': 2202 s_port = atoi(optarg); 2203 if (s_port == 0) { 2204 usage(argv[0]); 2205 } 2206 LOGI("Opening loopback port %d\n", s_port); 2207 break; 2208 2209 case 'd': 2210 s_device_path = optarg; 2211 LOGI("Opening tty device %s\n", s_device_path); 2212 break; 2213 2214 case 's': 2215 s_device_path = optarg; 2216 s_device_socket = 1; 2217 LOGI("Opening socket %s\n", s_device_path); 2218 break; 2219 2220 default: 2221 usage(argv[0]); 2222 } 2223 } 2224 2225 if (s_port < 0 && s_device_path == NULL) { 2226 usage(argv[0]); 2227 } 2228 2229 RIL_register(&s_callbacks); 2230 2231 mainLoop(NULL); 2232 2233 return 0; 2234 } 2235 2236 #endif /* RIL_SHLIB */ 2237