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