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.
23 #include <sys/types.h>
28 #include "atchannel.h"
32 #include <sys/socket.h>
33 #include <cutils/sockets.h>
35 #include <sys/system_properties.h>
38 #include "hardware/qemu_pipe.h"
41 #include <utils/Log.h>
43 #define MAX_AT_RESPONSE 0x1000
45 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
46 #define PPP_TTY_PATH "eth0"
48 #ifdef USE_TI_COMMANDS
50 // Enable a workaround
51 // 1) Make incoming call, do not answer
52 // 2) Hangup remote end
53 // Expected: call should disappear from CLCC line
54 // Actual: Call shows as "ACTIVE" before disappearing
55 #define WORKAROUND_ERRONEOUS_ANSWER 1
57 // Some varients of the TI stack do not support the +CGEV unsolicited
58 // response. However, they seem to send an unsolicited +CME ERROR: 150
59 #define WORKAROUND_FAKE_CGEV 1
65 SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
68 SIM_NETWORK_PERSONALIZATION = 5
71 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
72 static RIL_RadioState currentState();
73 static int onSupports (int requestCode);
74 static void onCancel (RIL_Token t);
75 static const char *getVersion();
76 static int isRadioOn();
77 static SIM_Status getSIMStatus();
78 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status);
79 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status);
80 static void onDataCallListChanged(void *param);
82 extern const char * requestToString(int request);
84 /*** Static Variables ***/
85 static const RIL_RadioFunctions s_callbacks = {
95 static const struct RIL_Env *s_rilenv;
97 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
98 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
99 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
102 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
104 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
105 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
107 static int s_port = -1;
108 static const char * s_device_path = NULL;
109 static int s_device_socket = 0;
111 /* trigger change to this with s_state_cond */
112 static int s_closed = 0;
114 static int sFD; /* file desc of AT channel */
115 static char sATBuffer[MAX_AT_RESPONSE+1];
116 static char *sATBufferCur = NULL;
118 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
119 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
120 static const struct timeval TIMEVAL_0 = {0,0};
122 #ifdef WORKAROUND_ERRONEOUS_ANSWER
123 // Max number of times we'll try to repoll when we think
124 // we have a AT+CLCC race condition
125 #define REPOLL_CALLS_COUNT_MAX 4
127 // Line index that was incoming or waiting at last poll, or -1 for none
128 static int s_incomingOrWaitingLine = -1;
129 // Number of times we've asked for a repoll of AT+CLCC
130 static int s_repollCallsCount = 0;
131 // Should we expect a call to be answered in the next CLCC?
132 static int s_expectAnswer = 0;
133 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
135 static void pollSIMState (void *param);
136 static void setRadioState(RIL_RadioState newState);
138 static int clccStateToRILState(int state, RIL_CallState *p_state)
142 case 0: *p_state = RIL_CALL_ACTIVE; return 0;
143 case 1: *p_state = RIL_CALL_HOLDING; return 0;
144 case 2: *p_state = RIL_CALL_DIALING; return 0;
145 case 3: *p_state = RIL_CALL_ALERTING; return 0;
146 case 4: *p_state = RIL_CALL_INCOMING; return 0;
147 case 5: *p_state = RIL_CALL_WAITING; return 0;
153 * Note: directly modified line and has *p_call point directly into
156 static int callFromCLCCLine(char *line, RIL_Call *p_call)
158 //+CLCC: 1,0,2,0,0,\"+18005551212\",145
159 // index,isMT,state,mode,isMpty(,number,TOA)?
165 err = at_tok_start(&line);
166 if (err < 0) goto error;
168 err = at_tok_nextint(&line, &(p_call->index));
169 if (err < 0) goto error;
171 err = at_tok_nextbool(&line, &(p_call->isMT));
172 if (err < 0) goto error;
174 err = at_tok_nextint(&line, &state);
175 if (err < 0) goto error;
177 err = clccStateToRILState(state, &(p_call->state));
178 if (err < 0) goto error;
180 err = at_tok_nextint(&line, &mode);
181 if (err < 0) goto error;
183 p_call->isVoice = (mode == 0);
185 err = at_tok_nextbool(&line, &(p_call->isMpty));
186 if (err < 0) goto error;
188 if (at_tok_hasmore(&line)) {
189 err = at_tok_nextstr(&line, &(p_call->number));
191 /* tolerate null here */
192 if (err < 0) return 0;
194 // Some lame implementations return strings
195 // like "NOT AVAILABLE" in the CLCC line
196 if (p_call->number != NULL
197 && 0 == strspn(p_call->number, "+0123456789")
199 p_call->number = NULL;
202 err = at_tok_nextint(&line, &p_call->toa);
203 if (err < 0) goto error;
206 p_call->uusInfo = NULL;
211 LOGE("invalid CLCC line\n");
216 /** do post-AT+CFUN=1 initialization */
217 static void onRadioPowerOn()
219 #ifdef USE_TI_COMMANDS
220 /* Must be after CFUN=1 */
221 /* TI specific -- notifications for CPHS things such */
222 /* as CPHS message waiting indicator */
224 at_send_command("AT%CPHS=1", NULL);
226 /* TI specific -- enable NITZ unsol notifs */
227 at_send_command("AT%CTZV=1", NULL);
233 /** do post- SIM ready initialization */
234 static void onSIMReady()
236 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
238 * Always send SMS messages directly to the TE
240 * mode = 1 // discard when link is reserved (link should never be
242 * mt = 2 // most messages routed to TE
243 * bm = 2 // new cell BM's routed to TE
244 * ds = 1 // Status reports routed to TE
245 * bfr = 1 // flush buffer
247 at_send_command("AT+CNMI=1,2,2,1,1", NULL);
250 static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
255 ATResponse *p_response = NULL;
257 assert (datalen >= sizeof(int *));
258 onOff = ((int *)data)[0];
260 if (onOff == 0 && sState != RADIO_STATE_OFF) {
261 err = at_send_command("AT+CFUN=0", &p_response);
262 if (err < 0 || p_response->success == 0) goto error;
263 setRadioState(RADIO_STATE_OFF);
264 } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
265 err = at_send_command("AT+CFUN=1", &p_response);
266 if (err < 0|| p_response->success == 0) {
267 // Some stacks return an error when there is no SIM,
268 // but they really turn the RF portion on
269 // So, if we get an error, let's check to see if it
272 if (isRadioOn() != 1) {
276 setRadioState(RADIO_STATE_SIM_NOT_READY);
279 at_response_free(p_response);
280 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
283 at_response_free(p_response);
284 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
287 static void requestOrSendDataCallList(RIL_Token *t);
289 static void onDataCallListChanged(void *param)
291 requestOrSendDataCallList(NULL);
294 static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
296 requestOrSendDataCallList(&t);
299 static void requestOrSendDataCallList(RIL_Token *t)
301 ATResponse *p_response;
307 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
308 if (err != 0 || p_response->success == 0) {
310 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
312 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
317 for (p_cur = p_response->p_intermediates; p_cur != NULL;
318 p_cur = p_cur->p_next)
321 RIL_Data_Call_Response_v6 *responses =
322 alloca(n * sizeof(RIL_Data_Call_Response_v6));
325 for (i = 0; i < n; i++) {
326 responses[i].status = -1;
327 responses[i].suggestedRetryTime = -1;
328 responses[i].cid = -1;
329 responses[i].active = -1;
330 responses[i].type = "";
331 responses[i].ifname = "";
332 responses[i].addresses = "";
333 responses[i].dnses = "";
334 responses[i].gateways = "";
337 RIL_Data_Call_Response_v6 *response = responses;
338 for (p_cur = p_response->p_intermediates; p_cur != NULL;
339 p_cur = p_cur->p_next) {
340 char *line = p_cur->line;
342 err = at_tok_start(&line);
346 err = at_tok_nextint(&line, &response->cid);
350 err = at_tok_nextint(&line, &response->active);
357 at_response_free(p_response);
359 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
360 if (err != 0 || p_response->success == 0) {
362 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
364 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
369 for (p_cur = p_response->p_intermediates; p_cur != NULL;
370 p_cur = p_cur->p_next) {
371 char *line = p_cur->line;
374 err = at_tok_start(&line);
378 err = at_tok_nextint(&line, &cid);
382 for (i = 0; i < n; i++) {
383 if (responses[i].cid == cid)
388 /* details for a context we didn't hear about in the last request */
393 responses[i].status = 0;
396 err = at_tok_nextstr(&line, &out);
399 responses[i].type = alloca(strlen(out) + 1);
400 strcpy(responses[i].type, out);
402 // APN ignored for v5
403 err = at_tok_nextstr(&line, &out);
407 responses[i].ifname = alloca(strlen(PPP_TTY_PATH) + 1);
408 strcpy(responses[i].ifname, PPP_TTY_PATH);
410 err = at_tok_nextstr(&line, &out);
414 responses[i].addresses = alloca(strlen(out) + 1);
415 strcpy(responses[i].addresses, out);
418 char propValue[PROP_VALUE_MAX];
420 if (__system_property_get("ro.kernel.qemu", propValue) != 0) {
421 /* We are in the emulator - the dns servers are listed
422 * by the following system properties, setup in
423 * /system/etc/init.goldfish.sh:
429 const int dnslist_sz = 128;
430 char* dnslist = alloca(dnslist_sz);
431 const char* separator = "";
435 for (nn = 1; nn <= 4; nn++) {
436 /* Probe net.eth0.dns<n> */
437 char propName[PROP_NAME_MAX];
438 snprintf(propName, sizeof propName, "net.eth0.dns%d", nn);
440 /* Ignore if undefined */
441 if (__system_property_get(propName, propValue) == 0) {
445 /* Append the DNS IP address */
446 strlcat(dnslist, separator, dnslist_sz);
447 strlcat(dnslist, propValue, dnslist_sz);
450 responses[i].dnses = dnslist;
452 /* There is only on gateway in the emulator */
453 responses[i].gateways = "10.0.2.2";
456 /* I don't know where we are, so use the public Google DNS
457 * servers by default and no gateway.
459 responses[i].dnses = "8.8.8.8 8.8.4.4";
460 responses[i].gateways = "";
465 at_response_free(p_response);
468 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
469 n * sizeof(RIL_Data_Call_Response_v6));
471 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
473 n * sizeof(RIL_Data_Call_Response_v6));
479 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
481 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
484 at_response_free(p_response);
487 static void requestQueryNetworkSelectionMode(
488 void *data, size_t datalen, RIL_Token t)
491 ATResponse *p_response = NULL;
495 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
497 if (err < 0 || p_response->success == 0) {
501 line = p_response->p_intermediates->line;
503 err = at_tok_start(&line);
509 err = at_tok_nextint(&line, &response);
515 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
516 at_response_free(p_response);
519 at_response_free(p_response);
520 LOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
521 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
524 static void sendCallStateChanged(void *param)
526 RIL_onUnsolicitedResponse (
527 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
531 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
534 ATResponse *p_response;
543 #ifdef WORKAROUND_ERRONEOUS_ANSWER
544 int prevIncomingOrWaitingLine;
546 prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
547 s_incomingOrWaitingLine = -1;
548 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
550 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
552 if (err != 0 || p_response->success == 0) {
553 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
557 /* count the calls */
558 for (countCalls = 0, p_cur = p_response->p_intermediates
560 ; p_cur = p_cur->p_next
565 /* yes, there's an array of pointers and then an array of structures */
567 pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
568 p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
569 memset (p_calls, 0, countCalls * sizeof(RIL_Call));
571 /* init the pointer array */
572 for(i = 0; i < countCalls ; i++) {
573 pp_calls[i] = &(p_calls[i]);
576 for (countValidCalls = 0, p_cur = p_response->p_intermediates
578 ; p_cur = p_cur->p_next
580 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
586 #ifdef WORKAROUND_ERRONEOUS_ANSWER
587 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
588 || p_calls[countValidCalls].state == RIL_CALL_WAITING
590 s_incomingOrWaitingLine = p_calls[countValidCalls].index;
592 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
594 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
595 && p_calls[countValidCalls].state != RIL_CALL_HOLDING
603 #ifdef WORKAROUND_ERRONEOUS_ANSWER
605 // A call was incoming or waiting
606 // Now it's marked as active
607 // But we never answered it
609 // This is probably a bug, and the call will probably
610 // disappear from the call list in the next poll
611 if (prevIncomingOrWaitingLine >= 0
612 && s_incomingOrWaitingLine < 0
613 && s_expectAnswer == 0
615 for (i = 0; i < countValidCalls ; i++) {
617 if (p_calls[i].index == prevIncomingOrWaitingLine
618 && p_calls[i].state == RIL_CALL_ACTIVE
619 && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
622 "Hit WORKAROUND_ERRONOUS_ANSWER case."
623 " Repoll count: %d\n", s_repollCallsCount);
624 s_repollCallsCount++;
631 s_repollCallsCount = 0;
632 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
634 RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
635 countValidCalls * sizeof (RIL_Call *));
637 at_response_free(p_response);
639 #ifdef POLL_CALL_STATE
640 if (countValidCalls) { // We don't seem to get a "NO CARRIER" message from
641 // smd, so we're forced to poll until the call ends.
645 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
650 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
651 at_response_free(p_response);
654 static void requestDial(void *data, size_t datalen, RIL_Token t)
661 p_dial = (RIL_Dial *)data;
663 switch (p_dial->clir) {
664 case 1: clir = "I"; break; /*invocation*/
665 case 2: clir = "i"; break; /*suppression*/
667 case 0: clir = ""; break; /*subscription default*/
670 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
672 ret = at_send_command(cmd, NULL);
676 /* success or failure is ignored by the upper layer here.
677 it will call GET_CURRENT_CALLS and determine success that way */
678 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
681 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
683 RIL_SMS_WriteArgs *p_args;
687 ATResponse *p_response = NULL;
689 p_args = (RIL_SMS_WriteArgs *)data;
691 length = strlen(p_args->pdu)/2;
692 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
694 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
696 if (err != 0 || p_response->success == 0) goto error;
698 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
699 at_response_free(p_response);
703 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
704 at_response_free(p_response);
707 static void requestHangup(void *data, size_t datalen, RIL_Token t)
714 p_line = (int *)data;
717 // "Releases a specific active call X"
718 asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
720 ret = at_send_command(cmd, NULL);
724 /* success or failure is ignored by the upper layer here.
725 it will call GET_CURRENT_CALLS and determine success that way */
726 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
729 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
731 ATResponse *p_response = NULL;
736 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
738 if (err < 0 || p_response->success == 0) {
739 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
743 line = p_response->p_intermediates->line;
745 err = at_tok_start(&line);
746 if (err < 0) goto error;
748 err = at_tok_nextint(&line, &(response[0]));
749 if (err < 0) goto error;
751 err = at_tok_nextint(&line, &(response[1]));
752 if (err < 0) goto error;
754 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
756 at_response_free(p_response);
760 LOGE("requestSignalStrength must never return an error when radio is on");
761 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
762 at_response_free(p_response);
765 static void requestRegistrationState(int request, void *data,
766 size_t datalen, RIL_Token t)
770 char * responseStr[4];
771 ATResponse *p_response = NULL;
780 if (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
783 } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
791 err = at_send_command_singleline(cmd, prefix, &p_response);
793 if (err != 0) goto error;
795 line = p_response->p_intermediates->line;
797 err = at_tok_start(&line);
798 if (err < 0) goto error;
800 /* Ok you have to be careful here
801 * The solicited version of the CREG response is
802 * +CREG: n, stat, [lac, cid]
803 * and the unsolicited version is
804 * +CREG: stat, [lac, cid]
805 * The <n> parameter is basically "is unsolicited creg on?"
806 * which it should always be
808 * Now we should normally get the solicited version here,
809 * but the unsolicited version could have snuck in
810 * so we have to handle both
812 * Also since the LAC and CID are only reported when registered,
813 * we can have 1, 2, 3, or 4 arguments here
815 * finally, a +CGREG: answer may have a fifth value that corresponds
816 * to the network type, as in;
818 * +CGREG: n, stat [,lac, cid [,networkType]]
821 /* count number of commas */
823 for (p = line ; *p != '\0' ;p++) {
824 if (*p == ',') commas++;
828 case 0: /* +CREG: <stat> */
829 err = at_tok_nextint(&line, &response[0]);
830 if (err < 0) goto error;
835 case 1: /* +CREG: <n>, <stat> */
836 err = at_tok_nextint(&line, &skip);
837 if (err < 0) goto error;
838 err = at_tok_nextint(&line, &response[0]);
839 if (err < 0) goto error;
842 if (err < 0) goto error;
845 case 2: /* +CREG: <stat>, <lac>, <cid> */
846 err = at_tok_nextint(&line, &response[0]);
847 if (err < 0) goto error;
848 err = at_tok_nexthexint(&line, &response[1]);
849 if (err < 0) goto error;
850 err = at_tok_nexthexint(&line, &response[2]);
851 if (err < 0) goto error;
853 case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
854 err = at_tok_nextint(&line, &skip);
855 if (err < 0) goto error;
856 err = at_tok_nextint(&line, &response[0]);
857 if (err < 0) goto error;
858 err = at_tok_nexthexint(&line, &response[1]);
859 if (err < 0) goto error;
860 err = at_tok_nexthexint(&line, &response[2]);
861 if (err < 0) goto error;
863 /* special case for CGREG, there is a fourth parameter
864 * that is the network type (unknown/gprs/edge/umts)
866 case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
867 err = at_tok_nextint(&line, &skip);
868 if (err < 0) goto error;
869 err = at_tok_nextint(&line, &response[0]);
870 if (err < 0) goto error;
871 err = at_tok_nexthexint(&line, &response[1]);
872 if (err < 0) goto error;
873 err = at_tok_nexthexint(&line, &response[2]);
874 if (err < 0) goto error;
875 err = at_tok_nexthexint(&line, &response[3]);
876 if (err < 0) goto error;
883 asprintf(&responseStr[0], "%d", response[0]);
884 asprintf(&responseStr[1], "%x", response[1]);
885 asprintf(&responseStr[2], "%x", response[2]);
888 asprintf(&responseStr[3], "%d", response[3]);
890 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
891 at_response_free(p_response);
895 LOGE("requestRegistrationState must never return an error when radio is on");
896 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
897 at_response_free(p_response);
900 static void requestOperator(void *data, size_t datalen, RIL_Token t)
908 memset(response, 0, sizeof(response));
910 ATResponse *p_response = NULL;
912 err = at_send_command_multiline(
913 "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
914 "+COPS:", &p_response);
916 /* we expect 3 lines here:
917 * +COPS: 0,0,"T - Mobile"
919 * +COPS: 0,2,"310170"
922 if (err != 0) goto error;
924 for (i = 0, p_cur = p_response->p_intermediates
926 ; p_cur = p_cur->p_next, i++
928 char *line = p_cur->line;
930 err = at_tok_start(&line);
931 if (err < 0) goto error;
933 err = at_tok_nextint(&line, &skip);
934 if (err < 0) goto error;
936 // If we're unregistered, we may just get
937 // a "+COPS: 0" response
938 if (!at_tok_hasmore(&line)) {
943 err = at_tok_nextint(&line, &skip);
944 if (err < 0) goto error;
946 // a "+COPS: 0, n" response is also possible
947 if (!at_tok_hasmore(&line)) {
952 err = at_tok_nextstr(&line, &(response[i]));
953 if (err < 0) goto error;
957 /* expect 3 lines exactly */
961 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
962 at_response_free(p_response);
966 LOGE("requestOperator must not return error when radio is on");
967 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
968 at_response_free(p_response);
971 static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
978 RIL_SMS_Response response;
979 ATResponse *p_response = NULL;
981 smsc = ((const char **)data)[0];
982 pdu = ((const char **)data)[1];
984 tpLayerLength = strlen(pdu)/2;
986 // "NULL for default SMSC"
991 asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
992 asprintf(&cmd2, "%s%s", smsc, pdu);
994 err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
996 if (err != 0 || p_response->success == 0) goto error;
998 memset(&response, 0, sizeof(response));
1000 /* FIXME fill in messageRef and ackPDU */
1002 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
1003 at_response_free(p_response);
1007 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1008 at_response_free(p_response);
1011 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
1016 ATResponse *p_response = NULL;
1018 apn = ((const char **)data)[2];
1020 #ifdef USE_TI_COMMANDS
1021 // Config for multislot class 10 (probably default anyway eh?)
1022 err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
1025 err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
1026 #endif /* USE_TI_COMMANDS */
1031 ssize_t written, rlen;
1032 char status[32] = {0};
1034 const char *pdp_type;
1036 ALOGD("requesting data connection to APN '%s'", apn);
1038 fd = open ("/dev/qmi", O_RDWR);
1039 if (fd >= 0) { /* the device doesn't exist on the emulator */
1041 ALOGD("opened the qmi device\n");
1042 asprintf(&cmd, "up:%s", apn);
1047 written = write (fd, cmd + cur, len - cur);
1048 } while (written < 0 && errno == EINTR);
1051 LOGE("### ERROR writing to /dev/qmi");
1059 // wait for interface to come online
1064 rlen = read(fd, status, 31);
1065 } while (rlen < 0 && errno == EINTR);
1068 LOGE("### ERROR reading from /dev/qmi");
1072 status[rlen] = '\0';
1073 ALOGD("### status: %s", status);
1075 } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
1080 LOGE("### Failed to get data connection up\n");
1084 qmistatus = system("netcfg rmnet0 dhcp");
1086 ALOGD("netcfg rmnet0 dhcp: status %d\n", qmistatus);
1088 if (qmistatus < 0) goto error;
1092 if (datalen > 6 * sizeof(char *)) {
1093 pdp_type = ((const char **)data)[6];
1098 asprintf(&cmd, "AT+CGDCONT=1,\"%s\",\"%s\",,0,0", pdp_type, apn);
1099 //FIXME check for error here
1100 err = at_send_command(cmd, NULL);
1103 // Set required QoS params to default
1104 err = at_send_command("AT+CGQREQ=1", NULL);
1106 // Set minimum QoS params to default
1107 err = at_send_command("AT+CGQMIN=1", NULL);
1109 // packet-domain event reporting
1110 err = at_send_command("AT+CGEREP=1,0", NULL);
1112 // Hangup anything that's happening there now
1113 err = at_send_command("AT+CGACT=1,0", NULL);
1115 // Start data on PDP context 1
1116 err = at_send_command("ATD*99***1#", &p_response);
1118 if (err < 0 || p_response->success == 0) {
1123 requestOrSendDataCallList(&t);
1125 at_response_free(p_response);
1129 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1130 at_response_free(p_response);
1134 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
1139 ackSuccess = ((int *)data)[0];
1141 if (ackSuccess == 1) {
1142 err = at_send_command("AT+CNMA=1", NULL);
1143 } else if (ackSuccess == 0) {
1144 err = at_send_command("AT+CNMA=2", NULL);
1146 LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
1150 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1152 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1156 static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
1158 ATResponse *p_response = NULL;
1159 RIL_SIM_IO_Response sr;
1162 RIL_SIM_IO_v6 *p_args;
1165 memset(&sr, 0, sizeof(sr));
1167 p_args = (RIL_SIM_IO_v6 *)data;
1169 /* FIXME handle pin2 */
1171 if (p_args->data == NULL) {
1172 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
1173 p_args->command, p_args->fileid,
1174 p_args->p1, p_args->p2, p_args->p3);
1176 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
1177 p_args->command, p_args->fileid,
1178 p_args->p1, p_args->p2, p_args->p3, p_args->data);
1181 err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
1183 if (err < 0 || p_response->success == 0) {
1187 line = p_response->p_intermediates->line;
1189 err = at_tok_start(&line);
1190 if (err < 0) goto error;
1192 err = at_tok_nextint(&line, &(sr.sw1));
1193 if (err < 0) goto error;
1195 err = at_tok_nextint(&line, &(sr.sw2));
1196 if (err < 0) goto error;
1198 if (at_tok_hasmore(&line)) {
1199 err = at_tok_nextstr(&line, &(sr.simResponse));
1200 if (err < 0) goto error;
1203 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
1204 at_response_free(p_response);
1209 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1210 at_response_free(p_response);
1215 static void requestEnterSimPin(void* data, size_t datalen, RIL_Token t)
1217 ATResponse *p_response = NULL;
1220 const char** strings = (const char**)data;;
1222 if ( datalen == sizeof(char*) ) {
1223 asprintf(&cmd, "AT+CPIN=%s", strings[0]);
1224 } else if ( datalen == 2*sizeof(char*) ) {
1225 asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
1229 err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
1232 if (err < 0 || p_response->success == 0) {
1234 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
1236 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1238 at_response_free(p_response);
1242 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
1244 const char *ussdRequest;
1246 ussdRequest = (char *)(data);
1249 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1256 /*** Callback methods from the RIL library to us ***/
1259 * Call from RIL to us to make a RIL_REQUEST
1261 * Must be completed with a call to RIL_onRequestComplete()
1263 * RIL_onRequestComplete() may be called from any thread, before or after
1264 * this function returns.
1266 * Will always be called from the same thread, so returning here implies
1267 * that the radio is ready to process another command (whether or not
1268 * the previous command has completed).
1271 onRequest (int request, void *data, size_t datalen, RIL_Token t)
1273 ATResponse *p_response;
1276 ALOGD("onRequest: %s", requestToString(request));
1278 /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
1279 * when RADIO_STATE_UNAVAILABLE.
1281 if (sState == RADIO_STATE_UNAVAILABLE
1282 && request != RIL_REQUEST_GET_SIM_STATUS
1284 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1288 /* Ignore all non-power requests when RADIO_STATE_OFF
1289 * (except RIL_REQUEST_GET_SIM_STATUS)
1291 if (sState == RADIO_STATE_OFF
1292 && !(request == RIL_REQUEST_RADIO_POWER
1293 || request == RIL_REQUEST_GET_SIM_STATUS)
1295 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
1300 case RIL_REQUEST_GET_SIM_STATUS: {
1301 RIL_CardStatus_v6 *p_card_status;
1305 int result = getCardStatus(&p_card_status);
1306 if (result == RIL_E_SUCCESS) {
1307 p_buffer = (char *)p_card_status;
1308 buffer_size = sizeof(*p_card_status);
1313 RIL_onRequestComplete(t, result, p_buffer, buffer_size);
1314 freeCardStatus(p_card_status);
1317 case RIL_REQUEST_GET_CURRENT_CALLS:
1318 requestGetCurrentCalls(data, datalen, t);
1320 case RIL_REQUEST_DIAL:
1321 requestDial(data, datalen, t);
1323 case RIL_REQUEST_HANGUP:
1324 requestHangup(data, datalen, t);
1326 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
1327 // 3GPP 22.030 6.5.5
1328 // "Releases all held calls or sets User Determined User Busy
1329 // (UDUB) for a waiting call."
1330 at_send_command("AT+CHLD=0", NULL);
1332 /* success or failure is ignored by the upper layer here.
1333 it will call GET_CURRENT_CALLS and determine success that way */
1334 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1336 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
1337 // 3GPP 22.030 6.5.5
1338 // "Releases all active calls (if any exist) and accepts
1339 // the other (held or waiting) call."
1340 at_send_command("AT+CHLD=1", NULL);
1342 /* success or failure is ignored by the upper layer here.
1343 it will call GET_CURRENT_CALLS and determine success that way */
1344 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1346 case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
1347 // 3GPP 22.030 6.5.5
1348 // "Places all active calls (if any exist) on hold and accepts
1349 // the other (held or waiting) call."
1350 at_send_command("AT+CHLD=2", NULL);
1352 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1354 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
1356 /* success or failure is ignored by the upper layer here.
1357 it will call GET_CURRENT_CALLS and determine success that way */
1358 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1360 case RIL_REQUEST_ANSWER:
1361 at_send_command("ATA", NULL);
1363 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1365 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
1367 /* success or failure is ignored by the upper layer here.
1368 it will call GET_CURRENT_CALLS and determine success that way */
1369 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1371 case RIL_REQUEST_CONFERENCE:
1372 // 3GPP 22.030 6.5.5
1373 // "Adds a held call to the conversation"
1374 at_send_command("AT+CHLD=3", NULL);
1376 /* success or failure is ignored by the upper layer here.
1377 it will call GET_CURRENT_CALLS and determine success that way */
1378 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1380 case RIL_REQUEST_UDUB:
1381 /* user determined user busy */
1382 /* sometimes used: ATH */
1383 at_send_command("ATH", NULL);
1385 /* success or failure is ignored by the upper layer here.
1386 it will call GET_CURRENT_CALLS and determine success that way */
1387 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1390 case RIL_REQUEST_SEPARATE_CONNECTION:
1393 int party = ((int*)data)[0];
1395 // Make sure that party is in a valid range.
1396 // (Note: The Telephony middle layer imposes a range of 1 to 7.
1397 // It's sufficient for us to just make sure it's single digit.)
1398 if (party > 0 && party < 10) {
1399 sprintf(cmd, "AT+CHLD=2%d", party);
1400 at_send_command(cmd, NULL);
1401 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1403 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1408 case RIL_REQUEST_SIGNAL_STRENGTH:
1409 requestSignalStrength(data, datalen, t);
1411 case RIL_REQUEST_VOICE_REGISTRATION_STATE:
1412 case RIL_REQUEST_DATA_REGISTRATION_STATE:
1413 requestRegistrationState(request, data, datalen, t);
1415 case RIL_REQUEST_OPERATOR:
1416 requestOperator(data, datalen, t);
1418 case RIL_REQUEST_RADIO_POWER:
1419 requestRadioPower(data, datalen, t);
1421 case RIL_REQUEST_DTMF: {
1422 char c = ((char *)data)[0];
1424 asprintf(&cmd, "AT+VTS=%c", (int)c);
1425 at_send_command(cmd, NULL);
1427 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1430 case RIL_REQUEST_SEND_SMS:
1431 requestSendSMS(data, datalen, t);
1433 case RIL_REQUEST_SETUP_DATA_CALL:
1434 requestSetupDataCall(data, datalen, t);
1436 case RIL_REQUEST_SMS_ACKNOWLEDGE:
1437 requestSMSAcknowledge(data, datalen, t);
1440 case RIL_REQUEST_GET_IMSI:
1442 err = at_send_command_numeric("AT+CIMI", &p_response);
1444 if (err < 0 || p_response->success == 0) {
1445 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1447 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1448 p_response->p_intermediates->line, sizeof(char *));
1450 at_response_free(p_response);
1453 case RIL_REQUEST_GET_IMEI:
1455 err = at_send_command_numeric("AT+CGSN", &p_response);
1457 if (err < 0 || p_response->success == 0) {
1458 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1460 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1461 p_response->p_intermediates->line, sizeof(char *));
1463 at_response_free(p_response);
1466 case RIL_REQUEST_SIM_IO:
1467 requestSIM_IO(data,datalen,t);
1470 case RIL_REQUEST_SEND_USSD:
1471 requestSendUSSD(data, datalen, t);
1474 case RIL_REQUEST_CANCEL_USSD:
1476 err = at_send_command_numeric("AT+CUSD=2", &p_response);
1478 if (err < 0 || p_response->success == 0) {
1479 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1481 RIL_onRequestComplete(t, RIL_E_SUCCESS,
1482 p_response->p_intermediates->line, sizeof(char *));
1484 at_response_free(p_response);
1487 case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
1488 at_send_command("AT+COPS=0", NULL);
1491 case RIL_REQUEST_DATA_CALL_LIST:
1492 requestDataCallList(data, datalen, t);
1495 case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
1496 requestQueryNetworkSelectionMode(data, datalen, t);
1499 case RIL_REQUEST_OEM_HOOK_RAW:
1501 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1505 case RIL_REQUEST_OEM_HOOK_STRINGS: {
1509 ALOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
1512 for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
1513 i > 0 ; cur++, i --) {
1514 ALOGD("> '%s'", *cur);
1517 // echo back strings
1518 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
1522 case RIL_REQUEST_WRITE_SMS_TO_SIM:
1523 requestWriteSmsToSim(data, datalen, t);
1526 case RIL_REQUEST_DELETE_SMS_ON_SIM: {
1529 asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
1530 err = at_send_command(cmd, &p_response);
1532 if (err < 0 || p_response->success == 0) {
1533 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1535 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1537 at_response_free(p_response);
1541 case RIL_REQUEST_ENTER_SIM_PIN:
1542 case RIL_REQUEST_ENTER_SIM_PUK:
1543 case RIL_REQUEST_ENTER_SIM_PIN2:
1544 case RIL_REQUEST_ENTER_SIM_PUK2:
1545 case RIL_REQUEST_CHANGE_SIM_PIN:
1546 case RIL_REQUEST_CHANGE_SIM_PIN2:
1547 requestEnterSimPin(data, datalen, t);
1551 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1557 * Synchronous call from the RIL to us to return current radio state.
1558 * RADIO_STATE_UNAVAILABLE should be the initial state.
1560 static RIL_RadioState
1566 * Call from RIL to us to find out whether a specific request code
1567 * is supported by this implementation.
1569 * Return 1 for "supported" and 0 for "unsupported"
1573 onSupports (int requestCode)
1580 static void onCancel (RIL_Token t)
1586 static const char * getVersion(void)
1588 return "android reference-ril 1.0";
1592 setRadioState(RIL_RadioState newState)
1594 RIL_RadioState oldState;
1596 pthread_mutex_lock(&s_state_mutex);
1601 // If we're closed, the only reasonable state is
1602 // RADIO_STATE_UNAVAILABLE
1603 // This is here because things on the main thread
1604 // may attempt to change the radio state after the closed
1605 // event happened in another thread
1606 newState = RADIO_STATE_UNAVAILABLE;
1609 if (sState != newState || s_closed > 0) {
1612 pthread_cond_broadcast (&s_state_cond);
1615 pthread_mutex_unlock(&s_state_mutex);
1618 /* do these outside of the mutex */
1619 if (sState != oldState) {
1620 RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
1623 /* FIXME onSimReady() and onRadioPowerOn() cannot be called
1624 * from the AT reader thread
1625 * Currently, this doesn't happen, but if that changes then these
1626 * will need to be dispatched on the request thread
1628 if (sState == RADIO_STATE_SIM_READY) {
1630 } else if (sState == RADIO_STATE_SIM_NOT_READY) {
1636 /** Returns SIM_NOT_READY on error */
1640 ATResponse *p_response = NULL;
1646 if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
1647 ret = SIM_NOT_READY;
1651 err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
1654 ret = SIM_NOT_READY;
1658 switch (at_get_cme_error(p_response)) {
1662 case CME_SIM_NOT_INSERTED:
1667 ret = SIM_NOT_READY;
1671 /* CPIN? has succeeded, now look at the result */
1673 cpinLine = p_response->p_intermediates->line;
1674 err = at_tok_start (&cpinLine);
1677 ret = SIM_NOT_READY;
1681 err = at_tok_nextstr(&cpinLine, &cpinResult);
1684 ret = SIM_NOT_READY;
1688 if (0 == strcmp (cpinResult, "SIM PIN")) {
1691 } else if (0 == strcmp (cpinResult, "SIM PUK")) {
1694 } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
1695 return SIM_NETWORK_PERSONALIZATION;
1696 } else if (0 != strcmp (cpinResult, "READY")) {
1697 /* we're treating unsupported lock types as "sim absent" */
1702 at_response_free(p_response);
1709 at_response_free(p_response);
1715 * Get the current card status.
1717 * This must be freed using freeCardStatus.
1718 * @return: On success returns RIL_E_SUCCESS
1720 static int getCardStatus(RIL_CardStatus_v6 **pp_card_status) {
1721 static RIL_AppStatus app_status_array[] = {
1723 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
1724 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
1725 // SIM_NOT_READY = 1
1726 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
1727 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
1729 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
1730 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
1732 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
1733 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
1735 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
1736 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
1737 // SIM_NETWORK_PERSONALIZATION = 5
1738 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
1739 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }
1741 RIL_CardState card_state;
1744 int sim_status = getSIMStatus();
1745 if (sim_status == SIM_ABSENT) {
1746 card_state = RIL_CARDSTATE_ABSENT;
1749 card_state = RIL_CARDSTATE_PRESENT;
1753 // Allocate and initialize base card status.
1754 RIL_CardStatus_v6 *p_card_status = malloc(sizeof(RIL_CardStatus_v6));
1755 p_card_status->card_state = card_state;
1756 p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
1757 p_card_status->gsm_umts_subscription_app_index = RIL_CARD_MAX_APPS;
1758 p_card_status->cdma_subscription_app_index = RIL_CARD_MAX_APPS;
1759 p_card_status->ims_subscription_app_index = RIL_CARD_MAX_APPS;
1760 p_card_status->num_applications = num_apps;
1762 // Initialize application status
1764 for (i = 0; i < RIL_CARD_MAX_APPS; i++) {
1765 p_card_status->applications[i] = app_status_array[SIM_ABSENT];
1768 // Pickup the appropriate application status
1769 // that reflects sim_status for gsm.
1770 if (num_apps != 0) {
1771 // Only support one app, gsm
1772 p_card_status->num_applications = 1;
1773 p_card_status->gsm_umts_subscription_app_index = 0;
1775 // Get the correct app status
1776 p_card_status->applications[0] = app_status_array[sim_status];
1779 *pp_card_status = p_card_status;
1780 return RIL_E_SUCCESS;
1784 * Free the card status returned by getCardStatus
1786 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status) {
1787 free(p_card_status);
1791 * SIM ready means any commands that access the SIM will work, including:
1792 * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
1793 * (all SMS-related commands)
1796 static void pollSIMState (void *param)
1798 ATResponse *p_response;
1801 if (sState != RADIO_STATE_SIM_NOT_READY) {
1802 // no longer valid to poll
1806 switch(getSIMStatus()) {
1810 case SIM_NETWORK_PERSONALIZATION:
1812 setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
1816 RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
1820 setRadioState(RADIO_STATE_SIM_READY);
1825 /** returns 1 if on, 0 if off, and -1 on error */
1826 static int isRadioOn()
1828 ATResponse *p_response = NULL;
1833 err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
1835 if (err < 0 || p_response->success == 0) {
1836 // assume radio is off
1840 line = p_response->p_intermediates->line;
1842 err = at_tok_start(&line);
1843 if (err < 0) goto error;
1845 err = at_tok_nextbool(&line, &ret);
1846 if (err < 0) goto error;
1848 at_response_free(p_response);
1854 at_response_free(p_response);
1859 * Initialize everything that can be configured while we're still in
1862 static void initializeCallback(void *param)
1864 ATResponse *p_response = NULL;
1867 setRadioState (RADIO_STATE_OFF);
1871 /* note: we don't check errors here. Everything important will
1872 be handled in onATTimeout and onATReaderClosed */
1874 /* atchannel is tolerant of echo but it must */
1875 /* have verbose result codes */
1876 at_send_command("ATE0Q0V1", NULL);
1878 /* No auto-answer */
1879 at_send_command("ATS0=0", NULL);
1881 /* Extended errors */
1882 at_send_command("AT+CMEE=1", NULL);
1884 /* Network registration events */
1885 err = at_send_command("AT+CREG=2", &p_response);
1887 /* some handsets -- in tethered mode -- don't support CREG=2 */
1888 if (err < 0 || p_response->success == 0) {
1889 at_send_command("AT+CREG=1", NULL);
1892 at_response_free(p_response);
1894 /* GPRS registration events */
1895 at_send_command("AT+CGREG=1", NULL);
1897 /* Call Waiting notifications */
1898 at_send_command("AT+CCWA=1", NULL);
1900 /* Alternating voice/data off */
1901 at_send_command("AT+CMOD=0", NULL);
1904 at_send_command("AT+CMUT=0", NULL);
1906 /* +CSSU unsolicited supp service notifications */
1907 at_send_command("AT+CSSN=0,1", NULL);
1909 /* no connected line identification */
1910 at_send_command("AT+COLP=0", NULL);
1912 /* HEX character set */
1913 at_send_command("AT+CSCS=\"HEX\"", NULL);
1915 /* USSD unsolicited */
1916 at_send_command("AT+CUSD=1", NULL);
1918 /* Enable +CGEV GPRS event notifications, but don't buffer */
1919 at_send_command("AT+CGEREP=1,0", NULL);
1922 at_send_command("AT+CMGF=0", NULL);
1924 #ifdef USE_TI_COMMANDS
1926 at_send_command("AT%CPI=3", NULL);
1928 /* TI specific -- notifications when SMS is ready (currently ignored) */
1929 at_send_command("AT%CSTAT=1", NULL);
1931 #endif /* USE_TI_COMMANDS */
1934 /* assume radio is off on error */
1935 if (isRadioOn() > 0) {
1936 setRadioState (RADIO_STATE_SIM_NOT_READY);
1940 static void waitForClose()
1942 pthread_mutex_lock(&s_state_mutex);
1944 while (s_closed == 0) {
1945 pthread_cond_wait(&s_state_cond, &s_state_mutex);
1948 pthread_mutex_unlock(&s_state_mutex);
1952 * Called by atchannel when an unsolicited line appears
1953 * This is called on atchannel's reader thread. AT commands may
1954 * not be issued here
1956 static void onUnsolicited (const char *s, const char *sms_pdu)
1961 /* Ignore unsolicited responses until we're initialized.
1962 * This is OK because the RIL library will poll for initial state
1964 if (sState == RADIO_STATE_UNAVAILABLE) {
1968 if (strStartsWith(s, "%CTZV:")) {
1969 /* TI specific -- NITZ time */
1973 at_tok_start(&line);
1975 err = at_tok_nextstr(&line, &response);
1978 LOGE("invalid NITZ line %s\n", s);
1980 RIL_onUnsolicitedResponse (
1981 RIL_UNSOL_NITZ_TIME_RECEIVED,
1982 response, strlen(response));
1984 } else if (strStartsWith(s,"+CRING:")
1985 || strStartsWith(s,"RING")
1986 || strStartsWith(s,"NO CARRIER")
1987 || strStartsWith(s,"+CCWA")
1989 RIL_onUnsolicitedResponse (
1990 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
1992 #ifdef WORKAROUND_FAKE_CGEV
1993 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
1994 #endif /* WORKAROUND_FAKE_CGEV */
1995 } else if (strStartsWith(s,"+CREG:")
1996 || strStartsWith(s,"+CGREG:")
1998 RIL_onUnsolicitedResponse (
1999 RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
2001 #ifdef WORKAROUND_FAKE_CGEV
2002 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
2003 #endif /* WORKAROUND_FAKE_CGEV */
2004 } else if (strStartsWith(s, "+CMT:")) {
2005 RIL_onUnsolicitedResponse (
2006 RIL_UNSOL_RESPONSE_NEW_SMS,
2007 sms_pdu, strlen(sms_pdu));
2008 } else if (strStartsWith(s, "+CDS:")) {
2009 RIL_onUnsolicitedResponse (
2010 RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
2011 sms_pdu, strlen(sms_pdu));
2012 } else if (strStartsWith(s, "+CGEV:")) {
2013 /* Really, we can ignore NW CLASS and ME CLASS events here,
2014 * but right now we don't since extranous
2015 * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
2017 /* can't issue AT commands here -- call on main thread */
2018 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
2019 #ifdef WORKAROUND_FAKE_CGEV
2020 } else if (strStartsWith(s, "+CME ERROR: 150")) {
2021 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
2022 #endif /* WORKAROUND_FAKE_CGEV */
2026 /* Called on command or reader thread */
2027 static void onATReaderClosed()
2029 LOGI("AT channel closed\n");
2033 setRadioState (RADIO_STATE_UNAVAILABLE);
2036 /* Called on command thread */
2037 static void onATTimeout()
2039 LOGI("AT channel timeout; closing\n");
2044 /* FIXME cause a radio reset here */
2046 setRadioState (RADIO_STATE_UNAVAILABLE);
2049 static void usage(char *s)
2052 fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
2054 fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
2060 mainLoop(void *param)
2065 AT_DUMP("== ", "entering mainLoop()", -1 );
2066 at_set_on_reader_closed(onATReaderClosed);
2067 at_set_on_timeout(onATTimeout);
2073 fd = socket_loopback_client(s_port, SOCK_STREAM);
2074 } else if (s_device_socket) {
2075 if (!strcmp(s_device_path, "/dev/socket/qemud")) {
2076 /* Before trying to connect to /dev/socket/qemud (which is
2077 * now another "legacy" way of communicating with the
2078 * emulator), we will try to connecto to gsm service via
2080 fd = qemu_pipe_open("qemud:gsm");
2082 /* Qemu-specific control socket */
2083 fd = socket_local_client( "qemud",
2084 ANDROID_SOCKET_NAMESPACE_RESERVED,
2089 if ( write(fd, "gsm", 3) != 3 ||
2090 read(fd, answer, 2) != 2 ||
2091 memcmp(answer, "OK", 2) != 0)
2100 fd = socket_local_client( s_device_path,
2101 ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
2103 } else if (s_device_path != NULL) {
2104 fd = open (s_device_path, O_RDWR);
2105 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
2106 /* disable echo on serial ports */
2108 tcgetattr( fd, &ios );
2109 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
2110 tcsetattr( fd, TCSANOW, &ios );
2115 perror ("opening AT interface. retrying...");
2122 ret = at_open(fd, onUnsolicited);
2125 LOGE ("AT error %d on at_open\n", ret);
2129 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
2131 // Give initializeCallback a chance to dispatched, since
2132 // we don't presently have a cancellation mechanism
2136 LOGI("Re-opening after close");
2142 pthread_t s_tid_mainloop;
2144 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
2149 pthread_attr_t attr;
2153 while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
2156 s_port = atoi(optarg);
2161 LOGI("Opening loopback port %d\n", s_port);
2165 s_device_path = optarg;
2166 LOGI("Opening tty device %s\n", s_device_path);
2170 s_device_path = optarg;
2171 s_device_socket = 1;
2172 LOGI("Opening socket %s\n", s_device_path);
2181 if (s_port < 0 && s_device_path == NULL) {
2186 pthread_attr_init (&attr);
2187 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2188 ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
2190 return &s_callbacks;
2192 #else /* RIL_SHLIB */
2193 int main (int argc, char **argv)
2199 while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
2202 s_port = atoi(optarg);
2206 LOGI("Opening loopback port %d\n", s_port);
2210 s_device_path = optarg;
2211 LOGI("Opening tty device %s\n", s_device_path);
2215 s_device_path = optarg;
2216 s_device_socket = 1;
2217 LOGI("Opening socket %s\n", s_device_path);
2225 if (s_port < 0 && s_device_path == NULL) {
2229 RIL_register(&s_callbacks);
2236 #endif /* RIL_SHLIB */