1 /* //device/system/htcgeneric-ril/htcgeneric-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"
34 #include <sys/socket.h>
35 #include <cutils/sockets.h>
40 #include <utils/Log.h>
42 #define MAX_AT_RESPONSE 0x1000
44 #define RIL_REQUEST_SEND_SMS_EXTENDED 512
46 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
47 #define PPP_TTY_PATH "ppp0"
49 #ifdef USE_TI_COMMANDS
51 // Enable workaround for bug in (TI-based) HTC stack
52 // 1) Make incoming call, do not answer
53 // 2) Hangup remote end
54 // Expected: call should disappear from CLCC line
55 // Actual: Call shows as "ACTIVE" before disappearing
56 #define WORKAROUND_ERRONEOUS_ANSWER 1
58 // Some varients of the TI stack do not support the +CGEV unsolicited
59 // response. However, they seem to send an unsolicited +CME ERROR: 150
60 #define WORKAROUND_FAKE_CGEV 1
66 SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
69 SIM_NETWORK_PERSONALIZATION = 5
72 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
73 static RIL_RadioState currentState();
74 static int onSupports (int requestCode);
75 static void onCancel (RIL_Token t);
76 static const char *getVersion();
77 static int isRadioOn();
78 static SIM_Status getSIMStatus();
79 static int getCardStatus(RIL_CardStatus **pp_card_status);
80 static void freeCardStatus(RIL_CardStatus *p_card_status);
81 static void onDataCallListChanged(void *param);
82 static int killConn(char * cid);
85 extern const char * requestToString(int request);
87 /*** Static Variables ***/
88 static const RIL_RadioFunctions s_callbacks = {
98 static const struct RIL_Env *s_rilenv;
100 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
101 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
102 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
105 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
107 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
108 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
110 static int slow_sim=0;
111 static int s_port = -1;
112 static int cdma_north_american_dialing = 0;
113 static const char * s_device_path = NULL;
114 static int s_device_socket = 0;
116 /* trigger change to this with s_state_cond */
117 static int s_closed = 0;
119 static int sFD; /* file desc of AT channel */
120 static char sATBuffer[MAX_AT_RESPONSE+1];
121 static char *sATBufferCur = NULL;
122 /* Higher layers expect a NITZ string in this format:
123 * 08/10/28,19:08:37-20,1 (yy/mm/dd,hh:mm:ss(+/-)tz,dst)
125 static char sNITZtime[sizeof("08/10/28,19:08:37-20,1")+4];
127 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
128 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
129 static const struct timeval TIMEVAL_0 = {0,0};
131 #ifdef WORKAROUND_ERRONEOUS_ANSWER
132 // Max number of times we'll try to repoll when we think
133 // we have a AT+CLCC race condition
134 #define REPOLL_CALLS_COUNT_MAX 4
136 // Line index that was incoming or waiting at last poll, or -1 for none
137 static int s_incomingOrWaitingLine = -1;
138 // Number of times we've asked for a repoll of AT+CLCC
139 static int s_repollCallsCount = 0;
140 // Should we expect a call to be answered in the next CLCC?
141 static int s_expectAnswer = 0;
142 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
144 static void pollSIMState (void *param);
145 static void setRadioState(RIL_RadioState newState);
148 static int is_world_cdma=0; /* Will be set to 1 for world phones operating in CDMA mode (i.e. RhodiumW/RHOD400/RHOD500) */
149 static char erisystem[50];
150 static char *callwaiting_num;
151 static int countValidCalls=0;
152 static int signalStrength[2];
154 static void handle_cdma_ccwa (const char *s)
161 free(callwaiting_num);
162 callwaiting_num = NULL;
164 line = tmp = strdup(s);
165 err = at_tok_start(&tmp);
168 err = at_tok_nextstr(&tmp, &callwaiting_num);
171 callwaiting_num = strdup(callwaiting_num);
172 LOGE("successfully set callwaiting_numn");
177 extern char** cdma_to_gsmpdu(const char *);
178 extern char* gsm_to_cdmapdu(const char *);
179 extern int hex2int(const char);
181 static void HexStr_to_DecInt(char *strings, unsigned int *ints)
184 int j = strlen(strings);
186 for(i = 0, k = 0; i < j; i += 2, k++)
188 printf("%d, %d\n", i, k);
189 if(strings[i] <= 57){
190 *(ints + k) += (unsigned int)((strings[i] - 48) * 16);
193 *(ints+k) += (unsigned int)(((strings[i] - 97) + 10) * 16);
196 if(strings[i+1] <= 57){
197 *(ints+k) += (unsigned int)(strings[i+1] - 48);
200 *(ints+k) += (unsigned int)((strings[i+1] - 97) + 10);
205 static int clccStateToRILState(int state, RIL_CallState *p_state)
209 case 0: *p_state = RIL_CALL_ACTIVE; return 0;
210 case 1: *p_state = RIL_CALL_HOLDING; return 0;
211 case 2: *p_state = RIL_CALL_DIALING; return 0;
212 case 3: *p_state = RIL_CALL_ALERTING; return 0;
213 case 4: *p_state = RIL_CALL_INCOMING; return 0;
214 case 5: *p_state = RIL_CALL_WAITING; return 0;
219 static const char* networkStatusToRilString(int state)
222 case 0: return("unknown"); break;
223 case 1: return("available"); break;
224 case 2: return("current"); break;
225 case 3: return("forbidden"); break;
226 default: return NULL;
230 // some phone functions are controlled by msm_proc_comm through /sys
231 void writesys(char *name, char *val) {
234 strcpy(filename,"/sys/class/vogue_hw/");
235 strcat(filename,name);
236 fout=fopen(filename,"w");
238 fprintf(fout, "%s", val);
242 * Note: directly modified line and has *p_call point directly into
245 static int callFromCLCCLine(char *line, RIL_Call *p_call)
247 //+CLCC: 1,0,2,0,0,\"+18005551212\",145
248 // index,isMT,state,mode,isMpty(,number,TOA)?
254 err = at_tok_start(&line);
255 if (err < 0) goto error;
257 err = at_tok_nextint(&line, &(p_call->index));
258 if (err < 0) goto error;
260 err = at_tok_nextbool(&line, &(p_call->isMT));
261 if (err < 0) goto error;
263 err = at_tok_nextint(&line, &state);
264 if (err < 0) goto error;
266 err = clccStateToRILState(state, &(p_call->state));
267 if (err < 0) goto error;
269 err = at_tok_nextint(&line, &mode);
270 if (err < 0) goto error;
272 p_call->isVoice = (mode == 0);
274 err = at_tok_nextbool(&line, &(p_call->isMpty));
275 if (err < 0) goto error;
277 if (at_tok_hasmore(&line)) {
278 err = at_tok_nextstr(&line, &(p_call->number));
280 /* tolerate null here */
281 if (err < 0) return 0;
283 // Some lame implementations return strings
284 // like "NOT AVAILABLE" in the CLCC line
285 if (p_call->number != NULL
286 && 0 == strspn(p_call->number, "+0123456789")
288 p_call->number = NULL;
291 err = at_tok_nextint(&line, &p_call->toa);
292 if (err < 0) goto error;
298 LOGE("invalid CLCC line\n");
302 //returns the call number of the active data call, or -1 if no active call
303 static int dataCallNum()
306 ATResponse *p_response;
313 if(currentState() != RADIO_STATE_SIM_READY){
317 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
319 if (err != 0 || p_response->success == 0) {
323 /* count the calls */
324 for (countCalls = 0, p_cur = p_response->p_intermediates
326 ; p_cur = p_cur->p_next
331 p_call = (RIL_Call *)alloca(sizeof(RIL_Call));
332 memset (p_call, 0, sizeof(RIL_Call));
334 for (i = 0, p_cur = p_response->p_intermediates
336 ; p_cur = p_cur->p_next
338 err = callFromCLCCLine(p_cur->line, p_call);
344 if(p_call[0].isVoice == 0) // only count data calls
353 /** do post-AT+CFUN=1 initialization */
354 static void onRadioPowerOn()
356 #ifdef USE_TI_COMMANDS
357 /* Must be after CFUN=1 */
358 /* TI specific -- notifications for CPHS things such */
359 /* as CPHS message waiting indicator */
361 at_send_command("AT%CPHS=1", NULL);
363 /* TI specific -- enable NITZ unsol notifs */
364 at_send_command("AT%CTZV=1", NULL);
368 at_send_command("ATE0", NULL);
369 at_send_command("AT+CLIP=1", NULL);
370 at_send_command("AT+CLIR=0", NULL);
371 at_send_command("AT+CPPP=2", NULL);
372 at_send_command("AT+HTCNV=1,12,6", NULL);
374 /*enable ENS mode, okay to fail */
375 // at_send_command("AT+HTCENS=1", NULL);
376 // at_send_command("AT+HSDPA=1", NULL);
377 at_send_command("AT+HTCAGPS=5", NULL);
378 at_send_command("AT", NULL);
379 at_send_command("AT+ODEN=112", NULL);
380 at_send_command("AT+ODEN=911", NULL);
381 // at_send_command("AT+ALS=4294967295", NULL);
386 /** do post- SIM ready initialization */
387 static void onSIMReady()
389 /* Common initialization commands */
391 /* Network registration */
392 at_send_command("AT+COPS=0", NULL);
395 /* Preferred RAT - UMTS Dualmode */
396 // at_send_command("AT+XRAT=1,2", NULL);
398 //debug what type of sim is it?
399 at_send_command("AT+SIMTYPE", NULL);
402 * Always send SMS messages directly to the TE
404 * mode = 1 // discard when link is reserved (link should never be
406 * mt = 2 // most messages routed to TE
407 * bm = 2 // new cell BM's routed to TE
408 * ds = 1 // Status reports routed to TE
409 * bfr = 1 // flush buffer
411 at_send_command("AT+CNMI=1,2,2,1,1", NULL);
413 at_send_command("AT+CSCB=1", NULL);
415 /* Enable +CGEV GPRS event notifications, but don't buffer */
416 // at_send_command("AT+CGEREP=1,0", NULL);
418 /* Enable NITZ reporting */
419 // at_send_command("AT+CTZU=1", NULL);
420 // at_send_command("AT+CTZR=1", NULL);
421 at_send_command("AT+HTCCTZR=1", NULL);
423 /* Enable unsolizited RSSI reporting */
424 at_send_command("AT@HTCCSQ=1", NULL);
426 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
431 at_send_command("AT+HTC_GPSONE=4", NULL);
432 at_send_command("AT+CLVL=102", NULL);
433 at_send_command("AT+CLVL=51", NULL);
437 static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
442 ATResponse *p_response = NULL;
444 assert (datalen >= sizeof(int *));
445 onOff = ((int *)data)[0];
447 if (onOff == 0 && sState != RADIO_STATE_OFF) {
448 if(isgsm || is_world_cdma)
449 err = at_send_command("AT+CFUN=0", &p_response);
451 err = at_send_command("AT+CFUN=66", &p_response);
452 if (err < 0 || p_response->success == 0) goto error;
453 setRadioState(RADIO_STATE_OFF);
454 } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
455 err = at_send_command("AT+CFUN=1", &p_response);
456 if (err < 0|| p_response->success == 0) {
457 // Some stacks return an error when there is no SIM,
458 // but they really turn the RF portion on
459 // So, if we get an error, let's check to see if it
462 if (isRadioOn() != 1) {
466 setRadioState(RADIO_STATE_SIM_NOT_READY);
469 at_response_free(p_response);
470 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
474 at_response_free(p_response);
475 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
478 static void requestOrSendDataCallList(RIL_Token *t);
480 static void onDataCallListChanged(void *param)
482 requestOrSendDataCallList(NULL);
485 static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
487 requestOrSendDataCallList(&t);
490 static void requestOrSendDataCallList(RIL_Token *t)
492 ATResponse *p_response;
494 RIL_Data_Call_Response *responses;
502 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
503 if (err != 0 || p_response->success == 0) {
505 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
507 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
512 for (p_cur = p_response->p_intermediates; p_cur != NULL;
513 p_cur = p_cur->p_next)
516 responses = alloca(n * sizeof(RIL_Data_Call_Response));
519 for (i = 0; i < n; i++) {
520 responses[i].cid = -1;
521 responses[i].active = -1;
522 responses[i].type = "";
523 responses[i].apn = "";
524 responses[i].address = "";
527 RIL_Data_Call_Response *response = responses;
528 for (p_cur = p_response->p_intermediates; p_cur != NULL;
529 p_cur = p_cur->p_next) {
530 char *line = p_cur->line;
532 err = at_tok_start(&line);
536 err = at_tok_nextint(&line, &response->cid);
540 err = at_tok_nextint(&line, &response->active);
547 at_response_free(p_response);
549 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
550 if (err != 0 || p_response->success == 0) {
552 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
554 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
559 for (p_cur = p_response->p_intermediates; p_cur != NULL;
560 p_cur = p_cur->p_next) {
561 char *line = p_cur->line;
568 err = at_tok_start(&line);
572 err = at_tok_nextint(&line, &cid);
576 for (i = 0; i < n; i++) {
577 if (responses[i].cid == cid)
582 /* details for a context we didn't hear about in the last request */
586 err = at_tok_nextstr(&line, &out);
590 responses[i].type = alloca(strlen(out) + 1);
591 strcpy(responses[i].type, out);
593 err = at_tok_nextstr(&line, &out);
597 responses[i].apn = alloca(strlen(out) + 1);
598 strcpy(responses[i].apn, out);
600 err = at_tok_nextstr(&line, &out);
604 responses[i].address = alloca(strlen(out) + 1);
605 strcpy(responses[i].address, out);
608 at_response_free(p_response);
613 responses = alloca(sizeof(RIL_Data_Call_Response));
615 responses[0].cid = 1;
616 if (dataCallNum() >= 0)
617 responses[0].active = 1;
619 responses[0].active = 0;
620 responses[0].type = "";
621 responses[0].apn = "internet";
622 responses[0].address = "";
625 // make sure pppd is still running, invalidate datacall if it isn't
626 if ((fd = open("/etc/ppp/ppp-gprs.pid",O_RDONLY)) > 0)
632 responses[0].active = 0;
636 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
637 n * sizeof(RIL_Data_Call_Response));
639 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
641 n * sizeof(RIL_Data_Call_Response));
647 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
649 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
652 at_response_free(p_response);
655 static void requestBasebandVersion(void *data, size_t datalen, RIL_Token t)
658 ATResponse *p_response = NULL;
659 char * response = NULL;
663 err = at_send_command_singleline("AT+CGMM", "", &p_response);
664 if (err != 0) goto error;
666 line = p_response->p_intermediates->line;
668 response = (char *)alloca(sizeof(char *));
670 err = at_tok_nextstr(&line, &response);
671 if (err < 0) goto error;
673 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char *));
674 at_response_free(p_response);
676 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
681 at_response_free(p_response);
682 LOGE("ERROR: requestBasebandVersion failed\n");
683 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
687 static void requestQueryNetworkSelectionMode(
688 void *data, size_t datalen, RIL_Token t)
691 ATResponse *p_response = NULL;
695 if(isgsm) { //this command conflicts with the network status command
696 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
698 if (err < 0 || p_response->success == 0) {
702 line = p_response->p_intermediates->line;
704 err = at_tok_start(&line);
710 err = at_tok_nextint(&line, &response);
717 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
718 at_response_free(p_response);
722 at_response_free(p_response);
723 LOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
724 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
727 static void requestQueryAvailableNetworks(void *data, size_t datalen, RIL_Token t)
729 /* We expect an answer on the following form:
730 +COPS: (2,"AT&T","AT&T","310410",0),(1,"T-Mobile ","TMO","310260",0)
733 int err, operators, i, skip, status;
734 ATResponse *p_response = NULL;
735 char * c_skip, *line, *p = NULL;
736 char ** response = NULL;
738 err = at_send_command_singleline("AT+COPS=?", "+COPS:", &p_response);
740 if (err != 0) goto error;
742 line = p_response->p_intermediates->line;
744 err = at_tok_start(&line);
745 if (err < 0) goto error;
747 /* Count number of '(' in the +COPS response to get number of operators*/
749 for (p = line ; *p != '\0' ;p++) {
750 if (*p == '(') operators++;
753 response = (char **)alloca(operators * 4 * sizeof(char *));
755 for (i = 0 ; i < operators ; i++ )
757 err = at_tok_nextstr(&line, &c_skip);
758 if (err < 0) goto error;
759 if (strcmp(c_skip,"") == 0)
764 status = atoi(&c_skip[1]);
765 response[i*4+3] = (char*)networkStatusToRilString(status);
767 err = at_tok_nextstr(&line, &(response[i*4+0]));
768 if (err < 0) goto error;
770 err = at_tok_nextstr(&line, &(response[i*4+1]));
771 if (err < 0) goto error;
773 err = at_tok_nextstr(&line, &(response[i*4+2]));
774 if (err < 0) goto error;
776 err = at_tok_nextstr(&line, &c_skip);
778 if (err < 0) goto error;
781 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, (operators * 4 * sizeof(char *)));
782 at_response_free(p_response);
786 at_response_free(p_response);
787 LOGE("ERROR - requestQueryAvailableNetworks() failed");
788 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
791 static void requestGetPreferredNetworkType(void *data, size_t datalen, RIL_Token t)
794 ATResponse *p_response = NULL;
800 err = at_send_command_singleline("AT+CGAATT?", "+CGAATT:", &p_response);
802 if (err < 0 || p_response->success == 0) {
806 line = p_response->p_intermediates->line;
808 err = at_tok_start(&line);
814 // Get third int in response
815 err = at_tok_nextint(&line, &response);
819 err = at_tok_nextint(&line, &response);
823 err = at_tok_nextint(&line, &response);
827 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
828 at_response_free(p_response);
831 LOGE("ERROR: requestGetPreferredNetworkType() failed - modem does not support command\n");
832 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
835 at_response_free(p_response);
836 LOGE("ERROR: requestGetPreferredNetworkType() failed\n");
837 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
840 static void requestSetPreferredNetworkType(void *data, size_t datalen, RIL_Token t)
843 ATResponse *p_response = NULL;
845 const char *at_rat = NULL;
849 assert (datalen >= sizeof(int *));
850 rat = ((int *)data)[0];
852 #ifdef USE_IDCC_MODEM
855 case 0: at_rat = "1,2"; break;/* Dual Mode - WCDMA preferred*/
856 case 1: at_rat = "0"; break; /* GSM only */
857 case 2: at_rat = "2"; break; /* WCDMA only */
860 /* Need to unregister from NW before changing preferred RAT */
861 err = at_send_command("AT+COPS=2", NULL);
862 if (err < 0) goto error;
864 asprintf(&cmd, "AT+XRAT=%s", at_rat);
866 LOGD("In requestSetPreferredNetworkType RAPH");
868 case 0: at_rat = "2,1,0"; break;/* Dual Mode - WCDMA preferred*/
869 case 1: at_rat = "2,1,1"; break; /* GSM only */
870 case 2: at_rat = "2,1,2"; break; /* WCDMA only */
873 /* For some reason, without the bandset command, the CGAATT
874 one fails. [mdrobnak] */
875 err = at_send_command("AT+BANDSET=0", NULL);
876 if (err < 0) goto error;
878 asprintf(&cmd, "AT+CGAATT=%s", at_rat);
880 #endif /* USE_IDCC_MODEM */
881 err = at_send_command(cmd, &p_response);
884 if (err < 0|| p_response->success == 0) {
888 /* Register on the NW again */
889 err = at_send_command("AT+COPS=0", NULL);
890 if (err < 0) goto error;
892 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, sizeof(int));
893 at_response_free(p_response);
896 LOGE("ERROR: requestSetPreferredNetworkType() failed - command not supported by modem\n");
897 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
900 at_response_free(p_response);
901 LOGE("ERROR: requestSetPreferredNetworkType() failed\n");
902 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
906 static void requestQueryFacilityLock(void *data, size_t datalen, RIL_Token t)
908 int err, rat, response;
909 ATResponse *p_response = NULL;
912 char * facility_string = NULL;
913 char * facility_password = NULL;
914 char * facility_class = NULL;
917 assert (datalen >= (3 * sizeof(char **)));
919 facility_string = ((char **)data)[0];
920 facility_password = ((char **)data)[1];
921 facility_class = ((char **)data)[2];
924 asprintf(&cmd, "AT+CLCK=\"%s\",2,\"%s\",%s", facility_string, facility_password, facility_class);
925 err = at_send_command_singleline(cmd,"+CLCK:", &p_response);
927 if (err < 0 || p_response->success == 0){
931 line = p_response->p_intermediates->line;
933 err = at_tok_start(&line);
939 err = at_tok_nextint(&line, &response);
945 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
946 at_response_free(p_response);
950 at_response_free(p_response);
951 LOGE("ERROR: requestQueryFacilityLock() failed\n");
952 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
955 static void sendCallStateChanged(void *param)
957 RIL_onUnsolicitedResponse (
958 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
962 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
965 ATResponse *p_response;
973 char *l_callwaiting_num=NULL;
975 #ifdef WORKAROUND_ERRONEOUS_ANSWER
976 int prevIncomingOrWaitingLine;
978 prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
979 s_incomingOrWaitingLine = -1;
980 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
982 if(currentState() != RADIO_STATE_SIM_READY){
983 /* Might be waiting for SIM PIN */
984 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
987 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
989 if (err != 0 || p_response->success == 0) {
990 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
994 /* count the calls */
995 for (countCalls = 0, p_cur = p_response->p_intermediates
997 ; p_cur = p_cur->p_next
1002 if (callwaiting_num) {
1003 /* This is not thread-safe. Boo. */
1004 l_callwaiting_num = callwaiting_num;
1005 callwaiting_num = NULL;
1009 /* yes, there's an array of pointers and then an array of structures */
1011 pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
1012 p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
1013 memset (p_calls, 0, countCalls * sizeof(RIL_Call));
1015 /* init the pointer array */
1016 for(i = 0; i < countCalls ; i++) {
1017 pp_calls[i] = &(p_calls[i]);
1020 for (countValidCalls = 0, p_cur = p_response->p_intermediates
1022 ; p_cur = p_cur->p_next
1024 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
1030 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1031 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
1032 || p_calls[countValidCalls].state == RIL_CALL_WAITING
1034 s_incomingOrWaitingLine = p_calls[countValidCalls].index;
1036 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
1038 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
1039 && p_calls[countValidCalls].state != RIL_CALL_HOLDING
1043 if(p_calls[countValidCalls].isVoice) // only count voice calls
1047 if (l_callwaiting_num) {
1049 int index = p_calls[countValidCalls-1].index+1;
1051 /* Try not to use an index greater than 9 */
1055 for (i=countValidCalls-2; i >= 0; i++) {
1056 if (p_calls[i].index < 9) {
1057 index = p_calls[i].index+1;
1063 snprintf(fake_clcc, 64, "+CLCC: %d,0,5,0,0,\"%s\",129",
1064 index, l_callwaiting_num);
1065 free(l_callwaiting_num);
1066 err = callFromCLCCLine(fake_clcc, p_calls + countValidCalls);
1072 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1074 // A call was incoming or waiting
1075 // Now it's marked as active
1076 // But we never answered it
1078 // This is probably a bug, and the call will probably
1079 // disappear from the call list in the next poll
1080 if (prevIncomingOrWaitingLine >= 0
1081 && s_incomingOrWaitingLine < 0
1082 && s_expectAnswer == 0
1084 for (i = 0; i < countValidCalls ; i++) {
1086 if (p_calls[i].index == prevIncomingOrWaitingLine
1087 && p_calls[i].state == RIL_CALL_ACTIVE
1088 && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
1091 "Hit WORKAROUND_ERRONOUS_ANSWER case."
1092 " Repoll count: %d\n", s_repollCallsCount);
1093 s_repollCallsCount++;
1100 s_repollCallsCount = 0;
1101 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
1102 LOGI("Calls=%d,Valid=%d\n",countCalls,countValidCalls);
1103 if(countValidCalls==0) { // close audio if no voice calls.
1104 LOGI("Audio Close\n");
1105 writesys("audio","5");
1108 RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
1109 countValidCalls * sizeof (RIL_Call *));
1111 at_response_free(p_response);
1113 #ifdef POLL_CALL_STATE
1114 if (countValidCalls) // We don't seem to get a "NO CARRIER" message from
1115 // smd, so we're forced to poll until the call ends.
1120 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
1125 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1126 at_response_free(p_response);
1129 static void requestDial(void *data, size_t datalen, RIL_Token t)
1136 p_dial = (RIL_Dial *)data;
1138 switch (p_dial->clir) {
1139 case 1: clir = "I"; break; /*invocation*/
1140 case 2: clir = "i"; break; /*suppression*/
1142 case 0: clir = ""; break; /*subscription default*/
1144 writesys("audio","2");
1145 if(cdma_north_american_dialing && strncmp(p_dial->address, "+1", 2)==0)
1146 asprintf(&cmd, "ATD%s%s;", p_dial->address+1, clir);
1148 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
1150 ret = at_send_command(cmd, NULL);
1154 /* success or failure is ignored by the upper layer here.
1155 it will call GET_CURRENT_CALLS and determine success that way */
1156 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1159 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
1161 RIL_SMS_WriteArgs *p_args;
1165 ATResponse *p_response = NULL;
1169 p_args = (RIL_SMS_WriteArgs *)data;
1171 length = strlen(p_args->pdu)/2;
1172 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
1174 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
1178 if (err != 0 || p_response->success == 0) goto error;
1180 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1181 at_response_free(p_response);
1183 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1188 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1189 at_response_free(p_response);
1192 static void requestHangup(void *data, size_t datalen, RIL_Token t)
1199 p_line = (int *)data;
1201 // 3GPP 22.030 6.5.5
1202 // "Releases a specific active call X"
1203 asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
1205 ret = at_send_command(cmd, NULL);
1208 // writesys("audio","5");
1210 /* success or failure is ignored by the upper layer here.
1211 it will call GET_CURRENT_CALLS and determine success that way */
1212 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1215 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
1217 ATResponse *p_response = NULL;
1222 #if 0 /* Just rely on unsolicited reports */
1223 if(signalStrength[0] == 0 && signalStrength[1] == 0) {
1225 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
1227 err = at_send_command_singleline("AT+HTC_CSQ", "+HTC_CSQ:", &p_response);
1229 if (err < 0 || p_response->success == 0) {
1230 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1234 line = p_response->p_intermediates->line;
1236 err = at_tok_start(&line);
1237 if (err < 0) goto error;
1239 err = at_tok_nextint(&line, &(response[0]));
1240 if (err < 0) goto error;
1242 err = at_tok_nextint(&line, &(response[1]));
1243 if (err < 0) goto error;
1248 signalStrength[0] = response[0];
1249 signalStrength[1] = response[1];
1250 at_response_free(p_response);
1253 LOGD("Sending stored CSQ values to RIL");
1254 response[0] = signalStrength[0];
1255 response[1] = signalStrength[1];
1258 response[0] = signalStrength[0];
1259 response[1] = signalStrength[1];
1260 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1264 LOGE("requestSignalStrength must never return an error when radio is on");
1265 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1266 at_response_free(p_response);
1269 static void requestDtmfStart(void *data, size_t datalen, RIL_Token t)
1275 assert (datalen >= sizeof(char *));
1277 c = ((char *)data)[0];
1278 at_send_command("AT+CMUT=1", NULL);
1279 asprintf(&cmd, "AT+VTS=%c", (int)c);
1281 at_send_command("AT+WFSH", NULL); //FIXME: what is this for??? send flash? doesn't make sense
1283 err = at_send_command(cmd, NULL);
1286 if (err != 0) goto error;
1288 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1292 LOGE("ERROR: requestDtmfStart failed");
1293 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1297 static void requestDtmfStop(void *data, size_t datalen, RIL_Token t)
1301 /* Send a command to cancel the DTMF tone*/
1302 err = at_send_command("AT", NULL);
1303 if (err != 0) goto error;
1304 err = at_send_command("AT+CMUT=0", NULL);
1305 if (err != 0) goto error;
1307 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1311 LOGE("ERROR: requestDtmfStop failed");
1312 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1316 static void requestSetMute(void *data, size_t datalen, RIL_Token t)
1321 assert (datalen >= sizeof(int *));
1323 asprintf(&cmd, "AT+CMUT=%d", ((int*)data)[0]);
1325 err = at_send_command(cmd, NULL);
1328 if (err != 0) goto error;
1330 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1334 LOGE("ERROR: requestSetMute failed");
1335 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1339 static void requestGetMute(void *data, size_t datalen, RIL_Token t)
1342 ATResponse *p_response = NULL;
1347 err = at_send_command_singleline("AT+CMUT?", "+CMUT:", &p_response);
1349 err = at_send_command_singleline("AT+MUT", "+CMUT:", &p_response);
1351 if (err < 0 || p_response->success == 0) {
1355 line = p_response->p_intermediates->line;
1357 err = at_tok_start(&line);
1358 if (err < 0) goto error;
1360 err = at_tok_nextint(&line, &response[0]);
1361 if (err < 0) goto error;
1363 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char*));
1364 at_response_free(p_response);
1369 LOGE("ERROR: requestGetMute failed");
1370 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1371 at_response_free(p_response);
1374 static void requestScreenState(void *data, size_t datalen, RIL_Token t)
1376 int err, screenState;
1378 assert (datalen >= sizeof(int *));
1379 screenState = ((int*)data)[0];
1381 if(screenState == 1)
1388 "AT+ENCSQ=1;+CREG=2\r"
1390 requestRegistrationState
1395 /* Screen is on - be sure to enable all unsolicited notifications again */
1396 /* err = at_send_command("AT+CREG=2", NULL);
1397 if (err < 0) goto error;
1398 err = at_send_command("AT+CGREG=2", NULL);
1399 if (err < 0) goto error;
1400 err = at_send_command("AT+CGEREP=1,0", NULL);
1401 if (err < 0) goto error;
1402 err = at_send_command("AT@HTCPDPFD=0", NULL);
1403 if (err < 0) goto error;
1404 err = at_send_command("AT+ENCSQ=1",NULL);
1405 if (err < 0) goto error;
1406 err = at_send_command("AT@HTCCSQ=1", NULL);
1407 if (err < 0) goto error;*/
1409 err = at_send_command("AT+ENCSQ=1;+CREG=2", NULL);
1410 if (err < 0) goto error;
1411 err = at_send_command("AT+HTCCTZR=1", NULL);
1412 if (err < 0) goto error;
1413 err = at_send_command("AT@HTCPDPFD=0", NULL);
1414 if (err < 0) goto error;
1418 } else if (screenState == 0) {
1425 "AT+ENCSQ=0;+CREG=1\r"
1429 /* Screen is off - disable all unsolicited notifications */
1430 /*err = at_send_command("AT+CREG=0", NULL);
1431 if (err < 0) goto error;
1432 err = at_send_command("AT+CGREG=0", NULL);
1433 if (err < 0) goto error;
1434 err = at_send_command("AT+CGEREP=0,0", NULL);
1435 if (err < 0) goto error;
1436 err = at_send_command("AT@HTCPDPFD=1", NULL);
1437 if (err < 0) goto error;
1438 err = at_send_command("AT+ENCSQ=0",NULL);
1439 if (err < 0) goto error;
1440 err = at_send_command("AT@HTCCSQ=0", NULL);
1441 if (err < 0) goto error;*/
1443 err = at_send_command("AT+HTCPDPIDLE", NULL);
1444 if (err < 0) goto error;
1445 err = at_send_command("AT+ENCSQ=0;+CREG=1", NULL);
1446 if (err < 0) goto error;
1447 err = at_send_command("AT+HTCCTZR=2", NULL);
1448 if (err < 0) goto error;
1449 err = at_send_command("AT@HTCPDPFD=1", NULL);
1450 if (err < 0) goto error;
1455 /* Not a defined value - error */
1459 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1463 LOGE("ERROR: requestScreenState failed");
1464 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1467 static void requestRegistrationState(int request, void *data,
1468 size_t datalen, RIL_Token t)
1472 char * responseStr[4];
1473 ATResponse *p_response = NULL;
1491 if (request == RIL_REQUEST_REGISTRATION_STATE) {
1494 } else if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
1502 /* "Regular" CDMA (like Diam/Raph) uses AT+COPS, world phone CDMA uses AT+HTC_SRV_STATUS */
1504 cmd = "AT+HTC_SRV_STATUS?";
1508 prefix= "$HTC_SYSTYPE";
1511 for (i=0;i<4 && err != 0;i++)
1512 err = at_send_command_singleline(cmd, prefix, &p_response);
1514 if (err != 0) goto error;
1516 line = p_response->p_intermediates->line;
1518 err = at_tok_start(&line);
1519 if (err < 0) goto error;
1521 /* Ok you have to be careful here
1522 * The solicited version of the CREG response is
1523 * +CREG: n, stat, [lac, cid]
1524 * and the unsolicited version is
1525 * +CREG: stat, [lac, cid]
1526 * The <n> parameter is basically "is unsolicited creg on?"
1527 * which it should always be
1529 * Now we should normally get the solicited version here,
1530 * but the unsolicited version could have snuck in
1531 * so we have to handle both
1533 * Also since the LAC and CID are only reported when registered,
1534 * we can have 1, 2, 3, or 4 arguments here
1536 * finally, a +CGREG: answer may have a fifth value that corresponds
1537 * to the network type, as in;
1539 * +CGREG: n, stat [,lac, cid [,networkType]]
1542 /* count number of commas */
1544 for (p = line ; *p != '\0' ;p++) {
1545 if (*p == ',') commas++;
1549 case 0: /* +CREG: <stat> */
1550 err = at_tok_nextint(&line, &response[0]);
1551 if (err < 0) goto error;
1556 case 1: /* +CREG: <n>, <stat> */
1557 err = at_tok_nextint(&line, &skip);
1558 if (err < 0) goto error;
1559 err = at_tok_nextint(&line, &response[0]);
1560 if (err < 0) goto error;
1563 if (err < 0) goto error;
1566 case 2: /* +CREG: <stat>, <lac>, <cid> */
1567 err = at_tok_nextint(&line, &response[0]);
1568 if (err < 0) goto error;
1569 err = at_tok_nexthexint(&line, &response[1]);
1570 if (err < 0) goto error;
1571 err = at_tok_nexthexint(&line, &response[2]);
1572 if (err < 0) goto error;
1574 case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
1575 err = at_tok_nextint(&line, &skip);
1576 if (err < 0) goto error;
1577 err = at_tok_nextint(&line, &response[0]);
1578 if (err < 0) goto error;
1579 err = at_tok_nexthexint(&line, &response[1]);
1580 if (err < 0) goto error;
1581 err = at_tok_nexthexint(&line, &response[2]);
1582 if (err < 0) goto error;
1584 /* Hack for broken +CGREG responses which don't return the network type */
1585 if(request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
1586 ATResponse *p_response_op = NULL;
1587 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response_op);
1588 /* We need to get the 4th return param */
1591 char *p_op, *line_op;
1592 line_op = p_response_op->p_intermediates->line;
1594 for (p_op = line_op ; *p_op != '\0' ;p_op++) {
1595 if (*p_op == ',') commas_op++;
1598 if (commas_op == 3) {
1599 err = at_tok_start(&line_op);
1600 err = at_tok_nextint(&line_op, &skip);
1601 if (err < 0) goto error;
1602 err = at_tok_nextint(&line_op, &skip);
1603 if (err < 0) goto error;
1604 err = at_tok_nextint(&line_op, &skip);
1605 if (err < 0) goto error;
1606 err = at_tok_nextint(&line_op, &response[3]);
1607 if (err < 0) goto error;
1608 /* Now translate to 'Broken Android Speak' - can't follow the GSM spec */
1609 switch(response[3]) {
1610 /* GSM/GSM Compact - aka GRPS */
1615 /* EGPRS - aka EDGE */
1619 /* UTRAN - UMTS aka 3G */
1624 /* UTRAN with HSDPA and/or HSUPA aka Turbo-3G */
1633 at_response_free(p_response_op);
1636 /* special case for CGREG, there is a fourth parameter
1637 * that is the network type (unknown/gprs/edge/umts)
1639 case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
1640 err = at_tok_nextint(&line, &skip);
1641 if (err < 0) goto error;
1642 err = at_tok_nextint(&line, &response[0]);
1643 if (err < 0) goto error;
1644 err = at_tok_nexthexint(&line, &response[1]);
1645 if (err < 0) goto error;
1646 err = at_tok_nexthexint(&line, &response[2]);
1647 if (err < 0) goto error;
1648 err = at_tok_nexthexint(&line, &response[3]);
1649 if (err < 0) goto error;
1655 if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
1656 err = at_tok_nextint(&line, &response[3]);
1657 if (response[3] < 1)
1659 if (response[3] > 3)
1663 asprintf(&responseStr[0], "%d", response[0]);
1664 asprintf(&responseStr[1], "%x", response[1]);
1665 asprintf(&responseStr[2], "%x", response[2]);
1666 asprintf(&responseStr[3], "%d", response[3]);
1668 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
1669 at_response_free(p_response);
1673 LOGE("requestRegistrationState must never return an error when radio is on");
1674 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1675 at_response_free(p_response);
1678 static void requestOperator(void *data, size_t datalen, RIL_Token t)
1686 memset(response, 0, sizeof(response));
1688 ATResponse *p_response = NULL;
1690 err = at_send_command_multiline(
1691 "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
1692 "+COPS:", &p_response);
1694 /* we expect 3 lines here:
1695 * +COPS: 0,0,"T - Mobile"
1697 * +COPS: 0,2,"310170"
1700 if (err != 0) goto error;
1702 for (i = 0, p_cur = p_response->p_intermediates
1704 ; p_cur = p_cur->p_next, i++
1706 char *line = p_cur->line;
1708 err = at_tok_start(&line);
1709 if (err < 0) goto error;
1711 err = at_tok_nextint(&line, &skip);
1712 if (err < 0) goto error;
1714 // If we're unregistered, we may just get
1715 // a "+COPS: 0" response
1716 if (!at_tok_hasmore(&line)) {
1721 err = at_tok_nextint(&line, &skip);
1722 if (err < 0) goto error;
1724 // a "+COPS: 0, n" response is also possible
1725 if (!at_tok_hasmore(&line)) {
1730 err = at_tok_nextstr(&line, &(response[i]));
1731 if (err < 0) goto error;
1742 response[0]=erisystem;
1743 response[1]="Android";
1744 response[2]="310260";
1747 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1748 at_response_free(p_response);
1752 LOGE("requestOperator must not return error when radio is on");
1753 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1754 at_response_free(p_response);
1757 static void requestSendSMS(void *data, size_t datalen, RIL_Token t, int request)
1762 const char *testSmsc;
1763 int tpLayerLength,length,i,plus = 0;
1764 char *cmd1, *cmd2, *line, *temp;
1766 int tosca,curChar=0;
1767 RIL_SMS_Response response;
1768 ATResponse *p_response = NULL;
1769 ATResponse *p2_response = NULL;
1773 RIL_SMS_Response resp;
1777 testSmsc = ((char **)data)[0];
1778 pdu = ((const char **)data)[1];
1780 tpLayerLength = strlen(pdu)/2;
1781 LOGI("SMSC=%s PDU=%s",testSmsc,pdu);
1782 // "NULL for default SMSC"
1783 if (testSmsc == NULL) {
1785 err = at_send_command_singleline("AT+CSCA?", "+CSCA:", &p2_response);
1787 if (err < 0 || p2_response->success == 0) {
1791 line = p2_response->p_intermediates->line;
1793 err = at_tok_start(&line);
1794 if (err < 0) goto error;
1796 err = at_tok_nextstr(&line, &temp);
1797 if (err < 0) goto error;
1799 err = at_tok_nextint(&line, &tosca);
1800 if (err < 0) goto error;
1807 length = strlen(temp) - plus;
1808 sprintf(smsc,"%.2x%.2x",(length + 1) / 2 + 1, tosca);
1810 for (i = 0; curChar < length - 1; i+=2 ) {
1811 smsc[5+i] = temp[plus+curChar++];
1812 smsc[4+i] = temp[plus+curChar++];
1815 if ( length % 2) {//One extra number
1816 smsc[4+length] = temp[curChar];
1818 smsc[5+length]='\0';
1820 smsc[4+length] = '\0';
1822 //first = malloc(30*sizeof(byte_t));
1823 //length = 2 + (gsm_bcdnum_from_ascii(temp,strlen(temp),&first)) / 2;
1824 //sprintf(smsc,"%.2x%.2x%s",length,tosca,first);
1829 strcpy(smsc,testSmsc);
1830 LOGI("SMSC=%s PDU=%s",smsc,pdu);
1833 strcpy(sendstr,"00");
1834 strcat(sendstr,pdu);
1835 LOGI("GSM PDU=%s",pdu);
1836 cdma=gsm_to_cdmapdu(sendstr);
1837 tpLayerLength = strlen(cdma)/2;
1839 asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
1841 asprintf(&cmd2, "%s%s", smsc, pdu);
1843 asprintf(&cmd2, "%s", cdma);
1845 err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
1851 if (err != 0 || p_response->success == 0) goto error;
1853 memset(&response, 0, sizeof(response));
1855 /* FIXME fill in messageRef and ackPDU */
1856 line = p_response->p_intermediates->line;
1857 err = at_tok_start(&line);
1858 if (err < 0) goto error;
1860 err = at_tok_nextint(&line, &response.messageRef);
1861 if (err < 0) goto error;
1863 response.ackPDU = NULL;
1865 if (request == RIL_REQUEST_SEND_SMS_EXTENDED)
1867 extendedResponse.resp = response;
1868 extendedResponse.result = 1;
1869 RIL_onRequestComplete(t, RIL_E_SUCCESS, &extendedResponse, sizeof(extendedResponse));
1873 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
1875 at_response_free(p_response);
1876 at_response_free(p2_response);
1880 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1881 at_response_free(p_response);
1882 at_response_free(p2_response);
1885 static void requestSetupDataCall(char **data, size_t datalen, RIL_Token t)
1893 ATResponse *p_response = NULL;
1894 int fd, pppstatus,i,fd2;
1897 ssize_t written, rlen;
1898 char status[32] = {0};
1902 char *response[3] = { "1", PPP_TTY_PATH, "255.255.255.255" };
1905 apn = ((const char **)data)[2];
1906 user = ((char **)data)[3];
1914 pass = ((char **)data)[4];
1922 LOGD("requesting data connection to APN '%s'\n", apn);
1924 //Make sure there is no existing connection or pppd instance running
1925 if(killConn(response[0]) < 0)
1931 LOGE("Android want us to connect as CDMA while we are a GSM phone !");
1935 LOGE("Android want us to connect as GSM while we are a CDMA phone !");
1938 asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
1939 //FIXME check for error here
1940 err = at_send_command(cmd, NULL);
1942 // Set required QoS params to default
1943 err = at_send_command("AT+CGQREQ=1", NULL);
1944 // Set minimum QoS params to default
1945 err = at_send_command("AT+CGQMIN=1", NULL);
1946 // packet-domain event reporting
1947 err = at_send_command("AT+CGEREP=1,0", NULL);
1948 // Hangup anything that's happening there now
1949 err = at_send_command("AT+CGACT=0,1", NULL);
1950 // Start data on PDP context 1
1951 err = at_send_command("ATD*99***1#", &p_response);
1952 if (err < 0 || p_response->success == 0) {
1953 at_response_free(p_response);
1956 at_response_free(p_response);
1959 err = at_send_command("AT+CFUN=1", NULL);
1960 err = at_send_command("AT+HTC_DUN=0", NULL);
1961 err = at_send_command("ATH", NULL);
1962 err = at_send_command("ATDT#777", &p_response);
1963 if (err < 0 || p_response->success == 0) {
1964 at_response_free(p_response);
1967 at_response_free(p_response);
1970 asprintf(&userpass, "%s * %s\n", user, pass);
1971 len = strlen(userpass);
1972 fd = open("/etc/ppp/pap-secrets",O_WRONLY);
1975 write(fd, userpass, len);
1977 fd = open("/etc/ppp/chap-secrets",O_WRONLY);
1980 write(fd, userpass, len);
1984 pppconfig = fopen("/etc/ppp/options.smd","r");
1989 fseek(pppconfig, 0, SEEK_END);
1990 buffSize = ftell(pppconfig);
1994 buffer = (char *) malloc (sizeof(char)*buffSize);
1998 //read in the original file
1999 len = fread (buffer,1,buffSize,pppconfig);
2000 if (len != buffSize)
2004 pppconfig = fopen("/etc/ppp/options.smd1","w");
2005 fwrite(buffer,1,buffSize,pppconfig);
2006 fprintf(pppconfig,"user %s\n",user);
2010 // The modem replies immediately even if it's not connected!
2011 // so wait a short time.
2013 mypppstatus = system("/bin/pppd /dev/smd1");//Or smd7 ?
2014 if (mypppstatus < 0)
2016 sleep(5); // allow time for ip-up to run
2018 * We are supposed to return IP address in response[2], but this is not used by android currently
2024 ifc_get_info(PPP_TTY_PATH, &addr, &mask, &flags);
2027 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
2031 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2035 static int killConn(char *cid)
2040 ATResponse *p_response = NULL;
2042 while((fd = open("/etc/ppp/ppp-gprs.pid",O_RDONLY)) > 0) {
2044 system("killall pppd");
2053 asprintf(&cmd, "AT+CGACT=0,%s", cid);
2055 err = at_send_command(cmd, &p_response);
2058 if (err < 0 || p_response->success == 0) {
2059 at_response_free(p_response);
2062 at_response_free(p_response);
2065 if (dataCallNum() >= 0) {
2066 err = at_send_command("ATH", &p_response);
2068 if (err < 0 || p_response->success == 0) {
2069 at_response_free(p_response);
2072 at_response_free(p_response);
2081 static void requestDeactivateDataCall(void *data, size_t datalen, RIL_Token t)
2085 cid = ((char **)data)[0];
2086 if (killConn(cid) < 0)
2089 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2093 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2096 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
2101 ackSuccess = ((int *)data)[0];
2103 if (ackSuccess == 1) {
2104 err = at_send_command("AT+CNMA=1", NULL);
2105 } else if (ackSuccess == 0) {
2106 err = at_send_command("AT+CNMA=2", NULL);
2108 LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
2112 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2116 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2120 static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
2122 ATResponse *p_response = NULL;
2123 RIL_SIM_IO_Response sr;
2129 memset(&sr, 0, sizeof(sr));
2131 p_args = (RIL_SIM_IO *)data;
2135 /* FIXME handle pin2 */
2137 if (p_args->data == NULL) {
2138 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
2139 p_args->command, p_args->fileid,
2140 p_args->p1, p_args->p2, p_args->p3);
2142 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
2143 p_args->command, p_args->fileid,
2144 p_args->p1, p_args->p2, p_args->p3, p_args->data);
2147 err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
2149 if (err < 0 || p_response->success == 0) {
2153 line = p_response->p_intermediates->line;
2155 err = at_tok_start(&line);
2156 if (err < 0) goto error;
2158 err = at_tok_nextint(&line, &(sr.sw1));
2159 if (err < 0) goto error;
2161 err = at_tok_nextint(&line, &(sr.sw2));
2162 if (err < 0) goto error;
2164 if (at_tok_hasmore(&line)) {
2165 err = at_tok_nextstr(&line, &(sr.simResponse));
2166 if (err < 0) goto error;
2170 if(p_args->fileid != 0x6f40) {
2171 LOGE("SIM IO Request: %s\n", cmd);
2172 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
2173 at_response_free(p_response);
2176 } else { //Asking for the MSISDN or phone number. 1+ bytes alpha id (leave null), 1 byte length of bcd number (set to 11), 1 byte TON/NPI (set to FF), 10 byte phone num, 1 byte capability id, 1 byte extension id
2180 if(p_args->command == 192)
2181 asprintf(&sr.simResponse,"000000806f40040011a0aa01020120");
2190 err = at_send_command_singleline("AT+CNUM", "+CNUM:", &p_response);
2192 if (err < 0 || p_response->success == 0)
2194 line = p_response->p_intermediates->line;
2196 at_tok_start(&line);
2197 err = at_tok_nextstr(&line, &response);
2200 err = at_tok_nextstr(&line, &response);
2204 if(response[0]=='+')
2207 length = strlen(response) - plus;
2208 asprintf(&msid,"%.2x%.2dFFFFFFFFFFFFFFFFFFFF",(length + 1) / 2 + 1, 81 + plus * 10);
2210 for (i = 0; curChar < length - 1; i+=2 ) {
2211 msid[5+i] = response[plus+curChar++];
2212 msid[4+i] = response[plus+curChar++];
2215 if ( length % 2) //One extra number
2216 msid[4+length] = response[curChar];
2218 asprintf(&sr.simResponse,"ffffffffffffffffffffffffffffffffffff%sffff",msid);
2224 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
2225 at_response_free(p_response);
2230 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2231 at_response_free(p_response);
2236 static void requestEnterSimPin(void* data, size_t datalen, RIL_Token t)
2238 ATResponse *p_response = NULL;
2241 const char** strings = (const char**)data;;
2244 if ( datalen == sizeof(char*) ) {
2245 asprintf(&cmd, "AT+CPIN=\"%s\"", strings[0]);
2246 } else if ( datalen == 2*sizeof(char*) ) {
2247 asprintf(&cmd, "AT+CPIN=\"%s\",\"%s\"", strings[0], strings[1]);
2251 err = at_send_command_singleline(cmd, "+CREG:", &p_response);
2254 if (err < 0 || p_response->success == 0) {
2256 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
2258 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2260 /* Notify that SIM is ready */
2261 setRadioState(RADIO_STATE_SIM_READY);
2264 at_response_free(p_response);
2266 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2267 setRadioState(RADIO_STATE_SIM_READY);
2271 static void requestChangeSimPin(void* data, size_t datalen, RIL_Token t)
2273 ATResponse *p_response = NULL;
2276 const char** strings = (const char**)data;;
2279 if ( datalen == 2*sizeof(char*) )
2280 asprintf(&cmd, "AT+CPWD=\"SC\",\"%s\",\"%s\"", strings[0], strings[1]);
2284 err = at_send_command(cmd, &p_response);
2287 if (err < 0 || p_response->success == 0) {
2289 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
2292 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2294 at_response_free(p_response);
2296 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2301 static void unsolicitedNitzTime(const char * s)
2304 char * response = NULL;
2305 char * line, *origline;
2307 char * tz = NULL; /* Timezone */
2308 origline = line = strdup(s);
2310 /* Higher layers expect a NITZ string in this format:
2311 * 08/10/28,19:08:37-20,1 (yy/mm/dd,hh:mm:ss(+/-)tz,dst)
2314 if(strStartsWith(s,"+CTZV:")){
2316 /* Get Time and Timezone data and store in static variable.
2317 * Wait until DST is received to send response to upper layers
2319 at_tok_start(&line);
2321 err = at_tok_nextstr(&line, &tz);
2322 if (err < 0) goto error;
2324 err = at_tok_nextstr(&line, &response);
2325 if (err < 0) goto error;
2327 snprintf(sNITZtime, sizeof(sNITZtime), "%s%s", response, tz);
2330 else if(strStartsWith(s,"+CTZDST:")){
2332 /* We got DST, now assemble the response and send to upper layers */
2333 at_tok_start(&line);
2335 err = at_tok_nextstr(&line, &tz);
2336 if (err < 0) goto error;
2338 asprintf(&response, "%s,%s", sNITZtime, tz);
2340 RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response));
2344 else if(strStartsWith(s, "+HTCCTZV:")){
2345 at_tok_start(&line);
2347 err = at_tok_nextstr(&line, &response);
2348 if (err < 0) goto error;
2349 RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response));
2356 LOGE("Invalid NITZ line %s\n", s);
2359 static void unsolicitedRSSI(const char * s)
2363 char * line = NULL, *origline;
2364 const unsigned char asu_table[6]={0,2,6,12,25,31};
2366 origline = strdup(s);
2369 err = at_tok_start(&line);
2370 if (err < 0) goto error;
2372 err = at_tok_nextint(&line, &(response[0]));
2373 if (err < 0) goto error;
2375 response[0]=asu_table[response[0]%6];
2378 signalStrength[0]=response[0];
2379 signalStrength[1]=response[1];
2382 RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, response, sizeof(response));
2386 /* The notification was for a battery event - do not send a msg to upper layers */
2390 static void requestNotSupported(RIL_Token t, int request)
2392 LOGD("Request %d is unsupported", request);
2393 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
2397 static void requestOEMHookRaw(void *data, size_t datalen, RIL_Token t)
2399 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
2403 static void requestQueryCallWaiting(void *data, size_t datalen, RIL_Token t)
2405 ATResponse *p_response = NULL;
2412 class = ((int *)data)[0];
2414 asprintf(&cmd, "AT+CCWA=1,2,%d",class);
2416 err = at_send_command_singleline(cmd, "+CCWA:", &p_response);
2418 if (err < 0 || p_response->success == 0) goto error;
2420 line = p_response->p_intermediates->line;
2422 err = at_tok_start(&line);
2423 if (err < 0) goto error;
2425 err = at_tok_nextint(&line, &(response[0]));
2426 if (err < 0) goto error;
2428 if (at_tok_hasmore(&line)) {
2429 err = at_tok_nextint(&line, &(response[1]));
2430 if (err < 0) goto error;
2433 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
2434 at_response_free(p_response);
2439 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2440 at_response_free(p_response);
2444 static void requestSetCallWaiting(void *data, size_t datalen, RIL_Token t)
2446 ATResponse *p_response = NULL;
2451 if((datalen<2)||(data==NULL)) goto error;
2453 enabled = ((int *)data)[0];
2454 class = ((int *)data)[1];
2456 asprintf(&cmd, "AT+CCWA=0,%d,%d",enabled,class);
2458 err = at_send_command(cmd, NULL);
2460 if (err < 0 ) goto error;
2462 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2463 at_response_free(p_response);
2468 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2469 at_response_free(p_response);
2473 static void requestQueryCallForwardStatus(RIL_Token t)
2479 ATResponse *p_response = NULL;
2481 RIL_CallForwardInfo **responses = NULL;
2484 err = at_send_command_multiline("AT+CCFC=0,2", "+CCFC:", &p_response);
2486 if(err != 0 || p_response->success == 0)
2489 for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next)
2492 responses = alloca(n * sizeof(RIL_CallForwardInfo *));
2494 for(i = 0; i < n; i++) {
2495 responses[i] = alloca(sizeof(RIL_CallForwardInfo));
2496 responses[i]->status = 0;
2497 responses[i]->reason = 0;
2498 responses[i]->serviceClass = 0;
2499 responses[i]->toa = 0;
2500 responses[i]->number = "";
2501 responses[i]->timeSeconds = 0;
2504 for (i = 0,p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) {
2505 char *line = p_cur->line;
2507 err = at_tok_start(&line);
2508 if (err < 0) goto error;
2510 err = at_tok_nextint(&line, &(responses[i]->status));
2511 if (err < 0) goto error;
2513 err = at_tok_nextint(&line, &(responses[i]->serviceClass));
2514 if (err < 0) goto error;
2516 if(!at_tok_hasmore(&line)) continue;
2518 err = at_tok_nextstr(&line, &(responses[i]->number));
2519 if (err < 0) goto error;
2521 if(!at_tok_hasmore(&line)) continue;
2523 err = at_tok_nextint(&line, &(responses[i]->toa));
2524 if (err < 0) goto error;
2526 if(!at_tok_hasmore(&line)) continue;
2527 at_tok_nextint(&line,&tmp);
2529 if(!at_tok_hasmore(&line)) continue;
2530 at_tok_nextint(&line,&tmp);
2532 if(!at_tok_hasmore(&line)) continue;
2533 err = at_tok_nextint(&line, &(responses[i]->timeSeconds));
2534 if (err < 0) goto error;
2538 at_response_free(p_response);
2539 RIL_onRequestComplete(t, RIL_E_SUCCESS, responses, sizeof(RIL_CallForwardInfo **));
2543 at_response_free(p_response);
2544 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2547 static void requestSetCallForward(void *data, RIL_Token t)
2551 RIL_CallForwardInfo *info = NULL;
2553 info = ((RIL_CallForwardInfo *) data);
2555 if(data == NULL) goto error;
2557 asprintf(&cmd, "AT+CCFC = %d, %d, \"%s\"",
2558 info->reason, info->status,
2561 err = at_send_command(cmd, NULL);
2563 if (err < 0 ) goto error;
2565 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2570 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2574 static void requestGetCLIR(void *data, size_t datalen, RIL_Token t)
2576 /* Even though data and datalen must be NULL and 0 respectively this
2577 * condition is not verified
2579 ATResponse *p_response = NULL;
2584 err = at_send_command_singleline("AT+CLIR?", "+CLIR:", &p_response);
2586 if (err < 0 || p_response->success == 0) goto error;
2588 line = p_response->p_intermediates->line;
2589 err = at_tok_start(&line);
2590 if (err < 0) goto error;
2592 err = at_tok_nextint(&line, &(response[0]));
2593 if (err < 0) goto error;
2595 err = at_tok_nextint(&line, &(response[1]));
2596 if (err < 0) goto error;
2598 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
2599 at_response_free(p_response);
2603 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2604 at_response_free(p_response);
2607 static void requestSetCLIR(void *data, size_t datalen, RIL_Token t)
2612 asprintf(&cmd, "AT+CLIR=%d", ((int *)data)[0]);
2614 err = at_send_command(cmd, NULL);
2618 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
2620 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2623 static void requestSendSMSExpectMore(void *data, size_t datalen, RIL_Token t)
2626 asprintf(&cmd, "AT+CMMS=1");
2627 at_send_command(cmd, NULL);
2629 requestSendSMS(data, datalen, t, 0);
2632 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
2634 ATResponse *p_response = NULL;
2637 cbytes_t ussdRequest;
2640 char *newUSSDRequest;
2642 ussdRequest = (cbytes_t)(data);
2643 temp = malloc(strlen((char *)ussdRequest)*sizeof(char)+1);
2644 len = utf8_to_gsm8(ussdRequest,strlen((char *)ussdRequest),temp);
2645 newUSSDRequest = malloc(2*len*sizeof(char)+1);
2646 gsm_hex_from_bytes(newUSSDRequest,temp, len);
2647 newUSSDRequest[2*len]='\0';
2648 asprintf(&cmd, "AT+CUSD=1,\"%s\",15", newUSSDRequest);
2649 free(newUSSDRequest);
2651 err = at_send_command(cmd, &p_response);
2653 if (err < 0 || p_response->success == 0) {
2656 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2658 at_response_free(p_response);
2660 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
2665 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2668 static void unsolicitedUSSD(const char *s)
2670 char *line, *linestart;
2671 int typeCode, count, err, len;
2673 char *outputmessage;
2674 char *responseStr[2];
2676 LOGD("unsolicitedUSSD %s\n",s);
2678 linestart=line=strdup(s);
2679 err = at_tok_start(&line);
2680 if(err < 0) goto error;
2682 err = at_tok_nextint(&line, &typeCode);
2683 if(err < 0) goto error;
2685 if(at_tok_hasmore(&line)) {
2686 err = at_tok_nextstr(&line, &message);
2687 if(err < 0) goto error;
2688 outputmessage = malloc(strlen(message)*2+1);
2689 gsm_hex_to_bytes((cbytes_t)message,strlen(message),(bytes_t)outputmessage);
2690 responseStr[1] = malloc(strlen(outputmessage)*2+1);
2691 len = utf8_from_gsm8((cbytes_t)outputmessage,strlen(outputmessage),(bytes_t)responseStr[1]);
2692 responseStr[1][strlen(message)/2]='\0';
2693 free(outputmessage);
2696 responseStr[1]=NULL;
2700 asprintf(&responseStr[0], "%d", typeCode);
2702 RIL_onUnsolicitedResponse (RIL_UNSOL_ON_USSD, responseStr, count*sizeof(char*));
2707 LOGE("unexpectedUSSD error\n");
2710 static void unsolicitedERI(const char *s) {
2711 char *line, *origline;
2715 origline = strdup(s);
2717 at_tok_start(&line);
2719 at_tok_nextint(&line, &temp);
2720 at_tok_nextint(&line, &temp);
2721 at_tok_nextint(&line, &temp);
2722 at_tok_nextint(&line, &temp);
2723 at_tok_nextint(&line, &temp);
2724 at_tok_nextint(&line, &temp);
2725 at_tok_nextint(&line, &temp);
2726 at_tok_nextstr(&line, &newEri);
2728 if(strlen(newEri)<50)
2729 strcpy(erisystem,newEri);
2734 static void requestSetFacilityLock(void *data, size_t datalen, RIL_Token t)
2736 /* It must be tested if the Lock for a particular class can be set without
2737 * modifing the values of the other class. If not, first must call
2738 * requestQueryFacilityLock to obtain the previus value
2744 char *password = NULL;
2747 assert (datalen >= (4 * sizeof(char **)));
2749 code = ((char **)data)[0];
2750 lock = ((char **)data)[1];
2751 password = ((char **)data)[2];
2752 class = ((char **)data)[3];
2754 asprintf(&cmd, "AT+CLCK=\"%s\",%s,\"%s\",%s", code, lock, password, class);
2755 err = at_send_command(cmd, NULL);
2756 if (err < 0) goto error;
2759 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2763 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2766 static void requestChangeBarringPassword(void *data, size_t datalen, RIL_Token t)
2770 char *string = NULL;
2771 char *old_password = NULL;
2772 char *new_password = NULL;
2774 assert (datalen >= (3 * sizeof(char **)));
2776 string = ((char **)data)[0];
2777 old_password = ((char **)data)[1];
2778 new_password = ((char **)data)[2];
2780 asprintf(&cmd, "AT+CPWD=\"%s\",\"%s\",\"%s\"", string, old_password, new_password);
2781 err = at_send_command(cmd, NULL);
2785 if (err < 0) goto error;
2787 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2791 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2794 static void requestSetNetworkSelectionManual(void *data, size_t datalen, RIL_Token t)
2796 char *operator = NULL;
2799 ATResponse *p_response = NULL;
2801 operator = (char *)data;
2802 asprintf(&cmd, "AT+COPS=1,2,\"%s\"", operator);
2803 err = at_send_command(cmd, &p_response);
2804 if (err < 0 || p_response->success == 0){
2805 err = at_send_command("AT+COPS=0", NULL);
2806 if(err < 0) goto error;
2809 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2810 at_response_free(p_response);
2815 at_response_free(p_response);
2816 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2819 static void requestQueryCLIP(void *data, size_t datalen, RIL_Token t)
2821 ATResponse *p_response = NULL;
2826 err = at_send_command_singleline("AT+CLIP?","+CLIP:",&p_response);
2827 if(err < 0 || p_response->success == 0) goto error;
2829 line = p_response->p_intermediates->line;
2830 err = at_tok_start(&line);
2831 if(err < 0) goto error;
2833 /* The first number is discarded */
2834 err = at_tok_nextint(&line, &response);
2835 if(err < 0) goto error;
2837 err = at_tok_nextint(&line, &response);
2838 if(err < 0) goto error;
2840 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
2841 at_response_free(p_response);
2845 at_response_free(p_response);
2846 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2849 static void requestResetRadio(RIL_Token t)
2853 err = at_send_command("AT+CFUN=16", NULL);
2855 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2857 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2862 static void requestSetSuppSVCNotification(void *data, size_t datalen, RIL_Token t)
2867 enabled = ((int *)data)[0];
2869 asprintf(&cmd, "AT+CSSN=%d,%d", enabled, enabled);
2870 err = at_send_command(cmd,NULL);
2873 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2875 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2878 static void requestExplicitCallTransfer(RIL_Token t)
2881 err = at_send_command("AT+CHLD=4",NULL);
2883 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2885 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2888 static void requestSetLocationUpdates(void *data, size_t datalen, RIL_Token t)
2893 ATResponse *p_response = NULL;
2894 updates = ((int *)data)[0] == 1? 2 : 2;
2896 asprintf(&cmd, "AT+CREG=%d", updates);
2898 err = at_send_command_singleline(cmd,"+CLIP:",&p_response);
2899 //if(err < 0 || p_response->success == 0) goto error;
2901 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2902 at_response_free(p_response);
2906 at_response_free(p_response);
2907 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2910 static void requestSTKGetprofile(RIL_Token t)
2913 int responselen = 0;
2914 ATResponse *p_response = NULL;
2915 char *response = NULL;
2918 err = at_send_command_singleline("AT+STKPROF?", "+STKPROF:", &p_response);
2920 if(err < 0 || p_response->success == 0) goto error;
2922 line = p_response->p_intermediates->line;
2923 err = at_tok_start(&line);
2924 if(err < 0) goto error;
2926 err = at_tok_nextint(&line, &responselen);
2927 if(err < 0) goto error;
2929 err = at_tok_nextstr(&line, &response);
2930 if(err < 0) goto error;
2932 at_response_free(p_response);
2933 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, responselen * sizeof(char));
2937 at_response_free(p_response);
2938 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2942 static void requestSTKSetProfile(void * data, size_t datalen, RIL_Token t)
2946 char *profile = NULL;
2949 profile = (char *)data;
2950 length = strlen(profile);
2951 asprintf(&cmd, "AT+STKPROF=%d,\"%s\"", length, profile);
2953 err = at_send_command(cmd, NULL);
2956 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2958 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2962 static void requestLastFailCause(RIL_Token t)
2964 ATResponse *p_response = NULL;
2970 err = at_send_command_singleline("AT+CEER", "+CEER:", &p_response);
2971 if(err < 0 || p_response->success == 0) goto error;
2973 line = p_response->p_intermediates->line;
2974 err = at_tok_start(&line);
2975 if(err < 0) goto error;
2977 err = at_tok_nextstr(&line, &tmp);
2978 if(err < 0) goto error;
2980 err = at_tok_nextint(&line, &response);
2981 if(err < 0) goto error;
2983 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
2984 at_response_free(p_response);
2988 at_response_free(p_response);
2989 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2992 static void requestHangupWaitingOrBackground(RIL_Token t)
2994 // 3GPP 22.030 6.5.5
2995 // "Releases all held calls or sets User Determined User Busy
2996 // (UDUB) for a waiting call."
2997 at_send_command("AT+CHLD=0", NULL);
2999 /* success or failure is ignored by the upper layer here.
3000 it will call GET_CURRENT_CALLS and determine success that way */
3001 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3004 static void requestHangupForegroundResumeBackground(RIL_Token t)
3006 // 3GPP 22.030 6.5.5
3007 // "Releases all active calls (if any exist) and accepts
3008 // the other (held or waiting) call."
3009 at_send_command("AT+CHLD=1", NULL);
3010 // writesys("audio","5");
3012 /* success or failure is ignored by the upper layer here.
3013 it will call GET_CURRENT_CALLS and determine success that way */
3014 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3017 static void requestSwitchWaitingOrHoldingAndActive(RIL_Token t)
3019 // 3GPP 22.030 6.5.5
3020 // "Places all active calls (if any exist) on hold and accepts
3021 // the other (held or waiting) call."
3023 at_send_command("AT+CHLD=2", NULL);
3025 at_send_command("AT+HTC_SENDFLASH", NULL);
3027 #ifdef WORKAROUND_ERRONEOUS_ANSWER
3029 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
3031 /* success or failure is ignored by the upper layer here.
3032 it will call GET_CURRENT_CALLS and determine success that way */
3033 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3036 static void requestAnswer(RIL_Token t)
3038 at_send_command("ATA", NULL);
3039 writesys("audio","2");
3041 #ifdef WORKAROUND_ERRONEOUS_ANSWER
3043 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
3045 /* success or failure is ignored by the upper layer here.
3046 it will call GET_CURRENT_CALLS and determine success that way */
3047 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3050 static void requestConference(RIL_Token t)
3052 // 3GPP 22.030 6.5.5
3053 // "Adds a held call to the conversation"
3054 at_send_command("AT+CHLD=3", NULL);
3056 /* success or failure is ignored by the upper layer here.
3057 it will call GET_CURRENT_CALLS and determine success that way */
3058 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3061 static void requestUDUB(RIL_Token t)
3063 /* user determined user busy */
3064 /* sometimes used: ATH */
3065 at_send_command("ATH", NULL);
3067 /* success or failure is ignored by the upper layer here.
3068 it will call GET_CURRENT_CALLS and determine success that way */
3069 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3073 static void requestSeparateConnection(void * data, size_t datalen, RIL_Token t)
3076 int party = ((int*)data)[0];
3078 // Make sure that party is in a valid range.
3079 // (Note: The Telephony middle layer imposes a range of 1 to 7.
3080 // It's sufficient for us to just make sure it's single digit.)
3081 if (party > 0 && party < 10){
3082 sprintf(cmd, "AT+CHLD=2%d", party);