1 /* //device/system/reference-ril/reference-ril.c
3 ** Copyright 2006, The Android Open Source Project
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
9 ** http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <telephony/ril.h>
24 #include <sys/types.h>
29 #include "atchannel.h"
33 #include <sys/socket.h>
34 #include <cutils/sockets.h>
38 #include <utils/Log.h>
40 #define MAX_AT_RESPONSE 0x1000
42 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
43 #define PPP_TTY_PATH "/dev/omap_csmi_tty1"
45 #ifdef USE_TI_COMMANDS
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
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
59 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
60 static RIL_RadioState currentState();
61 static int onSupports (int requestCode);
62 static void onCancel (RIL_Token t);
63 static const char *getVersion();
64 static int isRadioOn();
65 static int getSIMStatus();
66 static int getCardStatus(RIL_CardStatus **pp_card_status);
67 static void freeCardStatus(RIL_CardStatus *p_card_status);
68 static void onDataCallListChanged(void *param);
70 extern const char * requestToString(int request);
72 /*** Static Variables ***/
73 static const RIL_RadioFunctions s_callbacks = {
83 static const struct RIL_Env *s_rilenv;
85 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
86 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
87 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
90 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
92 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
93 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
95 static int s_port = -1;
96 static const char * s_device_path = NULL;
97 static int s_device_socket = 0;
99 /* trigger change to this with s_state_cond */
100 static int s_closed = 0;
102 static int sFD; /* file desc of AT channel */
103 static char sATBuffer[MAX_AT_RESPONSE+1];
104 static char *sATBufferCur = NULL;
106 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
107 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
108 static const struct timeval TIMEVAL_0 = {0,0};
110 #ifdef WORKAROUND_ERRONEOUS_ANSWER
111 // Max number of times we'll try to repoll when we think
112 // we have a AT+CLCC race condition
113 #define REPOLL_CALLS_COUNT_MAX 4
115 // Line index that was incoming or waiting at last poll, or -1 for none
116 static int s_incomingOrWaitingLine = -1;
117 // Number of times we've asked for a repoll of AT+CLCC
118 static int s_repollCallsCount = 0;
119 // Should we expect a call to be answered in the next CLCC?
120 static int s_expectAnswer = 0;
121 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
123 static void pollSIMState (void *param);
124 static void setRadioState(RIL_RadioState newState);
126 static int clccStateToRILState(int state, RIL_CallState *p_state)
130 case 0: *p_state = RIL_CALL_ACTIVE; return 0;
131 case 1: *p_state = RIL_CALL_HOLDING; return 0;
132 case 2: *p_state = RIL_CALL_DIALING; return 0;
133 case 3: *p_state = RIL_CALL_ALERTING; return 0;
134 case 4: *p_state = RIL_CALL_INCOMING; return 0;
135 case 5: *p_state = RIL_CALL_WAITING; return 0;
141 * Note: directly modified line and has *p_call point directly into
144 static int callFromCLCCLine(char *line, RIL_Call *p_call)
146 //+CLCC: 1,0,2,0,0,\"+18005551212\",145
147 // index,isMT,state,mode,isMpty(,number,TOA)?
153 err = at_tok_start(&line);
154 if (err < 0) goto error;
156 err = at_tok_nextint(&line, &(p_call->index));
157 if (err < 0) goto error;
159 err = at_tok_nextbool(&line, &(p_call->isMT));
160 if (err < 0) goto error;
162 err = at_tok_nextint(&line, &state);
163 if (err < 0) goto error;
165 err = clccStateToRILState(state, &(p_call->state));
166 if (err < 0) goto error;
168 err = at_tok_nextint(&line, &mode);
169 if (err < 0) goto error;
171 p_call->isVoice = (mode == 0);
173 err = at_tok_nextbool(&line, &(p_call->isMpty));
174 if (err < 0) goto error;
176 if (at_tok_hasmore(&line)) {
177 err = at_tok_nextstr(&line, &(p_call->number));
179 /* tolerate null here */
180 if (err < 0) return 0;
182 // Some lame implementations return strings
183 // like "NOT AVAILABLE" in the CLCC line
184 if (p_call->number != NULL
185 && 0 == strspn(p_call->number, "+0123456789")
187 p_call->number = NULL;
190 err = at_tok_nextint(&line, &p_call->toa);
191 if (err < 0) goto error;
197 LOGE("invalid CLCC line\n");
202 /** do post-AT+CFUN=1 initialization */
203 static void onRadioPowerOn()
205 #ifdef USE_TI_COMMANDS
206 /* Must be after CFUN=1 */
207 /* TI specific -- notifications for CPHS things such */
208 /* as CPHS message waiting indicator */
210 at_send_command("AT%CPHS=1", NULL);
212 /* TI specific -- enable NITZ unsol notifs */
213 at_send_command("AT%CTZV=1", NULL);
219 /** do post- SIM ready initialization */
220 static void onSIMReady()
222 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
224 * Always send SMS messages directly to the TE
226 * mode = 1 // discard when link is reserved (link should never be
228 * mt = 2 // most messages routed to TE
229 * bm = 2 // new cell BM's routed to TE
230 * ds = 1 // Status reports routed to TE
231 * bfr = 1 // flush buffer
233 at_send_command("AT+CNMI=1,2,2,1,1", NULL);
236 static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
241 ATResponse *p_response = NULL;
243 assert (datalen >= sizeof(int *));
244 onOff = ((int *)data)[0];
246 if (onOff == 0 && sState != RADIO_STATE_OFF) {
247 err = at_send_command("AT+CFUN=0", &p_response);
248 if (err < 0 || p_response->success == 0) goto error;
249 setRadioState(RADIO_STATE_OFF);
250 } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
251 err = at_send_command("AT+CFUN=1", &p_response);
252 if (err < 0|| p_response->success == 0) {
253 // Some stacks return an error when there is no SIM,
254 // but they really turn the RF portion on
255 // So, if we get an error, let's check to see if it
258 if (isRadioOn() != 1) {
262 setRadioState(RADIO_STATE_SIM_NOT_READY);
265 at_response_free(p_response);
266 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
269 at_response_free(p_response);
270 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
273 static void requestOrSendDataCallList(RIL_Token *t);
275 static void onDataCallListChanged(void *param)
277 requestOrSendDataCallList(NULL);
280 static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
282 requestOrSendDataCallList(&t);
285 static void requestOrSendDataCallList(RIL_Token *t)
287 ATResponse *p_response;
293 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
294 if (err != 0 || p_response->success == 0) {
296 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
298 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
303 for (p_cur = p_response->p_intermediates; p_cur != NULL;
304 p_cur = p_cur->p_next)
307 RIL_Data_Call_Response *responses =
308 alloca(n * sizeof(RIL_Data_Call_Response));
311 for (i = 0; i < n; i++) {
312 responses[i].cid = -1;
313 responses[i].active = -1;
314 responses[i].type = "";
315 responses[i].apn = "";
316 responses[i].address = "";
319 RIL_Data_Call_Response *response = responses;
320 for (p_cur = p_response->p_intermediates; p_cur != NULL;
321 p_cur = p_cur->p_next) {
322 char *line = p_cur->line;
324 err = at_tok_start(&line);
328 err = at_tok_nextint(&line, &response->cid);
332 err = at_tok_nextint(&line, &response->active);
339 at_response_free(p_response);
341 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
342 if (err != 0 || p_response->success == 0) {
344 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
346 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
351 for (p_cur = p_response->p_intermediates; p_cur != NULL;
352 p_cur = p_cur->p_next) {
353 char *line = p_cur->line;
360 err = at_tok_start(&line);
364 err = at_tok_nextint(&line, &cid);
368 for (i = 0; i < n; i++) {
369 if (responses[i].cid == cid)
374 /* details for a context we didn't hear about in the last request */
378 err = at_tok_nextstr(&line, &out);
382 responses[i].type = alloca(strlen(out) + 1);
383 strcpy(responses[i].type, out);
385 err = at_tok_nextstr(&line, &out);
389 responses[i].apn = alloca(strlen(out) + 1);
390 strcpy(responses[i].apn, out);
392 err = at_tok_nextstr(&line, &out);
396 responses[i].address = alloca(strlen(out) + 1);
397 strcpy(responses[i].address, out);
400 at_response_free(p_response);
403 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
404 n * sizeof(RIL_Data_Call_Response));
406 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
408 n * sizeof(RIL_Data_Call_Response));
414 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
416 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
419 at_response_free(p_response);
422 static void requestQueryNetworkSelectionMode(
423 void *data, size_t datalen, RIL_Token t)
426 ATResponse *p_response = NULL;
430 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
432 if (err < 0 || p_response->success == 0) {
436 line = p_response->p_intermediates->line;
438 err = at_tok_start(&line);
444 err = at_tok_nextint(&line, &response);
450 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
451 at_response_free(p_response);
454 at_response_free(p_response);
455 LOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
456 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
459 static void sendCallStateChanged(void *param)
461 RIL_onUnsolicitedResponse (
462 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
466 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
469 ATResponse *p_response;
478 #ifdef WORKAROUND_ERRONEOUS_ANSWER
479 int prevIncomingOrWaitingLine;
481 prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
482 s_incomingOrWaitingLine = -1;
483 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
485 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
487 if (err != 0 || p_response->success == 0) {
488 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
492 /* count the calls */
493 for (countCalls = 0, p_cur = p_response->p_intermediates
495 ; p_cur = p_cur->p_next
500 /* yes, there's an array of pointers and then an array of structures */
502 pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
503 p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
504 memset (p_calls, 0, countCalls * sizeof(RIL_Call));
506 /* init the pointer array */
507 for(i = 0; i < countCalls ; i++) {
508 pp_calls[i] = &(p_calls[i]);
511 for (countValidCalls = 0, p_cur = p_response->p_intermediates
513 ; p_cur = p_cur->p_next
515 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
521 #ifdef WORKAROUND_ERRONEOUS_ANSWER
522 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
523 || p_calls[countValidCalls].state == RIL_CALL_WAITING
525 s_incomingOrWaitingLine = p_calls[countValidCalls].index;
527 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
529 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
530 && p_calls[countValidCalls].state != RIL_CALL_HOLDING
538 #ifdef WORKAROUND_ERRONEOUS_ANSWER
540 // A call was incoming or waiting
541 // Now it's marked as active
542 // But we never answered it
544 // This is probably a bug, and the call will probably
545 // disappear from the call list in the next poll
546 if (prevIncomingOrWaitingLine >= 0
547 && s_incomingOrWaitingLine < 0
548 && s_expectAnswer == 0
550 for (i = 0; i < countValidCalls ; i++) {
552 if (p_calls[i].index == prevIncomingOrWaitingLine
553 && p_calls[i].state == RIL_CALL_ACTIVE
554 && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
557 "Hit WORKAROUND_ERRONOUS_ANSWER case."
558 " Repoll count: %d\n", s_repollCallsCount);
559 s_repollCallsCount++;
566 s_repollCallsCount = 0;
567 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
569 RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
570 countValidCalls * sizeof (RIL_Call *));
572 at_response_free(p_response);
574 #ifdef POLL_CALL_STATE
575 if (countValidCalls) { // We don't seem to get a "NO CARRIER" message from
576 // smd, so we're forced to poll until the call ends.
580 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
585 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
586 at_response_free(p_response);
589 static void requestDial(void *data, size_t datalen, RIL_Token t)
596 p_dial = (RIL_Dial *)data;
598 switch (p_dial->clir) {
599 case 1: clir = "I"; break; /*invocation*/
600 case 2: clir = "i"; break; /*suppression*/
602 case 0: clir = ""; break; /*subscription default*/
605 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
607 ret = at_send_command(cmd, NULL);
611 /* success or failure is ignored by the upper layer here.
612 it will call GET_CURRENT_CALLS and determine success that way */
613 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
616 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
618 RIL_SMS_WriteArgs *p_args;
622 ATResponse *p_response = NULL;
624 p_args = (RIL_SMS_WriteArgs *)data;
626 length = strlen(p_args->pdu)/2;
627 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
629 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
631 if (err != 0 || p_response->success == 0) goto error;
633 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
634 at_response_free(p_response);
638 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
639 at_response_free(p_response);
642 static void requestHangup(void *data, size_t datalen, RIL_Token t)
649 p_line = (int *)data;
652 // "Releases a specific active call X"
653 asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
655 ret = at_send_command(cmd, NULL);
659 /* success or failure is ignored by the upper layer here.
660 it will call GET_CURRENT_CALLS and determine success that way */
661 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
664 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
666 ATResponse *p_response = NULL;
671 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
673 if (err < 0 || p_response->success == 0) {
674 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
678 line = p_response->p_intermediates->line;
680 err = at_tok_start(&line);
681 if (err < 0) goto error;
683 err = at_tok_nextint(&line, &(response[0]));
684 if (err < 0) goto error;
686 err = at_tok_nextint(&line, &(response[1]));
687 if (err < 0) goto error;
689 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
691 at_response_free(p_response);
695 LOGE("requestSignalStrength must never return an error when radio is on");
696 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
697 at_response_free(p_response);
700 static void requestRegistrationState(int request, void *data,
701 size_t datalen, RIL_Token t)
705 char * responseStr[4];
706 ATResponse *p_response = NULL;
715 if (request == RIL_REQUEST_REGISTRATION_STATE) {
718 } else if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
726 err = at_send_command_singleline(cmd, prefix, &p_response);
728 if (err != 0) goto error;
730 line = p_response->p_intermediates->line;
732 err = at_tok_start(&line);
733 if (err < 0) goto error;
735 /* Ok you have to be careful here
736 * The solicited version of the CREG response is
737 * +CREG: n, stat, [lac, cid]
738 * and the unsolicited version is
739 * +CREG: stat, [lac, cid]
740 * The <n> parameter is basically "is unsolicited creg on?"
741 * which it should always be
743 * Now we should normally get the solicited version here,
744 * but the unsolicited version could have snuck in
745 * so we have to handle both
747 * Also since the LAC and CID are only reported when registered,
748 * we can have 1, 2, 3, or 4 arguments here
750 * finally, a +CGREG: answer may have a fifth value that corresponds
751 * to the network type, as in;
753 * +CGREG: n, stat [,lac, cid [,networkType]]
756 /* count number of commas */
758 for (p = line ; *p != '\0' ;p++) {
759 if (*p == ',') commas++;
763 case 0: /* +CREG: <stat> */
764 err = at_tok_nextint(&line, &response[0]);
765 if (err < 0) goto error;
770 case 1: /* +CREG: <n>, <stat> */
771 err = at_tok_nextint(&line, &skip);
772 if (err < 0) goto error;
773 err = at_tok_nextint(&line, &response[0]);
774 if (err < 0) goto error;
777 if (err < 0) goto error;
780 case 2: /* +CREG: <stat>, <lac>, <cid> */
781 err = at_tok_nextint(&line, &response[0]);
782 if (err < 0) goto error;
783 err = at_tok_nexthexint(&line, &response[1]);
784 if (err < 0) goto error;
785 err = at_tok_nexthexint(&line, &response[2]);
786 if (err < 0) goto error;
788 case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
789 err = at_tok_nextint(&line, &skip);
790 if (err < 0) goto error;
791 err = at_tok_nextint(&line, &response[0]);
792 if (err < 0) goto error;
793 err = at_tok_nexthexint(&line, &response[1]);
794 if (err < 0) goto error;
795 err = at_tok_nexthexint(&line, &response[2]);
796 if (err < 0) goto error;
798 /* special case for CGREG, there is a fourth parameter
799 * that is the network type (unknown/gprs/edge/umts)
801 case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
802 err = at_tok_nextint(&line, &skip);
803 if (err < 0) goto error;
804 err = at_tok_nextint(&line, &response[0]);
805 if (err < 0) goto error;
806 err = at_tok_nexthexint(&line, &response[1]);
807 if (err < 0) goto error;
808 err = at_tok_nexthexint(&line, &response[2]);
809 if (err < 0) goto error;
810 err = at_tok_nexthexint(&line, &response[3]);
811 if (err < 0) goto error;
818 asprintf(&responseStr[0], "%d", response[0]);
819 asprintf(&responseStr[1], "%d", response[1]);
820 asprintf(&responseStr[2], "%d", response[2]);
823 asprintf(&responseStr[3], "%d", response[3]);
825 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
826 at_response_free(p_response);
830 LOGE("requestRegistrationState must never return an error when radio is on");
831 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
832 at_response_free(p_response);
835 static void requestOperator(void *data, size_t datalen, RIL_Token t)
843 memset(response, 0, sizeof(response));
845 ATResponse *p_response = NULL;
847 err = at_send_command_multiline(
848 "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
849 "+COPS:", &p_response);
851 /* we expect 3 lines here:
852 * +COPS: 0,0,"T - Mobile"
854 * +COPS: 0,2,"310170"
857 if (err != 0) goto error;
859 for (i = 0, p_cur = p_response->p_intermediates
861 ; p_cur = p_cur->p_next, i++
863 char *line = p_cur->line;
865 err = at_tok_start(&line);
866 if (err < 0) goto error;
868 err = at_tok_nextint(&line, &skip);
869 if (err < 0) goto error;
871 // If we're unregistered, we may just get
872 // a "+COPS: 0" response
873 if (!at_tok_hasmore(&line)) {
878 err = at_tok_nextint(&line, &skip);
879 if (err < 0) goto error;
881 // a "+COPS: 0, n" response is also possible
882 if (!at_tok_hasmore(&line)) {
887 err = at_tok_nextstr(&line, &(response[i]));
888 if (err < 0) goto error;
892 /* expect 3 lines exactly */
896 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
897 at_response_free(p_response);
901 LOGE("requestOperator must not return error when radio is on");
902 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
903 at_response_free(p_response);
906 static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
913 RIL_SMS_Response response;
914 ATResponse *p_response = NULL;
916 smsc = ((const char **)data)[0];
917 pdu = ((const char **)data)[1];
919 tpLayerLength = strlen(pdu)/2;
921 // "NULL for default SMSC"
926 asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
927 asprintf(&cmd2, "%s%s", smsc, pdu);
929 err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
931 if (err != 0 || p_response->success == 0) goto error;
933 memset(&response, 0, sizeof(response));
935 /* FIXME fill in messageRef and ackPDU */
937 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
938 at_response_free(p_response);
942 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
943 at_response_free(p_response);
946 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
951 ATResponse *p_response = NULL;
952 char *response[2] = { "1", PPP_TTY_PATH };
954 apn = ((const char **)data)[2];
956 #ifdef USE_TI_COMMANDS
957 // Config for multislot class 10 (probably default anyway eh?)
958 err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
961 err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
962 #endif /* USE_TI_COMMANDS */
967 ssize_t written, rlen;
968 char status[32] = {0};
971 LOGD("requesting data connection to APN '%s'", apn);
973 fd = open ("/dev/qmi", O_RDWR);
974 if (fd >= 0) { /* the device doesn't exist on the emulator */
976 LOGD("opened the qmi device\n");
977 asprintf(&cmd, "up:%s", apn);
982 written = write (fd, cmd + cur, len - cur);
983 } while (written < 0 && errno == EINTR);
986 LOGE("### ERROR writing to /dev/qmi");
994 // wait for interface to come online
999 rlen = read(fd, status, 31);
1000 } while (rlen < 0 && errno == EINTR);
1003 LOGE("### ERROR reading from /dev/qmi");
1007 status[rlen] = '\0';
1008 LOGD("### status: %s", status);
1010 } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
1015 LOGE("### Failed to get data connection up\n");
1019 qmistatus = system("netcfg rmnet0 dhcp");
1021 LOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus);
1023 if (qmistatus < 0) goto error;
1027 asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
1028 //FIXME check for error here
1029 err = at_send_command(cmd, NULL);
1032 // Set required QoS params to default
1033 err = at_send_command("AT+CGQREQ=1", NULL);
1035 // Set minimum QoS params to default
1036 err = at_send_command("AT+CGQMIN=1", NULL);
1038 // packet-domain event reporting
1039 err = at_send_command("AT+CGEREP=1,0", NULL);
1041 // Hangup anything that's happening there now
1042 err = at_send_command("AT+CGACT=1,0", NULL);
1044 // Start data on PDP context 1
1045 err = at_send_command("ATD*99***1#", &p_response);
1047 if (err < 0 || p_response->success == 0) {
1052 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1053 at_response_free(p_response);
1057 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1058 at_response_free(p_response);
1062 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
1067 ackSuccess = ((int *)data)[0];
1069 if (ackSuccess == 1) {
1070 err = at_send_command("AT+CNMA=1", NULL);
1071 } else if (ackSuccess == 0) {
1072 err = at_send_command("AT+CNMA=2", NULL);
1074 LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
1078 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1080 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1084 static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
1086 ATResponse *p_response = NULL;
1087 RIL_SIM_IO_Response sr;
1093 memset(&sr, 0, sizeof(sr));
1095 p_args = (RIL_SIM_IO *)data;
1097 /* FIXME handle pin2 */
1099 if (p_args->data == NULL) {
1100 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
1101 p_args->command, p_args->fileid,
1102 p_args->p1, p_args->p2, p_args->p3);
1104 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
1105 p_args->command, p_args->fileid,
1106 p_args->p1, p_args->p2, p_args->p3, p_args->data);
1109 err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
1111 if (err < 0 || p_response->success == 0) {
1115 line = p_response->p_intermediates->line;
1117 err = at_tok_start(&line);
1118 if (err < 0) goto error;
1120 err = at_tok_nextint(&line, &(sr.sw1));
1121 if (err < 0) goto error;
1123 err = at_tok_nextint(&line, &(sr.sw2));
1124 if (err < 0) goto error;
1126 if (at_tok_hasmore(&line)) {
1127 err = at_tok_nextstr(&line, &(sr.simResponse));
1128 if (err < 0) goto error;
1131 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
1132 at_response_free(p_response);
1137 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1138 at_response_free(p_response);
1143 static void requestEnterSimPin(void* data, size_t datalen, RIL_Token t)
1145 ATResponse *p_response = NULL;
1148 const char** strings = (const char**)data;;
1150 if ( datalen == sizeof(char*) ) {
1151 asprintf(&cmd, "AT+CPIN=%s", strings[0]);
1152 } else if ( datalen == 2*sizeof(char*) ) {
1153 asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
1157 err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
1160 if (err < 0 || p_response->success == 0) {
1162 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
1164 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1166 at_response_free(p_response);
1170 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
1172 const char *ussdRequest;
1174 ussdRequest = (char *)(data);
1177 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1184 /*** Callback methods from the RIL library to us ***/
1187 * Call from RIL to us to make a RIL_REQUEST
1189 * Must be completed with a call to RIL_onRequestComplete()
1191 * RIL_onRequestComplete() may be called from any thread, before or after
1192 * this function returns.
1194 * Will always be called from the same thread, so returning here implies
1195 * that the radio is ready to process another command (whether or not
1196 * the previous command has completed).
1199 onRequest (int request, void *data, size_t datalen, RIL_Token t)
1201 ATResponse *p_response;
1204 LOGD("onRequest: %s", requestToString(request));
1206 /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
1207 * when RADIO_STATE_UNAVAILABLE.
1209 if (sState == RADIO_STATE_UNAVAILABLE
1210 && request != RIL_REQUEST_GET_SIM_STATUS
1212 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1216 /* Ignore all non-power requests when RADIO_STATE_OFF
1217 * (except RIL_REQUEST_GET_SIM_STATUS)
1219 if (sState == RADIO_STATE_OFF
1220 && !(request == RIL_REQUEST_RADIO_POWER
1221 || request == RIL_REQUEST_GET_SIM_STATUS)
1223 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1228 case RIL_REQUEST_GET_SIM_STATUS: {
1229 RIL_CardStatus *p_card_status;
1233 int result = getCardStatus(&p_card_status);
1234 if (result == RIL_E_SUCCESS) {
1235 p_buffer = (char *)p_card_status;
1236 buffer_size = sizeof(*p_card_status);
1241 RIL_onRequestComplete(t, result, p_buffer, buffer_size);
1242 freeCardStatus(p_card_status);
1245 case RIL_REQUEST_GET_CURRENT_CALLS:
1246 requestGetCurrentCalls(data, datalen, t);
1248 case RIL_REQUEST_DIAL:
1249 requestDial(data, datalen, t);
1251 case RIL_REQUEST_HANGUP:
1252 requestHangup(data, datalen, t);
1254 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
1255 // 3GPP 22.030 6.5.5
1256 // "Releases all held calls or sets User Determined User Busy
1257 // (UDUB) for a waiting call."
1258 at_send_command("AT+CHLD=0", NULL);
1260 /* success or failure is ignored by the upper layer here.
1261 it will call GET_CURRENT_CALLS and determine success that way */
1262 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1264 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
1265 // 3GPP 22.030 6.5.5
1266 // "Releases all active calls (if any exist) and accepts
1267 // the other (held or waiting) call."
1268 at_send_command("AT+CHLD=1", NULL);
1270 /* success or failure is ignored by the upper layer here.
1271 it will call GET_CURRENT_CALLS and determine success that way */
1272 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1274 case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
1275 // 3GPP 22.030 6.5.5
1276 // "Places all active calls (if any exist) on hold and accepts
1277 // the other (held or waiting) call."
1278 at_send_command("AT+CHLD=2", NULL);
1280 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1282 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
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);
1288 case RIL_REQUEST_ANSWER:
1289 at_send_command("ATA", NULL);
1291 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1293 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
1295 /* success or failure is ignored by the upper layer here.
1296 it will call GET_CURRENT_CALLS and determine success that way */
1297 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1299 case RIL_REQUEST_CONFERENCE:
1300 // 3GPP 22.030 6.5.5
1301 // "Adds a held call to the conversation"
1302 at_send_command("AT+CHLD=3", NULL);
1304 /* success or failure is ignored by the upper layer here.
1305 it will call GET_CURRENT_CALLS and determine success that way */
1306 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1308 case RIL_REQUEST_UDUB:
1309 /* user determined user busy */
1310 /* sometimes used: ATH */
1311 at_send_command("ATH", NULL);
1313 /* success or failure is ignored by the upper layer here.
1314 it will call GET_CURRENT_CALLS and determine success that way */
1315 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1318 case RIL_REQUEST_SEPARATE_CONNECTION:
1321 int party = ((int*)data)[0];
1323 // Make sure that party is in a valid range.
1324 // (Note: The Telephony middle layer imposes a range of 1 to 7.
1325 // It's sufficient for us to just make sure it's single digit.)
1326 if (party > 0 && party < 10) {
1327 sprintf(cmd, "AT+CHLD=2%d", party);
1328 at_send_command(cmd, NULL);
1329 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1331 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1336 case RIL_REQUEST_SIGNAL_STRENGTH:
1337 requestSignalStrength(data, datalen, t);
1339 case RIL_REQUEST_REGISTRATION_STATE:
1340 case RIL_REQUEST_GPRS_REGISTRATION_STATE:
1341 requestRegistrationState(request, data, datalen, t);
1343 case RIL_REQUEST_OPERATOR:
1344 requestOperator(data, datalen, t);
1346 case RIL_REQUEST_RADIO_POWER:
1347 requestRadioPower(data, datalen, t);
1349 case RIL_REQUEST_DTMF: {
1350 char c = ((char *)data)[0];
1352 asprintf(&cmd, "AT+VTS=%c", (int)c);
1353 at_send_command(cmd, NULL);
1355 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1358 case RIL_REQUEST_SEND_SMS:
1359 requestSendSMS(data, datalen, t);
1361 case RIL_REQUEST_SETUP_DATA_CALL:
1362 requestSetupDataCall(data, datalen, t);
1364 case RIL_REQUEST_SMS_ACKNOWLEDGE:
1365 requestSMSAcknowledge(data, datalen, t);
1368 case RIL_REQUEST_GET_IMSI:
1370 err = at_send_command_numeric("AT+CIMI", &p_response);
1372 if (err < 0 || p_response->success == 0) {
1373 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1375 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1376 p_response->p_intermediates->line, sizeof(char *));
1378 at_response_free(p_response);
1381 case RIL_REQUEST_GET_IMEI:
1383 err = at_send_command_numeric("AT+CGSN", &p_response);
1385 if (err < 0 || p_response->success == 0) {
1386 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1388 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1389 p_response->p_intermediates->line, sizeof(char *));
1391 at_response_free(p_response);
1394 case RIL_REQUEST_SIM_IO:
1395 requestSIM_IO(data,datalen,t);
1398 case RIL_REQUEST_SEND_USSD:
1399 requestSendUSSD(data, datalen, t);
1402 case RIL_REQUEST_CANCEL_USSD:
1404 err = at_send_command_numeric("AT+CUSD=2", &p_response);
1406 if (err < 0 || p_response->success == 0) {
1407 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1409 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1410 p_response->p_intermediates->line, sizeof(char *));
1412 at_response_free(p_response);
1415 case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
1416 at_send_command("AT+COPS=0", NULL);
1419 case RIL_REQUEST_DATA_CALL_LIST:
1420 requestDataCallList(data, datalen, t);
1423 case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
1424 requestQueryNetworkSelectionMode(data, datalen, t);
1427 case RIL_REQUEST_OEM_HOOK_RAW:
1429 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1433 case RIL_REQUEST_OEM_HOOK_STRINGS: {
1437 LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
1440 for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
1441 i > 0 ; cur++, i --) {
1442 LOGD("> '%s'", *cur);
1445 // echo back strings
1446 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1450 case RIL_REQUEST_WRITE_SMS_TO_SIM:
1451 requestWriteSmsToSim(data, datalen, t);
1454 case RIL_REQUEST_DELETE_SMS_ON_SIM: {
1457 asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
1458 err = at_send_command(cmd, &p_response);
1460 if (err < 0 || p_response->success == 0) {
1461 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1463 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1465 at_response_free(p_response);
1469 case RIL_REQUEST_ENTER_SIM_PIN:
1470 case RIL_REQUEST_ENTER_SIM_PUK:
1471 case RIL_REQUEST_ENTER_SIM_PIN2:
1472 case RIL_REQUEST_ENTER_SIM_PUK2:
1473 case RIL_REQUEST_CHANGE_SIM_PIN:
1474 case RIL_REQUEST_CHANGE_SIM_PIN2:
1475 requestEnterSimPin(data, datalen, t);
1479 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1485 * Synchronous call from the RIL to us to return current radio state.
1486 * RADIO_STATE_UNAVAILABLE should be the initial state.
1488 static RIL_RadioState
1494 * Call from RIL to us to find out whether a specific request code
1495 * is supported by this implementation.
1497 * Return 1 for "supported" and 0 for "unsupported"
1501 onSupports (int requestCode)
1508 static void onCancel (RIL_Token t)
1514 static const char * getVersion(void)
1516 return "android reference-ril 1.0";
1520 setRadioState(RIL_RadioState newState)
1522 RIL_RadioState oldState;
1524 pthread_mutex_lock(&s_state_mutex);
1529 // If we're closed, the only reasonable state is
1530 // RADIO_STATE_UNAVAILABLE
1531 // This is here because things on the main thread
1532 // may attempt to change the radio state after the closed
1533 // event happened in another thread
1534 newState = RADIO_STATE_UNAVAILABLE;
1537 if (sState != newState || s_closed > 0) {
1540 pthread_cond_broadcast (&s_state_cond);
1543 pthread_mutex_unlock(&s_state_mutex);
1546 /* do these outside of the mutex */
1547 if (sState != oldState) {
1548 RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
1551 /* FIXME onSimReady() and onRadioPowerOn() cannot be called
1552 * from the AT reader thread
1553 * Currently, this doesn't happen, but if that changes then these
1554 * will need to be dispatched on the request thread
1556 if (sState == RADIO_STATE_SIM_READY) {
1558 } else if (sState == RADIO_STATE_SIM_NOT_READY) {
1564 /** returns one of RIM_SIM_*. Returns RIL_SIM_NOT_READY on error */
1568 ATResponse *p_response = NULL;
1574 if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
1575 ret = RIL_SIM_NOT_READY;
1579 err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
1582 ret = RIL_SIM_NOT_READY;
1586 switch (at_get_cme_error(p_response)) {
1590 case CME_SIM_NOT_INSERTED:
1591 ret = RIL_SIM_ABSENT;
1595 ret = RIL_SIM_NOT_READY;
1599 /* CPIN? has succeeded, now look at the result */
1601 cpinLine = p_response->p_intermediates->line;
1602 err = at_tok_start (&cpinLine);
1605 ret = RIL_SIM_NOT_READY;
1609 err = at_tok_nextstr(&cpinLine, &cpinResult);
1612 ret = RIL_SIM_NOT_READY;
1616 if (0 == strcmp (cpinResult, "SIM PIN")) {
1619 } else if (0 == strcmp (cpinResult, "SIM PUK")) {
1622 } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
1623 return RIL_SIM_NETWORK_PERSONALIZATION;
1624 } else if (0 != strcmp (cpinResult, "READY")) {
1625 /* we're treating unsupported lock types as "sim absent" */
1626 ret = RIL_SIM_ABSENT;
1630 at_response_free(p_response);
1634 ret = RIL_SIM_READY;
1637 at_response_free(p_response);
1643 * Get the current card status.
1645 * This must be freed using freeCardStatus.
1646 * @return: On success returns RIL_E_SUCCESS
1648 static int getCardStatus(RIL_CardStatus **pp_card_status) {
1649 static RIL_AppStatus app_status_array[] = {
1650 // RIL_SIM_ABSENT = 0
1651 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
1652 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
1653 // RIL_SIM_NOT_READY = 1
1654 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
1655 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
1656 // RIL_SIM_READY = 2
1657 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
1658 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
1660 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
1661 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
1663 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
1664 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
1665 // RIL_SIM_NETWORK_PERSONALIZATION = 5
1666 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
1667 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }
1669 RIL_CardState card_state;
1672 int sim_status = getSIMStatus();
1673 if (sim_status == RIL_SIM_ABSENT) {
1674 card_state = RIL_CARDSTATE_ABSENT;
1677 card_state = RIL_CARDSTATE_PRESENT;
1681 // Allocate and initialize base card status.
1682 RIL_CardStatus *p_card_status = malloc(sizeof(RIL_CardStatus));
1683 p_card_status->card_state = card_state;
1684 p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
1685 p_card_status->gsm_umts_subscription_app_index = RIL_CARD_MAX_APPS;
1686 p_card_status->cdma_subscription_app_index = RIL_CARD_MAX_APPS;
1687 p_card_status->num_applications = num_apps;
1689 // Initialize application status
1691 for (i = 0; i < RIL_CARD_MAX_APPS; i++) {
1692 p_card_status->applications[i] = app_status_array[RIL_SIM_ABSENT];
1695 // Pickup the appropriate application status
1696 // that reflects sim_status for gsm.
1697 if (num_apps != 0) {
1698 // Only support one app, gsm
1699 p_card_status->num_applications = 1;
1700 p_card_status->gsm_umts_subscription_app_index = 0;
1702 // Get the correct app status
1703 p_card_status->applications[0] = app_status_array[sim_status];
1706 *pp_card_status = p_card_status;
1707 return RIL_E_SUCCESS;
1711 * Free the card status returned by getCardStatus
1713 static void freeCardStatus(RIL_CardStatus *p_card_status) {
1714 free(p_card_status);
1718 * SIM ready means any commands that access the SIM will work, including:
1719 * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
1720 * (all SMS-related commands)
1723 static void pollSIMState (void *param)
1725 ATResponse *p_response;
1728 if (sState != RADIO_STATE_SIM_NOT_READY) {
1729 // no longer valid to poll
1733 switch(getSIMStatus()) {
1734 case RIL_SIM_ABSENT:
1737 case RIL_SIM_NETWORK_PERSONALIZATION:
1739 setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
1742 case RIL_SIM_NOT_READY:
1743 RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
1747 setRadioState(RADIO_STATE_SIM_READY);
1752 /** returns 1 if on, 0 if off, and -1 on error */
1753 static int isRadioOn()
1755 ATResponse *p_response = NULL;
1760 err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
1762 if (err < 0 || p_response->success == 0) {
1763 // assume radio is off
1767 line = p_response->p_intermediates->line;
1769 err = at_tok_start(&line);
1770 if (err < 0) goto error;
1772 err = at_tok_nextbool(&line, &ret);
1773 if (err < 0) goto error;
1775 at_response_free(p_response);
1781 at_response_free(p_response);
1786 * Initialize everything that can be configured while we're still in
1789 static void initializeCallback(void *param)
1791 ATResponse *p_response = NULL;
1794 setRadioState (RADIO_STATE_OFF);
1798 /* note: we don't check errors here. Everything important will
1799 be handled in onATTimeout and onATReaderClosed */
1801 /* atchannel is tolerant of echo but it must */
1802 /* have verbose result codes */
1803 at_send_command("ATE0Q0V1", NULL);
1805 /* No auto-answer */
1806 at_send_command("ATS0=0", NULL);
1808 /* Extended errors */
1809 at_send_command("AT+CMEE=1", NULL);
1811 /* Network registration events */
1812 err = at_send_command("AT+CREG=2", &p_response);
1814 /* some handsets -- in tethered mode -- don't support CREG=2 */
1815 if (err < 0 || p_response->success == 0) {
1816 at_send_command("AT+CREG=1", NULL);
1819 at_response_free(p_response);
1821 /* GPRS registration events */
1822 at_send_command("AT+CGREG=1", NULL);
1824 /* Call Waiting notifications */
1825 at_send_command("AT+CCWA=1", NULL);
1827 /* Alternating voice/data off */
1828 at_send_command("AT+CMOD=0", NULL);
1831 at_send_command("AT+CMUT=0", NULL);
1833 /* +CSSU unsolicited supp service notifications */
1834 at_send_command("AT+CSSN=0,1", NULL);
1836 /* no connected line identification */
1837 at_send_command("AT+COLP=0", NULL);
1839 /* HEX character set */
1840 at_send_command("AT+CSCS=\"HEX\"", NULL);
1842 /* USSD unsolicited */
1843 at_send_command("AT+CUSD=1", NULL);
1845 /* Enable +CGEV GPRS event notifications, but don't buffer */
1846 at_send_command("AT+CGEREP=1,0", NULL);
1849 at_send_command("AT+CMGF=0", NULL);
1851 #ifdef USE_TI_COMMANDS
1853 at_send_command("AT%CPI=3", NULL);
1855 /* TI specific -- notifications when SMS is ready (currently ignored) */
1856 at_send_command("AT%CSTAT=1", NULL);
1858 #endif /* USE_TI_COMMANDS */
1861 /* assume radio is off on error */
1862 if (isRadioOn() > 0) {
1863 setRadioState (RADIO_STATE_SIM_NOT_READY);
1867 static void waitForClose()
1869 pthread_mutex_lock(&s_state_mutex);
1871 while (s_closed == 0) {
1872 pthread_cond_wait(&s_state_cond, &s_state_mutex);
1875 pthread_mutex_unlock(&s_state_mutex);
1879 * Called by atchannel when an unsolicited line appears
1880 * This is called on atchannel's reader thread. AT commands may
1881 * not be issued here
1883 static void onUnsolicited (const char *s, const char *sms_pdu)
1888 /* Ignore unsolicited responses until we're initialized.
1889 * This is OK because the RIL library will poll for initial state
1891 if (sState == RADIO_STATE_UNAVAILABLE) {
1895 if (strStartsWith(s, "%CTZV:")) {
1896 /* TI specific -- NITZ time */
1900 at_tok_start(&line);
1902 err = at_tok_nextstr(&line, &response);
1905 LOGE("invalid NITZ line %s\n", s);
1907 RIL_onUnsolicitedResponse (
1908 RIL_UNSOL_NITZ_TIME_RECEIVED,
1909 response, strlen(response));
1911 } else if (strStartsWith(s,"+CRING:")
1912 || strStartsWith(s,"RING")
1913 || strStartsWith(s,"NO CARRIER")
1914 || strStartsWith(s,"+CCWA")
1916 RIL_onUnsolicitedResponse (
1917 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
1919 #ifdef WORKAROUND_FAKE_CGEV
1920 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
1921 #endif /* WORKAROUND_FAKE_CGEV */
1922 } else if (strStartsWith(s,"+CREG:")
1923 || strStartsWith(s,"+CGREG:")
1925 RIL_onUnsolicitedResponse (
1926 RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
1928 #ifdef WORKAROUND_FAKE_CGEV
1929 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1930 #endif /* WORKAROUND_FAKE_CGEV */
1931 } else if (strStartsWith(s, "+CMT:")) {
1932 RIL_onUnsolicitedResponse (
1933 RIL_UNSOL_RESPONSE_NEW_SMS,
1934 sms_pdu, strlen(sms_pdu));
1935 } else if (strStartsWith(s, "+CDS:")) {
1936 RIL_onUnsolicitedResponse (
1937 RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
1938 sms_pdu, strlen(sms_pdu));
1939 } else if (strStartsWith(s, "+CGEV:")) {
1940 /* Really, we can ignore NW CLASS and ME CLASS events here,
1941 * but right now we don't since extranous
1942 * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
1944 /* can't issue AT commands here -- call on main thread */
1945 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1946 #ifdef WORKAROUND_FAKE_CGEV
1947 } else if (strStartsWith(s, "+CME ERROR: 150")) {
1948 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
1949 #endif /* WORKAROUND_FAKE_CGEV */
1953 /* Called on command or reader thread */
1954 static void onATReaderClosed()
1956 LOGI("AT channel closed\n");
1960 setRadioState (RADIO_STATE_UNAVAILABLE);
1963 /* Called on command thread */
1964 static void onATTimeout()
1966 LOGI("AT channel timeout; closing\n");
1971 /* FIXME cause a radio reset here */
1973 setRadioState (RADIO_STATE_UNAVAILABLE);
1976 static void usage(char *s)
1979 fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
1981 fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
1987 mainLoop(void *param)
1992 AT_DUMP("== ", "entering mainLoop()", -1 );
1993 at_set_on_reader_closed(onATReaderClosed);
1994 at_set_on_timeout(onATTimeout);
2000 fd = socket_loopback_client(s_port, SOCK_STREAM);
2001 } else if (s_device_socket) {
2002 if (!strcmp(s_device_path, "/dev/socket/qemud")) {
2003 /* Qemu-specific control socket */
2004 fd = socket_local_client( "qemud",
2005 ANDROID_SOCKET_NAMESPACE_RESERVED,
2010 if ( write(fd, "gsm", 3) != 3 ||
2011 read(fd, answer, 2) != 2 ||
2012 memcmp(answer, "OK", 2) != 0)
2020 fd = socket_local_client( s_device_path,
2021 ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
2023 } else if (s_device_path != NULL) {
2024 fd = open (s_device_path, O_RDWR);
2025 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
2026 /* disable echo on serial ports */
2028 tcgetattr( fd, &ios );
2029 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
2030 tcsetattr( fd, TCSANOW, &ios );
2035 perror ("opening AT interface. retrying...");
2042 ret = at_open(fd, onUnsolicited);
2045 LOGE ("AT error %d on at_open\n", ret);
2049 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
2051 // Give initializeCallback a chance to dispatched, since
2052 // we don't presently have a cancellation mechanism
2056 LOGI("Re-opening after close");
2062 pthread_t s_tid_mainloop;
2064 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
2069 pthread_attr_t attr;
2073 while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
2076 s_port = atoi(optarg);
2081 LOGI("Opening loopback port %d\n", s_port);
2085 s_device_path = optarg;
2086 LOGI("Opening tty device %s\n", s_device_path);
2090 s_device_path = optarg;
2091 s_device_socket = 1;
2092 LOGI("Opening socket %s\n", s_device_path);
2101 if (s_port < 0 && s_device_path == NULL) {
2106 pthread_attr_init (&attr);
2107 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2108 ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
2110 return &s_callbacks;
2112 #else /* RIL_SHLIB */
2113 int main (int argc, char **argv)
2119 while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
2122 s_port = atoi(optarg);
2126 LOGI("Opening loopback port %d\n", s_port);
2130 s_device_path = optarg;
2131 LOGI("Opening tty device %s\n", s_device_path);
2135 s_device_path = optarg;
2136 s_device_socket = 1;
2137 LOGI("Opening socket %s\n", s_device_path);
2145 if (s_port < 0 && s_device_path == NULL) {
2149 RIL_register(&s_callbacks);
2156 #endif /* RIL_SHLIB */