Sync froyo ril blob from hyc's codebase.
[xdandroid:rootfs.git] / htcgeneric-ril.c
1 /* //device/system/htcgeneric-ril/htcgeneric-ril.c
2  **
3  ** Copyright 2006, The Android Open Source Project
4  **
5  ** Licensed under the Apache License, Version 2.0 (the "License");
6  ** you may not use this file except in compliance with the License.
7  ** You may obtain a copy of the License at
8  **
9  **     http://www.apache.org/licenses/LICENSE-2.0
10  **
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  */
17
18 #include <telephony/ril.h>
19 #include <stdio.h>
20 #include <assert.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <pthread.h>
28 #include <alloca.h>
29 #include "atchannel.h"
30 #include "at_tok.h"
31 #include "misc.h"
32 #include "gsm.h"
33 #include <getopt.h>
34 #include <sys/socket.h>
35 #include <cutils/sockets.h>
36 #include <termios.h>
37
38 #define LOG_NDEBUG 0
39 #define LOG_TAG "RIL"
40 #include <utils/Log.h>
41
42 #define MAX_AT_RESPONSE 0x1000
43
44 #define RIL_REQUEST_SEND_SMS_EXTENDED 512
45
46 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
47 #define PPP_TTY_PATH "ppp0"
48
49 #ifdef USE_TI_COMMANDS
50
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
57
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
61 #endif
62
63 typedef enum {
64         SIM_ABSENT = 0,
65         SIM_NOT_READY = 1,
66         SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
67         SIM_PIN = 3,
68         SIM_PUK = 4,
69         SIM_NETWORK_PERSONALIZATION = 5
70 } SIM_Status;
71
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);
83
84
85 extern const char * requestToString(int request);
86
87 /*** Static Variables ***/
88 static const RIL_RadioFunctions s_callbacks = {
89         RIL_VERSION,
90         onRequest,
91         currentState,
92         onSupports,
93         onCancel,
94         getVersion
95 };
96
97 #ifdef RIL_SHLIB
98 static const struct RIL_Env *s_rilenv;
99
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)
103 #endif
104
105 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
106
107 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
108 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
109
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;
115
116 /* trigger change to this with s_state_cond */
117 static int s_closed = 0;
118
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)
124          */
125 static char sNITZtime[sizeof("08/10/28,19:08:37-20,1")+4];
126
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};
130
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
135
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 */
143
144 static void pollSIMState (void *param);
145 static void setRadioState(RIL_RadioState newState);
146
147 static int isgsm=0;
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];
153
154 static void handle_cdma_ccwa (const char *s)
155 {
156         int err;
157         char *line, *tmp;
158
159         if (callwaiting_num)
160         {
161                 free(callwaiting_num);
162                 callwaiting_num = NULL;
163         }
164         line = tmp = strdup(s);
165         err = at_tok_start(&tmp);
166         if (err)
167                 goto out;
168         err = at_tok_nextstr(&tmp, &callwaiting_num);
169         if (err)
170                 goto out;
171         callwaiting_num = strdup(callwaiting_num);
172         LOGE("successfully set callwaiting_numn");
173 out:
174         free(line);
175 }
176
177 extern char** cdma_to_gsmpdu(const char *);
178 extern char* gsm_to_cdmapdu(const char *);
179 extern int hex2int(const char);
180
181 static void HexStr_to_DecInt(char *strings, unsigned int *ints)
182 {
183         int i = 0;
184         int j = strlen(strings);
185         int k = 0;
186         for(i = 0, k = 0; i < j; i += 2, k++)
187         {
188                 printf("%d, %d\n", i, k);
189                 if(strings[i] <= 57){
190                         *(ints + k) += (unsigned int)((strings[i] - 48) * 16);
191                 }
192                 else{
193                         *(ints+k) += (unsigned int)(((strings[i] - 97) + 10) * 16);
194                 }
195
196                 if(strings[i+1] <= 57){
197                         *(ints+k) += (unsigned int)(strings[i+1] - 48);
198                 }
199                 else{
200                         *(ints+k) += (unsigned int)((strings[i+1] - 97) + 10);
201                 }
202         }
203 }
204
205 static int clccStateToRILState(int state, RIL_CallState *p_state)
206
207 {
208         switch(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;
215                 default: return -1;
216         }
217 }
218
219 static const char* networkStatusToRilString(int state)
220 {
221         switch(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;
227         }
228 }
229
230 // some phone functions are controlled by msm_proc_comm through /sys
231 void writesys(char *name, char *val) {
232         FILE *fout;
233         char filename[256];
234         strcpy(filename,"/sys/class/vogue_hw/");
235         strcat(filename,name);
236         fout=fopen(filename,"w");
237         if(!fout) return;
238         fprintf(fout, "%s", val);
239         fclose(fout);
240 }
241 /**
242  * Note: directly modified line and has *p_call point directly into
243  * modified line
244  */
245 static int callFromCLCCLine(char *line, RIL_Call *p_call)
246 {
247         //+CLCC: 1,0,2,0,0,\"+18005551212\",145
248         //     index,isMT,state,mode,isMpty(,number,TOA)?
249
250         int err;
251         int state;
252         int mode;
253
254         err = at_tok_start(&line);
255         if (err < 0) goto error;
256
257         err = at_tok_nextint(&line, &(p_call->index));
258         if (err < 0) goto error;
259
260         err = at_tok_nextbool(&line, &(p_call->isMT));
261         if (err < 0) goto error;
262
263         err = at_tok_nextint(&line, &state);
264         if (err < 0) goto error;
265
266         err = clccStateToRILState(state, &(p_call->state));
267         if (err < 0) goto error;
268
269         err = at_tok_nextint(&line, &mode);
270         if (err < 0) goto error;
271
272         p_call->isVoice = (mode == 0);
273
274         err = at_tok_nextbool(&line, &(p_call->isMpty));
275         if (err < 0) goto error;
276
277         if (at_tok_hasmore(&line)) {
278                 err = at_tok_nextstr(&line, &(p_call->number));
279
280                 /* tolerate null here */
281                 if (err < 0) return 0;
282
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")
287                    ) {
288                         p_call->number = NULL;
289                 }
290
291                 err = at_tok_nextint(&line, &p_call->toa);
292                 if (err < 0) goto error;
293         }
294
295         return 0;
296
297 error:
298         LOGE("invalid CLCC line\n");
299         return -1;
300 }
301
302 //returns the call number of the active data call, or -1 if no active call
303 static int dataCallNum()
304 {
305         int err;
306         ATResponse *p_response;
307         ATLine *p_cur;
308         int countCalls;
309         RIL_Call *p_call;
310         int i;
311         int callNumber = -1;
312
313         if(currentState() != RADIO_STATE_SIM_READY){
314                 return -1;
315         }
316
317         err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
318
319         if (err != 0 || p_response->success == 0) {
320                 return -1;
321         }
322
323         /* count the calls */
324         for (countCalls = 0, p_cur = p_response->p_intermediates
325                         ; p_cur != NULL
326                         ; p_cur = p_cur->p_next
327             ) {
328                 countCalls++;
329         }
330
331         p_call = (RIL_Call *)alloca(sizeof(RIL_Call));
332         memset (p_call, 0, sizeof(RIL_Call));
333
334         for (i = 0, p_cur = p_response->p_intermediates
335                         ; p_cur != NULL
336                         ; p_cur = p_cur->p_next
337             ) {
338                 err = callFromCLCCLine(p_cur->line, p_call);
339
340                 if (err != 0) {
341                         continue;
342                 }
343
344                 if(p_call[0].isVoice == 0) // only count data calls
345                 {
346                         callNumber = i;
347                 }
348         }
349         return callNumber;
350 }
351
352
353 /** do post-AT+CFUN=1 initialization */
354 static void onRadioPowerOn()
355 {
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 */
360
361         at_send_command("AT%CPHS=1", NULL);
362
363         /*  TI specific -- enable NITZ unsol notifs */
364         at_send_command("AT%CTZV=1", NULL);
365 #endif
366         if(isgsm)
367         {
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);
373
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);
382         }
383         pollSIMState(NULL);
384 }
385
386 /** do post- SIM ready initialization */
387 static void onSIMReady()
388 {
389         /* Common initialization commands */
390
391         /* Network registration */
392         at_send_command("AT+COPS=0", NULL);
393
394         if(isgsm) {
395                 /* Preferred RAT - UMTS Dualmode */
396 //              at_send_command("AT+XRAT=1,2", NULL);
397
398                 //debug what type of sim is it?
399                 at_send_command("AT+SIMTYPE", NULL);
400
401                 /*
402                  * Always send SMS messages directly to the TE
403                  *
404                  * mode = 1 // discard when link is reserved (link should never be
405                  *             reserved)
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
410                  */
411                 at_send_command("AT+CNMI=1,2,2,1,1", NULL);
412
413                 at_send_command("AT+CSCB=1", NULL);
414
415                 /*  Enable +CGEV GPRS event notifications, but don't buffer */
416 //              at_send_command("AT+CGEREP=1,0", NULL);
417
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);
422
423                 /* Enable unsolizited RSSI reporting */
424                 at_send_command("AT@HTCCSQ=1", NULL);
425
426                 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
427
428
429         } else {
430
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);
434         }
435 }
436
437 static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
438 {
439         int onOff;
440
441         int err;
442         ATResponse *p_response = NULL;
443
444         assert (datalen >= sizeof(int *));
445         onOff = ((int *)data)[0];
446
447         if (onOff == 0 && sState != RADIO_STATE_OFF) {
448                 if(isgsm || is_world_cdma)
449                         err = at_send_command("AT+CFUN=0", &p_response);
450                 else
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
460                         // turned on anyway
461
462                         if (isRadioOn() != 1) {
463                                 goto error;
464                         }
465                 }
466                 setRadioState(RADIO_STATE_SIM_NOT_READY);
467         }
468
469         at_response_free(p_response);
470         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
471         return;
472
473 error:
474         at_response_free(p_response);
475         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
476 }
477
478 static void requestOrSendDataCallList(RIL_Token *t);
479
480 static void onDataCallListChanged(void *param)
481 {
482         requestOrSendDataCallList(NULL);
483 }
484
485 static void requestDataCallList(void *data, size_t datalen, RIL_Token t)
486 {
487         requestOrSendDataCallList(&t);
488 }
489
490 static void requestOrSendDataCallList(RIL_Token *t)
491 {
492         ATResponse *p_response;
493         ATLine *p_cur;
494         RIL_Data_Call_Response *responses;
495         int err;
496         char status[1];
497         int fd;
498         int n = 0;
499         char *out;
500
501         if (isgsm) {
502                 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
503                 if (err != 0 || p_response->success == 0) {
504                         if (t != NULL)
505                                 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
506                         else
507                                 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
508                                                 NULL, 0);
509                         return;
510                 }
511
512                 for (p_cur = p_response->p_intermediates; p_cur != NULL;
513                                 p_cur = p_cur->p_next)
514                         n++;
515
516                 responses = alloca(n * sizeof(RIL_Data_Call_Response));
517
518                 int i;
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 = "";
525                 }
526
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;
531
532                         err = at_tok_start(&line);
533                         if (err < 0)
534                                 goto error;
535
536                         err = at_tok_nextint(&line, &response->cid);
537                         if (err < 0)
538                                 goto error;
539
540                         err = at_tok_nextint(&line, &response->active);
541                         if (err < 0)
542                                 goto error;
543
544                         response++;
545                 }
546
547                 at_response_free(p_response);
548
549                 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
550                 if (err != 0 || p_response->success == 0) {
551                         if (t != NULL)
552                                 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
553                         else
554                                 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
555                                                 NULL, 0);
556                         return;
557                 }
558
559                 for (p_cur = p_response->p_intermediates; p_cur != NULL;
560                                 p_cur = p_cur->p_next) {
561                         char *line = p_cur->line;
562                         int cid;
563                         char *type;
564                         char *apn;
565                         char *address;
566
567
568                         err = at_tok_start(&line);
569                         if (err < 0)
570                                 goto error;
571
572                         err = at_tok_nextint(&line, &cid);
573                         if (err < 0)
574                                 goto error;
575
576                         for (i = 0; i < n; i++) {
577                                 if (responses[i].cid == cid)
578                                         break;
579                         }
580
581                         if (i >= n) {
582                                 /* details for a context we didn't hear about in the last request */
583                                 continue;
584                         }
585
586                         err = at_tok_nextstr(&line, &out);
587                         if (err < 0)
588                                 goto error;
589
590                         responses[i].type = alloca(strlen(out) + 1);
591                         strcpy(responses[i].type, out);
592
593                         err = at_tok_nextstr(&line, &out);
594                         if (err < 0)
595                                 goto error;
596
597                         responses[i].apn = alloca(strlen(out) + 1);
598                         strcpy(responses[i].apn, out);
599
600                         err = at_tok_nextstr(&line, &out);
601                         if (err < 0)
602                                 goto error;
603
604                         responses[i].address = alloca(strlen(out) + 1);
605                         strcpy(responses[i].address, out);
606                 }
607
608                 at_response_free(p_response);
609
610         } else {
611                 //CDMA
612                 n = 1;
613                 responses = alloca(sizeof(RIL_Data_Call_Response));
614
615                 responses[0].cid = 1;
616                 if (dataCallNum() >= 0)
617                         responses[0].active = 1;
618                 else
619                         responses[0].active = 0;
620                 responses[0].type = "";
621                 responses[0].apn = "internet";
622                 responses[0].address = "";
623         }
624
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)
627         {
628                 close(fd);
629         }
630         else
631         {
632                 responses[0].active = 0;
633         }
634
635         if (t != NULL)
636                 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
637                                 n * sizeof(RIL_Data_Call_Response));
638         else
639                 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
640                                 responses,
641                                 n * sizeof(RIL_Data_Call_Response));
642
643         return;
644
645 error:
646         if (t != NULL)
647                 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
648         else
649                 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
650                                 NULL, 0);
651
652         at_response_free(p_response);
653 }
654
655 static void requestBasebandVersion(void *data, size_t datalen, RIL_Token t)
656 {
657         int err;
658         ATResponse *p_response = NULL;
659         char * response = NULL;
660         char* line = NULL;
661
662         if (isgsm) {
663                 err = at_send_command_singleline("AT+CGMM", "", &p_response);
664                 if (err != 0) goto error;
665
666                 line = p_response->p_intermediates->line;
667
668                 response = (char *)alloca(sizeof(char *));
669
670                 err = at_tok_nextstr(&line, &response);
671                 if (err < 0) goto error;
672
673                 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char *));
674                 at_response_free(p_response);
675         } else {
676                 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
677         }
678         return;
679
680 error:
681         at_response_free(p_response);
682         LOGE("ERROR: requestBasebandVersion failed\n");
683         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
684 }
685
686
687 static void requestQueryNetworkSelectionMode(
688                 void *data, size_t datalen, RIL_Token t)
689 {
690         int err;
691         ATResponse *p_response = NULL;
692         int response = 0;
693         char *line;
694
695         if(isgsm) { //this command conflicts with the network status command
696                 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
697
698                 if (err < 0 || p_response->success == 0) {
699                         goto error;
700                 }
701
702                 line = p_response->p_intermediates->line;
703
704                 err = at_tok_start(&line);
705
706                 if (err < 0) {
707                         goto error;
708                 }
709
710                 err = at_tok_nextint(&line, &response);
711
712                 if (err < 0) {
713                         goto error;
714                 }
715         }
716
717         RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
718         at_response_free(p_response);
719         return;
720
721 error:
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);
725 }
726
727 static void requestQueryAvailableNetworks(void *data, size_t datalen, RIL_Token t)
728 {
729         /* We expect an answer on the following form:
730            +COPS: (2,"AT&T","AT&T","310410",0),(1,"T-Mobile ","TMO","310260",0)
731          */
732
733         int err, operators, i, skip, status;
734         ATResponse *p_response = NULL;
735         char * c_skip, *line, *p = NULL;
736         char ** response = NULL;
737
738         err = at_send_command_singleline("AT+COPS=?", "+COPS:", &p_response);
739
740         if (err != 0) goto error;
741
742         line = p_response->p_intermediates->line;
743
744         err = at_tok_start(&line);
745         if (err < 0) goto error;
746
747         /* Count number of '(' in the +COPS response to get number of operators*/
748         operators = 0;
749         for (p = line ; *p != '\0' ;p++) {
750                 if (*p == '(') operators++;
751         }
752
753         response = (char **)alloca(operators * 4 * sizeof(char *));
754
755         for (i = 0 ; i < operators ; i++ )
756         {
757                 err = at_tok_nextstr(&line, &c_skip);
758                 if (err < 0) goto error;
759                 if (strcmp(c_skip,"") == 0)
760                 {
761                         operators = i;
762                         continue;
763                 }
764                 status = atoi(&c_skip[1]);
765                 response[i*4+3] = (char*)networkStatusToRilString(status);
766
767                 err = at_tok_nextstr(&line, &(response[i*4+0]));
768                 if (err < 0) goto error;
769
770                 err = at_tok_nextstr(&line, &(response[i*4+1]));
771                 if (err < 0) goto error;
772
773                 err = at_tok_nextstr(&line, &(response[i*4+2]));
774                 if (err < 0) goto error;
775
776                 err = at_tok_nextstr(&line, &c_skip);
777
778                 if (err < 0) goto error;
779         }
780
781         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, (operators * 4 * sizeof(char *)));
782         at_response_free(p_response);
783         return;
784
785 error:
786         at_response_free(p_response);
787         LOGE("ERROR - requestQueryAvailableNetworks() failed");
788         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
789 }
790
791 static void requestGetPreferredNetworkType(void *data, size_t datalen, RIL_Token t)
792 {
793         int err;
794         ATResponse *p_response = NULL;
795         int response = 0;
796         char *line;
797
798         if(isgsm)
799         {
800                 err = at_send_command_singleline("AT+CGAATT?", "+CGAATT:", &p_response);
801
802                 if (err < 0 || p_response->success == 0) {
803                         goto error;
804                 }
805
806                 line = p_response->p_intermediates->line;
807
808                 err = at_tok_start(&line);
809
810                 if (err < 0) {
811                         goto error;
812                 }
813
814                 // Get third int in response
815                 err = at_tok_nextint(&line, &response);
816                 if (err < 0) {
817                         goto error;
818                 }
819                 err = at_tok_nextint(&line, &response);
820                 if (err < 0) {
821                         goto error;
822                 }
823                 err = at_tok_nextint(&line, &response);
824                 if (err < 0) {
825                         goto error;
826                 }
827                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
828                 at_response_free(p_response);
829                 return;
830         }
831         LOGE("ERROR: requestGetPreferredNetworkType() failed - modem does not support command\n");
832         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
833         return;
834 error:
835         at_response_free(p_response);
836         LOGE("ERROR: requestGetPreferredNetworkType() failed\n");
837         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
838 }
839
840 static void requestSetPreferredNetworkType(void *data, size_t datalen, RIL_Token t)
841 {
842         int err, rat;
843         ATResponse *p_response = NULL;
844         char * cmd = NULL;
845         const char *at_rat = NULL;
846
847         if(isgsm)
848         {
849         assert (datalen >= sizeof(int *));
850         rat = ((int *)data)[0];
851
852 #ifdef USE_IDCC_MODEM
853         switch (rat)
854         {
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 */
858         }
859
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;
863
864         asprintf(&cmd, "AT+XRAT=%s", at_rat);
865 #else
866         LOGD("In requestSetPreferredNetworkType RAPH");
867         switch (rat) {
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 */
871         }
872
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;
877
878         asprintf(&cmd, "AT+CGAATT=%s", at_rat);
879
880 #endif /* USE_IDCC_MODEM */
881         err = at_send_command(cmd, &p_response);
882         free(cmd);
883
884         if (err < 0|| p_response->success == 0) {
885                 goto error;
886         }
887
888         /* Register on the NW again */
889         err = at_send_command("AT+COPS=0", NULL);
890         if (err < 0) goto error;
891
892         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, sizeof(int));
893         at_response_free(p_response);
894         return;
895         }
896         LOGE("ERROR: requestSetPreferredNetworkType() failed - command not supported by modem\n");
897         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
898         return;
899 error:
900         at_response_free(p_response);
901         LOGE("ERROR: requestSetPreferredNetworkType() failed\n");
902         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
903 }
904
905
906 static void requestQueryFacilityLock(void *data, size_t datalen, RIL_Token t)
907 {
908         int err, rat, response;
909         ATResponse *p_response = NULL;
910         char * cmd = NULL;
911         char * line = NULL;
912         char * facility_string = NULL;
913         char * facility_password = NULL;
914         char * facility_class = NULL;
915
916         LOGD("FACILITY");
917         assert (datalen >=  (3 * sizeof(char **)));
918
919         facility_string   = ((char **)data)[0];
920         facility_password = ((char **)data)[1];
921         facility_class    = ((char **)data)[2];
922
923
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);
926         free(cmd);
927         if (err < 0 || p_response->success == 0){
928                 goto error;
929         }
930
931         line = p_response->p_intermediates->line;
932
933         err = at_tok_start(&line);
934
935         if (err < 0) {
936                 goto error;
937         }
938
939         err = at_tok_nextint(&line, &response);
940
941         if (err < 0) {
942                 goto error;
943         }
944
945         RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
946         at_response_free(p_response);
947         return;
948
949 error:
950         at_response_free(p_response);
951         LOGE("ERROR: requestQueryFacilityLock() failed\n");
952         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
953 }
954
955 static void sendCallStateChanged(void *param)
956 {
957         RIL_onUnsolicitedResponse (
958                         RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
959                         NULL, 0);
960 }
961
962 static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
963 {
964         int err,fd;
965         ATResponse *p_response;
966         ATLine *p_cur;
967         int countCalls;
968         RIL_Call *p_calls;
969         RIL_Call **pp_calls;
970         int i;
971         char status[1];
972         int needRepoll = 0;
973         char *l_callwaiting_num=NULL;
974
975 #ifdef WORKAROUND_ERRONEOUS_ANSWER
976         int prevIncomingOrWaitingLine;
977
978         prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
979         s_incomingOrWaitingLine = -1;
980 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
981
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);
985         }
986
987         err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
988
989         if (err != 0 || p_response->success == 0) {
990                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
991                 return;
992         }
993
994         /* count the calls */
995         for (countCalls = 0, p_cur = p_response->p_intermediates
996                         ; p_cur != NULL
997                         ; p_cur = p_cur->p_next
998             ) {
999                 countCalls++;
1000         }
1001
1002         if (callwaiting_num) {
1003                 /* This is not thread-safe.  Boo. */
1004                 l_callwaiting_num = callwaiting_num;
1005                 callwaiting_num = NULL;
1006                 countCalls++;
1007         }
1008
1009         /* yes, there's an array of pointers and then an array of structures */
1010
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));
1014
1015         /* init the pointer array */
1016         for(i = 0; i < countCalls ; i++) {
1017                 pp_calls[i] = &(p_calls[i]);
1018         }
1019
1020         for (countValidCalls = 0, p_cur = p_response->p_intermediates
1021                         ; p_cur != NULL
1022                         ; p_cur = p_cur->p_next
1023             ) {
1024                 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
1025
1026                 if (err != 0) {
1027                         continue;
1028                 }
1029
1030 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1031                 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
1032                                 || p_calls[countValidCalls].state == RIL_CALL_WAITING
1033                    ) {
1034                         s_incomingOrWaitingLine = p_calls[countValidCalls].index;
1035                 }
1036 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
1037
1038                 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
1039                                 && p_calls[countValidCalls].state != RIL_CALL_HOLDING
1040                    ) {
1041                         needRepoll = 1;
1042                 }
1043                 if(p_calls[countValidCalls].isVoice) // only count voice calls
1044                         countValidCalls++;
1045         }
1046
1047         if (l_callwaiting_num) {
1048                 char fake_clcc[64];
1049                 int index = p_calls[countValidCalls-1].index+1;
1050
1051                 /* Try not to use an index greater than 9 */
1052                 if (index > 9) {
1053                         int i;
1054
1055                         for (i=countValidCalls-2; i >= 0; i++) {
1056                                 if (p_calls[i].index < 9) {
1057                                         index = p_calls[i].index+1;
1058                                         break;
1059                                 }
1060                         }
1061                 }
1062
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);
1067                 if (err == 0) {
1068                         countValidCalls++;
1069                 }
1070         }
1071
1072 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1073         // Basically:
1074         // A call was incoming or waiting
1075         // Now it's marked as active
1076         // But we never answered it
1077         //
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
1083            ) {
1084                 for (i = 0; i < countValidCalls ; i++) {
1085
1086                         if (p_calls[i].index == prevIncomingOrWaitingLine
1087                                         && p_calls[i].state == RIL_CALL_ACTIVE
1088                                         && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
1089                            ) {
1090                                 LOGI(
1091                                                 "Hit WORKAROUND_ERRONOUS_ANSWER case."
1092                                                 " Repoll count: %d\n", s_repollCallsCount);
1093                                 s_repollCallsCount++;
1094                                 goto error;
1095                         }
1096                 }
1097         }
1098
1099         s_expectAnswer = 0;
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");
1106         }
1107
1108         RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
1109                         countValidCalls * sizeof (RIL_Call *));
1110
1111         at_response_free(p_response);
1112
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.
1116 #else
1117         if (needRepoll)
1118 #endif
1119         {
1120                 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
1121         }
1122         return;
1123
1124 error:
1125         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1126         at_response_free(p_response);
1127 }
1128
1129 static void requestDial(void *data, size_t datalen, RIL_Token t)
1130 {
1131         RIL_Dial *p_dial;
1132         char *cmd;
1133         const char *clir;
1134         int ret;
1135
1136         p_dial = (RIL_Dial *)data;
1137
1138         switch (p_dial->clir) {
1139                 case 1: clir = "I"; break;  /*invocation*/
1140                 case 2: clir = "i"; break;  /*suppression*/
1141                 default:
1142                 case 0: clir = ""; break;   /*subscription default*/
1143         }
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);
1147         else
1148                 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
1149
1150         ret = at_send_command(cmd, NULL);
1151
1152         free(cmd);
1153
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);
1157 }
1158
1159 static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
1160 {
1161         RIL_SMS_WriteArgs *p_args;
1162         char *cmd;
1163         int length;
1164         int err;
1165         ATResponse *p_response = NULL;
1166
1167         if(isgsm) {
1168
1169                 p_args = (RIL_SMS_WriteArgs *)data;
1170
1171                 length = strlen(p_args->pdu)/2;
1172                 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
1173
1174                 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
1175
1176                 free(cmd);
1177
1178                 if (err != 0 || p_response->success == 0) goto error;
1179
1180                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1181                 at_response_free(p_response);
1182         } else {
1183                 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
1184         }
1185         return;
1186
1187 error:
1188         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1189         at_response_free(p_response);
1190 }
1191
1192 static void requestHangup(void *data, size_t datalen, RIL_Token t)
1193 {
1194         int *p_line;
1195
1196         int ret;
1197         char *cmd;
1198
1199         p_line = (int *)data;
1200
1201         // 3GPP 22.030 6.5.5
1202         // "Releases a specific active call X"
1203         asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
1204
1205         ret = at_send_command(cmd, NULL);
1206
1207         free(cmd);
1208         //      writesys("audio","5");
1209
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);
1213 }
1214
1215 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
1216 {
1217         ATResponse *p_response = NULL;
1218         int err;
1219         int response[2];
1220         char *line;
1221
1222 #if 0   /* Just rely on unsolicited reports */
1223         if(signalStrength[0] == 0 && signalStrength[1] == 0) {
1224                 if(isgsm)
1225                         err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
1226                 else
1227                         err = at_send_command_singleline("AT+HTC_CSQ", "+HTC_CSQ:", &p_response);
1228
1229                 if (err < 0 || p_response->success == 0) {
1230                         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1231                         goto error;
1232                 }
1233
1234                 line = p_response->p_intermediates->line;
1235
1236                 err = at_tok_start(&line);
1237                 if (err < 0) goto error;
1238
1239                 err = at_tok_nextint(&line, &(response[0]));
1240                 if (err < 0) goto error;
1241
1242                 err = at_tok_nextint(&line, &(response[1]));
1243                 if (err < 0) goto error;
1244                 if(!isgsm) {
1245                         response[0]*=2;
1246                         response[1]=99;
1247                 }
1248                 signalStrength[0] = response[0];
1249                 signalStrength[1] = response[1];
1250                 at_response_free(p_response);
1251
1252         } else {
1253                 LOGD("Sending stored CSQ values to RIL");
1254                 response[0] = signalStrength[0];
1255                 response[1] = signalStrength[1];
1256         }
1257 #endif
1258         response[0] = signalStrength[0];
1259         response[1] = signalStrength[1];
1260         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1261         return;
1262
1263 error:
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);
1267 }
1268
1269 static void requestDtmfStart(void *data, size_t datalen, RIL_Token t)
1270 {
1271         int err;
1272         char *cmd;
1273         char c;
1274
1275         assert (datalen >= sizeof(char *));
1276
1277         c = ((char *)data)[0];
1278         at_send_command("AT+CMUT=1", NULL);
1279         asprintf(&cmd, "AT+VTS=%c", (int)c);
1280         if(c=='*')
1281                 at_send_command("AT+WFSH", NULL); //FIXME: what is this for??? send flash? doesn't make sense
1282
1283         err = at_send_command(cmd, NULL);
1284         free(cmd);
1285
1286         if (err != 0) goto error;
1287
1288         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1289         return;
1290
1291 error:
1292         LOGE("ERROR: requestDtmfStart failed");
1293         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1294
1295 }
1296
1297 static void requestDtmfStop(void *data, size_t datalen, RIL_Token t)
1298 {
1299         int err;
1300
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;
1306
1307         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1308         return;
1309
1310 error:
1311         LOGE("ERROR: requestDtmfStop failed");
1312         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1313
1314 }
1315
1316 static void requestSetMute(void *data, size_t datalen, RIL_Token t)
1317 {
1318         int err;
1319         char *cmd;
1320
1321         assert (datalen >= sizeof(int *));
1322
1323         asprintf(&cmd, "AT+CMUT=%d", ((int*)data)[0]);
1324
1325         err = at_send_command(cmd, NULL);
1326         free(cmd);
1327
1328         if (err != 0) goto error;
1329
1330         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1331         return;
1332
1333 error:
1334         LOGE("ERROR: requestSetMute failed");
1335         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1336
1337 }
1338
1339 static void requestGetMute(void *data, size_t datalen, RIL_Token t)
1340 {
1341         int err;
1342         ATResponse *p_response = NULL;
1343         int response[1];
1344         char *line;
1345
1346         if(!isgsm) {
1347                 err = at_send_command_singleline("AT+CMUT?", "+CMUT:", &p_response);
1348         } else {
1349                 err = at_send_command_singleline("AT+MUT", "+CMUT:", &p_response);
1350         }
1351         if (err < 0 || p_response->success == 0) {
1352                 goto error;
1353         }
1354
1355         line = p_response->p_intermediates->line;
1356
1357         err = at_tok_start(&line);
1358         if (err < 0) goto error;
1359
1360         err = at_tok_nextint(&line, &response[0]);
1361         if (err < 0) goto error;
1362
1363         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char*));
1364         at_response_free(p_response);
1365
1366         return;
1367
1368 error:
1369         LOGE("ERROR: requestGetMute failed");
1370         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1371         at_response_free(p_response);
1372 }
1373
1374 static void requestScreenState(void *data, size_t datalen, RIL_Token t)
1375 {
1376         int err, screenState;
1377
1378         assert (datalen >= sizeof(int *));
1379         screenState = ((int*)data)[0];
1380
1381         if(screenState == 1)
1382         {
1383                 if (isgsm) {
1384                         /*
1385                          if (ppt)
1386                                 "AT+ENCSQ=1;\r"
1387                          else
1388                                  "AT+ENCSQ=1;+CREG=2\r"
1389
1390                         requestRegistrationState
1391
1392                          "AT+HTCCTZR=1\r"
1393                          "AT@HTCPDPFD=0\r"
1394                          */
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;*/
1408
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;                        
1415                 } else {
1416
1417                 }
1418         } else if (screenState == 0) {
1419                 if (isgsm) {
1420                         /*
1421                                 "AT+HTCPDPIDLE\r"
1422                                 if (ppt)
1423                                         "AT+ENCSQ=0;\r"
1424                                 else
1425                                         "AT+ENCSQ=0;+CREG=1\r"
1426                                 "AT+HTCCTZR=2\r"
1427                                 "AT@HTCPDPFD=1"
1428                          */
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;*/
1442
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;
1451                 } else {
1452
1453                 }
1454         } else {
1455                 /* Not a defined value - error */
1456                 goto error;
1457         }
1458
1459         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1460         return;
1461
1462 error:
1463         LOGE("ERROR: requestScreenState failed");
1464         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1465 }
1466
1467 static void requestRegistrationState(int request, void *data,
1468                 size_t datalen, RIL_Token t)
1469 {
1470         int err;
1471         int response[4];
1472         char * responseStr[4];
1473         ATResponse *p_response = NULL;
1474         const char *cmd;
1475         const char *prefix;
1476         char *line, *p;
1477         int commas;
1478         int skip;
1479         int i;
1480         int count = 4;
1481         int fd;
1482         int dataCall = 0;
1483         char status[1];
1484
1485         response[0]=1;
1486         response[1]=-1;
1487         response[2]=-1;
1488         response[3]=1;
1489
1490         if(isgsm) {
1491                 if (request == RIL_REQUEST_REGISTRATION_STATE) {
1492                         cmd = "AT+CREG?";
1493                         prefix = "+CREG:";
1494                 } else if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
1495                         cmd = "AT+CGREG?";
1496                         prefix = "+CGREG:";
1497                 } else {
1498                         assert(0);
1499                         goto error;
1500                 }
1501         } else {
1502                 /* "Regular" CDMA (like Diam/Raph) uses AT+COPS, world phone CDMA uses AT+HTC_SRV_STATUS */
1503                 if (is_world_cdma)
1504                         cmd = "AT+HTC_SRV_STATUS?";
1505                 else
1506                         cmd = "AT+COPS?";
1507
1508                 prefix= "$HTC_SYSTYPE";
1509         }
1510         err = 1;
1511         for (i=0;i<4 && err != 0;i++)
1512                 err = at_send_command_singleline(cmd, prefix, &p_response);
1513
1514         if (err != 0) goto error;
1515
1516         line = p_response->p_intermediates->line;
1517
1518         err = at_tok_start(&line);
1519         if (err < 0) goto error;
1520         if (isgsm) {
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
1528                  *
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
1532                  *
1533                  * Also since the LAC and CID are only reported when registered,
1534                  * we can have 1, 2, 3, or 4 arguments here
1535                  *
1536                  * finally, a +CGREG: answer may have a fifth value that corresponds
1537                  * to the network type, as in;
1538                  *
1539                  *   +CGREG: n, stat [,lac, cid [,networkType]]
1540                  */
1541
1542                 /* count number of commas */
1543                 commas = 0;
1544                 for (p = line ; *p != '\0' ;p++) {
1545                         if (*p == ',') commas++;
1546                 }
1547
1548                 switch (commas) {
1549                         case 0: /* +CREG: <stat> */
1550                                 err = at_tok_nextint(&line, &response[0]);
1551                                 if (err < 0) goto error;
1552                                 response[1] = -1;
1553                                 response[2] = -1;
1554                                 break;
1555
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;
1561                                 response[1] = -1;
1562                                 response[2] = -1;
1563                                 if (err < 0) goto error;
1564                                 break;
1565
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;
1573                                 break;
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;
1583
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 */
1589                                         int commas_op;
1590                                         commas_op = 0;
1591                                         char *p_op, *line_op;
1592                                         line_op = p_response_op->p_intermediates->line;
1593
1594                                         for (p_op = line_op ; *p_op != '\0' ;p_op++) {
1595                                                 if (*p_op == ',') commas_op++;
1596                                         }
1597
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 */
1611                                                         case 0:
1612                                                         case 1:
1613                                                                 response[3] = 1;
1614                                                                 break;
1615                                                                 /* EGPRS - aka EDGE */
1616                                                         case 3:
1617                                                                 response[3] = 2;
1618                                                                 break;
1619                                                                 /* UTRAN - UMTS aka 3G */
1620                                                         case 2:
1621                                                         case 7:
1622                                                                 response[3] = 3;
1623                                                                 break;
1624                                                                 /* UTRAN with HSDPA and/or HSUPA aka Turbo-3G */
1625                                                         case 4:
1626                                                         case 5:
1627                                                         case 6:
1628                                                                 response[3] = 9;
1629                                                                 break;
1630                                                 }
1631                                         }
1632
1633                                         at_response_free(p_response_op);
1634                                 }
1635                                 break;
1636                                 /* special case for CGREG, there is a fourth parameter
1637                                  * that is the network type (unknown/gprs/edge/umts)
1638                                  */
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;
1650                                 break;
1651                         default:
1652                                 goto error;
1653                 }
1654         } else { //CDMA
1655                 if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
1656                         err = at_tok_nextint(&line, &response[3]);
1657                         if (response[3] < 1)
1658                                 response[3] = 1;
1659                         if (response[3] > 3)
1660                                 response[3] = 3;
1661                 }
1662         }
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]);
1667
1668         RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
1669         at_response_free(p_response);
1670
1671         return;
1672 error:
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);
1676 }
1677
1678 static void requestOperator(void *data, size_t datalen, RIL_Token t)
1679 {
1680         int err;
1681         int i;
1682         int skip;
1683         ATLine *p_cur;
1684         char *response[4];
1685
1686         memset(response, 0, sizeof(response));
1687
1688         ATResponse *p_response = NULL;
1689         if(isgsm) {
1690                 err = at_send_command_multiline(
1691                                 "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
1692                                 "+COPS:", &p_response);
1693
1694                 /* we expect 3 lines here:
1695                  * +COPS: 0,0,"T - Mobile"
1696                  * +COPS: 0,1,"TMO"
1697                  * +COPS: 0,2,"310170"
1698                  */
1699
1700                 if (err != 0) goto error;
1701
1702                 for (i = 0, p_cur = p_response->p_intermediates
1703                                 ; p_cur != NULL
1704                                 ; p_cur = p_cur->p_next, i++
1705                     ) {
1706                         char *line = p_cur->line;
1707
1708                         err = at_tok_start(&line);
1709                         if (err < 0) goto error;
1710
1711                         err = at_tok_nextint(&line, &skip);
1712                         if (err < 0) goto error;
1713
1714                         // If we're unregistered, we may just get
1715                         // a "+COPS: 0" response
1716                         if (!at_tok_hasmore(&line)) {
1717                                 response[i] = NULL;
1718                                 continue;
1719                         }
1720
1721                         err = at_tok_nextint(&line, &skip);
1722                         if (err < 0) goto error;
1723
1724                         // a "+COPS: 0, n" response is also possible
1725                         if (!at_tok_hasmore(&line)) {
1726                                 response[i] = NULL;
1727                                 continue;
1728                         }
1729
1730                         err = at_tok_nextstr(&line, &(response[i]));
1731                         if (err < 0) goto error;
1732                 }
1733
1734                 if (i < 3) {
1735                         goto error;
1736                 }
1737                 if (i == 3) {
1738                         response[3] = '\0';
1739                 }
1740         }
1741         else {
1742                 response[0]=erisystem;
1743                 response[1]="Android";
1744                 response[2]="310260";
1745         }
1746
1747         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1748         at_response_free(p_response);
1749         return;
1750
1751 error:
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);
1755 }
1756
1757 static void requestSendSMS(void *data, size_t datalen, RIL_Token t, int request)
1758 {
1759         int err;
1760         char smsc[30];
1761         const char *pdu;
1762         const char *testSmsc;
1763         int tpLayerLength,length,i,plus = 0;
1764         char *cmd1, *cmd2, *line, *temp;
1765 //      bytes_t first;
1766         int tosca,curChar=0;
1767         RIL_SMS_Response response;
1768         ATResponse *p_response = NULL;
1769         ATResponse *p2_response = NULL;
1770         char * cdma=0;
1771         char sendstr[512];
1772         struct {
1773                 RIL_SMS_Response resp;
1774                 int result;
1775         } extendedResponse;
1776
1777         testSmsc = ((char **)data)[0];
1778         pdu = ((const char **)data)[1];
1779
1780         tpLayerLength = strlen(pdu)/2;
1781         LOGI("SMSC=%s  PDU=%s",testSmsc,pdu);
1782         // "NULL for default SMSC"
1783         if (testSmsc == NULL) {
1784                 if(isgsm){
1785                         err = at_send_command_singleline("AT+CSCA?", "+CSCA:", &p2_response);
1786
1787                         if (err < 0 || p2_response->success == 0) {
1788                                 goto error;
1789                         }
1790
1791                         line = p2_response->p_intermediates->line;
1792
1793                         err = at_tok_start(&line);
1794                         if (err < 0) goto error;
1795
1796                         err = at_tok_nextstr(&line, &temp);
1797                         if (err < 0) goto error;
1798
1799                         err = at_tok_nextint(&line, &tosca);
1800                         if (err < 0) goto error;
1801
1802                         if(temp[0]=='+') {
1803                                 ++temp;
1804                                 //plus = 1;
1805                         }
1806
1807                         length = strlen(temp) - plus;
1808                         sprintf(smsc,"%.2x%.2x",(length + 1) / 2 + 1, tosca);
1809
1810                         for (i = 0; curChar < length - 1; i+=2 ) {
1811                                 smsc[5+i] = temp[plus+curChar++];
1812                                 smsc[4+i] = temp[plus+curChar++];
1813                         }
1814
1815                         if ( length % 2) {//One extra number
1816                                 smsc[4+length] = temp[curChar];
1817                                 smsc[3+length]='F';
1818                                 smsc[5+length]='\0';
1819                         } else {
1820                                 smsc[4+length] = '\0';
1821                         }
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);
1825                         //free(first);
1826                 }
1827         }
1828         else
1829                 strcpy(smsc,testSmsc);
1830         LOGI("SMSC=%s  PDU=%s",smsc,pdu);
1831
1832         if(!isgsm) {
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;
1838         }
1839         asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
1840         if(isgsm)
1841                 asprintf(&cmd2, "%s%s", smsc, pdu);
1842         else
1843                 asprintf(&cmd2, "%s", cdma);
1844
1845         err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
1846
1847         free(cmd1);
1848         free(cmd2);
1849 //      free(smsc);
1850
1851         if (err != 0 || p_response->success == 0) goto error;
1852
1853         memset(&response, 0, sizeof(response));
1854
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;
1859
1860         err = at_tok_nextint(&line, &response.messageRef);
1861         if (err < 0) goto error;
1862         
1863         response.ackPDU = NULL;
1864
1865         if (request == RIL_REQUEST_SEND_SMS_EXTENDED)
1866         {
1867                 extendedResponse.resp = response;
1868                 extendedResponse.result = 1;
1869                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &extendedResponse, sizeof(extendedResponse));
1870         }
1871         else
1872         {
1873                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
1874         }
1875         at_response_free(p_response);
1876         at_response_free(p2_response);
1877         return;
1878
1879 error:
1880         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1881         at_response_free(p_response);
1882         at_response_free(p2_response);
1883 }
1884
1885 static void requestSetupDataCall(char **data, size_t datalen, RIL_Token t)
1886 {
1887         const char *apn;
1888         char *user = NULL;
1889         char *pass = NULL;
1890         char *cmd;
1891         char *userpass;
1892         int err;
1893         ATResponse *p_response = NULL;
1894         int fd, pppstatus,i,fd2;
1895         FILE *pppconfig;
1896         size_t cur = 0;
1897         ssize_t written, rlen;
1898         char status[32] = {0};
1899         char *buffer;
1900         long buffSize, len;
1901         int retry = 10;
1902         char *response[3] = { "1", PPP_TTY_PATH, "255.255.255.255" };
1903         int mypppstatus;
1904
1905         apn = ((const char **)data)[2];
1906         user = ((char **)data)[3];
1907         if(user != NULL)
1908         {
1909                 if (strlen(user)<2)
1910                         user = "dummy";
1911         } else
1912                 user = "dummy";
1913
1914         pass = ((char **)data)[4];
1915         if(pass != NULL)
1916         {
1917                 if (strlen(pass)<2)
1918                         pass = "dummy";
1919         } else
1920                 pass = "dummy";
1921
1922         LOGD("requesting data connection to APN '%s'\n", apn);
1923
1924         //Make sure there is no existing connection or pppd instance running
1925         if(killConn(response[0]) < 0)
1926                 goto error;
1927
1928         if(isgsm)
1929         {
1930                 if (*data[0]=='0')
1931                 LOGE("Android want us to connect as CDMA while we are a GSM phone !");
1932         } else
1933         {
1934                 if(*data[0]=='1')
1935                 LOGE("Android want us to connect as GSM while we are a CDMA phone !");
1936         }
1937         if(isgsm) {
1938                 asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
1939                 //FIXME check for error here
1940                 err = at_send_command(cmd, NULL);
1941                 free(cmd);
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);
1954                         goto error;
1955                 }
1956                 at_response_free(p_response);
1957         } else {
1958                 //CDMA
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);
1965                         goto error;
1966                 }
1967                 at_response_free(p_response);
1968         }
1969
1970         asprintf(&userpass, "%s * %s\n", user, pass);
1971         len = strlen(userpass);
1972         fd = open("/etc/ppp/pap-secrets",O_WRONLY);
1973         if(fd < 0)
1974                 goto error;
1975         write(fd, userpass, len);
1976         close(fd);
1977         fd = open("/etc/ppp/chap-secrets",O_WRONLY);
1978         if(fd < 0)
1979                 goto error;
1980         write(fd, userpass, len);
1981         close(fd);
1982         free(userpass);
1983
1984         pppconfig = fopen("/etc/ppp/options.smd","r");
1985         if(!pppconfig)
1986                 goto error;
1987
1988         //filesize
1989         fseek(pppconfig, 0, SEEK_END);
1990         buffSize = ftell(pppconfig);
1991         rewind(pppconfig);
1992
1993         //allocate memory
1994         buffer = (char *) malloc (sizeof(char)*buffSize);
1995         if (buffer == NULL)
1996                 goto error;
1997
1998         //read in the original file
1999         len = fread (buffer,1,buffSize,pppconfig);
2000         if (len != buffSize)
2001                 goto error;
2002         fclose(pppconfig);
2003
2004         pppconfig = fopen("/etc/ppp/options.smd1","w");
2005         fwrite(buffer,1,buffSize,pppconfig);
2006         fprintf(pppconfig,"user %s\n",user);
2007         fclose(pppconfig);
2008         free(buffer);
2009
2010         // The modem replies immediately even if it's not connected!
2011         // so wait a short time.
2012         sleep(2);
2013         mypppstatus = system("/bin/pppd /dev/smd1");//Or smd7 ?
2014         if (mypppstatus < 0)
2015                 goto error;
2016         sleep(5); // allow time for ip-up to run
2017         /*
2018          * We are supposed to return IP address in response[2], but this is not used by android currently
2019          */
2020         /*
2021         inaddr_t addr,mask;
2022         unsigned int flags;
2023         ifc_init();
2024         ifc_get_info(PPP_TTY_PATH, &addr, &mask, &flags);
2025         ifc_close();
2026         */
2027         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
2028         return;
2029
2030 error:
2031         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2032
2033 }
2034
2035 static int killConn(char *cid)
2036 {
2037         int err;
2038         char * cmd;
2039         int fd,i=0;
2040         ATResponse *p_response = NULL;
2041
2042         while((fd = open("/etc/ppp/ppp-gprs.pid",O_RDONLY)) > 0) {
2043                 if(i%5 == 0) {
2044                         system("killall pppd");
2045                 }
2046                 close(fd);
2047                 if(i>25)
2048                         goto error;
2049                 i++;
2050                 sleep(1);
2051         }
2052         if (isgsm) {
2053                 asprintf(&cmd, "AT+CGACT=0,%s", cid);
2054
2055                 err = at_send_command(cmd, &p_response);
2056                 free(cmd);
2057
2058                 if (err < 0 || p_response->success == 0) {
2059                         at_response_free(p_response);
2060                         goto error;
2061                 }
2062                 at_response_free(p_response);
2063         } else {
2064                 //CDMA
2065                 if (dataCallNum() >= 0) {
2066                         err = at_send_command("ATH", &p_response);
2067
2068                         if (err < 0 || p_response->success == 0) {
2069                                 at_response_free(p_response);
2070                                 goto error;
2071                         }
2072                         at_response_free(p_response);
2073                 }
2074         }
2075         return 0;
2076
2077 error:
2078         return -1;
2079 }
2080
2081 static void requestDeactivateDataCall(void *data, size_t datalen, RIL_Token t)
2082 {
2083         char *cid;
2084
2085         cid = ((char **)data)[0];
2086         if (killConn(cid) < 0)
2087                 goto error;
2088
2089         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2090         return;
2091
2092 error:
2093         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2094 }
2095
2096 static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
2097 {
2098         int ackSuccess;
2099         int err;
2100
2101         ackSuccess = ((int *)data)[0];
2102
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);
2107         } else {
2108                 LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
2109                 goto error;
2110         }
2111
2112         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2113         return;
2114
2115 error:
2116         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2117
2118 }
2119
2120 static void  requestSIM_IO(void *data, size_t datalen, RIL_Token t)
2121 {
2122         ATResponse *p_response = NULL;
2123         RIL_SIM_IO_Response sr;
2124         int err;
2125         char *cmd = NULL;
2126         RIL_SIM_IO *p_args;
2127         char *line;
2128
2129         memset(&sr, 0, sizeof(sr));
2130
2131         p_args = (RIL_SIM_IO *)data;
2132         if(slow_sim)
2133                 usleep(slow_sim);
2134
2135         /* FIXME handle pin2 */
2136
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);
2141         } else {
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);
2145         }
2146         if(isgsm){
2147                 err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
2148
2149                 if (err < 0 || p_response->success == 0) {
2150                         goto error;
2151                 }
2152
2153                 line = p_response->p_intermediates->line;
2154
2155                 err = at_tok_start(&line);
2156                 if (err < 0) goto error;
2157
2158                 err = at_tok_nextint(&line, &(sr.sw1));
2159                 if (err < 0) goto error;
2160
2161                 err = at_tok_nextint(&line, &(sr.sw2));
2162                 if (err < 0) goto error;
2163
2164                 if (at_tok_hasmore(&line)) {
2165                         err = at_tok_nextstr(&line, &(sr.simResponse));
2166                         if (err < 0) goto error;
2167                 }
2168         } else {
2169                 //CDMA
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);
2174                         free(cmd);
2175                         return;
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
2177                         sr.sw1=144;
2178                         sr.sw2=0;
2179
2180                         if(p_args->command == 192)
2181                                 asprintf(&sr.simResponse,"000000806f40040011a0aa01020120");
2182                         else {
2183                                 char * msid;
2184                                 char * response;
2185                                 int plus = 0;
2186                                 int length;
2187                                 int i;
2188                                 int curChar=0;
2189
2190                                 err = at_send_command_singleline("AT+CNUM", "+CNUM:", &p_response);
2191
2192                                 if (err < 0 || p_response->success == 0)
2193                                         goto error;
2194                                 line = p_response->p_intermediates->line;
2195
2196                                 at_tok_start(&line);
2197                                 err = at_tok_nextstr(&line, &response);
2198                                 if (err < 0)
2199                                         goto error;
2200                                 err = at_tok_nextstr(&line, &response);
2201                                 if (err < 0)
2202                                         goto error;
2203
2204                                 if(response[0]=='+')
2205                                         plus = 1;
2206
2207                                 length = strlen(response) - plus;
2208                                 asprintf(&msid,"%.2x%.2dFFFFFFFFFFFFFFFFFFFF",(length + 1) / 2 + 1, 81 + plus * 10);
2209
2210                                 for (i = 0; curChar < length - 1; i+=2 ) {
2211                                         msid[5+i] = response[plus+curChar++];
2212                                         msid[4+i] = response[plus+curChar++];
2213                                 }
2214
2215                                 if ( length % 2) //One extra number
2216                                         msid[4+length] = response[curChar];
2217
2218                                 asprintf(&sr.simResponse,"ffffffffffffffffffffffffffffffffffff%sffff",msid);
2219                                 free(msid);
2220                         }
2221                 }
2222         }
2223
2224         RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
2225         at_response_free(p_response);
2226         free(cmd);
2227         return;
2228
2229 error:
2230         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2231         at_response_free(p_response);
2232         free(cmd);
2233
2234 }
2235
2236 static void  requestEnterSimPin(void*  data, size_t  datalen, RIL_Token  t)
2237 {
2238         ATResponse   *p_response = NULL;
2239         int           err;
2240         char*         cmd = NULL;
2241         const char**  strings = (const char**)data;;
2242
2243         if(isgsm) {
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]);
2248                 } else
2249                         goto error;
2250
2251                 err = at_send_command_singleline(cmd, "+CREG:", &p_response);
2252                 free(cmd);
2253
2254                 if (err < 0 || p_response->success == 0) {
2255 error:
2256                         RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
2257                 } else {
2258                         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2259
2260                         /* Notify that SIM is ready */
2261                         setRadioState(RADIO_STATE_SIM_READY);
2262                 }
2263                 
2264                 at_response_free(p_response);
2265         } else {
2266                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2267                 setRadioState(RADIO_STATE_SIM_READY);
2268         }
2269 }
2270
2271 static void  requestChangeSimPin(void*  data, size_t  datalen, RIL_Token  t)
2272 {
2273         ATResponse   *p_response = NULL;
2274         int           err;
2275         char*         cmd = NULL;
2276         const char**  strings = (const char**)data;;
2277
2278         if(isgsm) {
2279                 if ( datalen == 2*sizeof(char*) )
2280                         asprintf(&cmd, "AT+CPWD=\"SC\",\"%s\",\"%s\"", strings[0], strings[1]);
2281                 else
2282                         goto error;
2283
2284                 err = at_send_command(cmd, &p_response);
2285                 free(cmd);
2286
2287                 if (err < 0 || p_response->success == 0) {
2288 error:
2289                         RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
2290                 }
2291                 else
2292                         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2293                 
2294                 at_response_free(p_response);
2295         } else {
2296                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2297         }
2298 }
2299
2300
2301 static void unsolicitedNitzTime(const char * s)
2302 {
2303         int err;
2304         char * response = NULL;
2305         char * line, *origline;
2306         char * p = NULL;
2307         char * tz = NULL; /* Timezone */
2308         origline = line = strdup(s);
2309
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)
2312          */
2313
2314         if(strStartsWith(s,"+CTZV:")){
2315
2316                 /* Get Time and Timezone data and store in static variable.
2317                  * Wait until DST is received to send response to upper layers
2318                  */
2319                 at_tok_start(&line);
2320
2321                 err = at_tok_nextstr(&line, &tz);
2322                 if (err < 0) goto error;
2323
2324                 err = at_tok_nextstr(&line, &response);
2325                 if (err < 0) goto error;
2326
2327                 snprintf(sNITZtime, sizeof(sNITZtime), "%s%s", response, tz);
2328
2329         }
2330         else if(strStartsWith(s,"+CTZDST:")){
2331
2332                 /* We got DST, now assemble the response and send to upper layers */
2333                 at_tok_start(&line);
2334
2335                 err = at_tok_nextstr(&line, &tz);
2336                 if (err < 0) goto error;
2337
2338                 asprintf(&response, "%s,%s", sNITZtime, tz);
2339
2340                 RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response));
2341                 free(response);
2342
2343         }
2344         else if(strStartsWith(s, "+HTCCTZV:")){
2345                 at_tok_start(&line);
2346
2347                 err = at_tok_nextstr(&line, &response);
2348                 if (err < 0) goto error;
2349                 RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response));
2350
2351         }
2352         free(origline);
2353         return;
2354
2355 error:
2356         LOGE("Invalid NITZ line %s\n", s);
2357 }
2358
2359 static void unsolicitedRSSI(const char * s)
2360 {
2361         int err;
2362         int response[2];
2363         char * line = NULL, *origline;
2364         const unsigned char asu_table[6]={0,2,6,12,25,31};
2365
2366         origline = strdup(s);
2367         line = origline;
2368
2369         err = at_tok_start(&line);
2370         if (err < 0) goto error;
2371
2372         err = at_tok_nextint(&line, &(response[0]));
2373         if (err < 0) goto error;
2374
2375         response[0]=asu_table[response[0]%6];
2376         response[1]=99;
2377
2378         signalStrength[0]=response[0];
2379         signalStrength[1]=response[1];
2380         free(origline);
2381
2382         RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, response, sizeof(response));
2383         return;
2384
2385 error:
2386         /* The notification was for a battery event - do not send a msg to upper layers */
2387         return;
2388 }
2389
2390 static void requestNotSupported(RIL_Token t, int request)
2391 {
2392         LOGD("Request %d is unsupported", request);
2393         RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
2394         return;
2395 }
2396
2397 static void requestOEMHookRaw(void *data, size_t datalen, RIL_Token t)
2398 {
2399         RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
2400         return;
2401 }
2402
2403 static void requestQueryCallWaiting(void *data, size_t datalen, RIL_Token t)
2404 {
2405         ATResponse *p_response = NULL;
2406         int err;
2407         char *cmd = NULL;
2408         char *line;
2409         int class;
2410         int response[2];
2411
2412         class = ((int *)data)[0];
2413
2414         asprintf(&cmd, "AT+CCWA=1,2,%d",class);
2415
2416         err = at_send_command_singleline(cmd, "+CCWA:", &p_response);
2417
2418         if (err < 0 || p_response->success == 0) goto error;
2419
2420         line = p_response->p_intermediates->line;
2421
2422         err = at_tok_start(&line);
2423         if (err < 0) goto error;
2424
2425         err = at_tok_nextint(&line, &(response[0]));
2426         if (err < 0) goto error;
2427
2428         if (at_tok_hasmore(&line)) {
2429                 err = at_tok_nextint(&line, &(response[1]));
2430                 if (err < 0) goto error;
2431         }
2432
2433         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
2434         at_response_free(p_response);
2435         free(cmd);
2436         return;
2437
2438 error:
2439         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2440         at_response_free(p_response);
2441         free(cmd);
2442 }
2443
2444 static void requestSetCallWaiting(void *data, size_t datalen, RIL_Token t)
2445 {
2446         ATResponse *p_response = NULL;
2447         int err;
2448         char *cmd = NULL;
2449         int enabled, class;
2450
2451         if((datalen<2)||(data==NULL)) goto error;
2452
2453         enabled = ((int *)data)[0];
2454         class = ((int *)data)[1];
2455
2456         asprintf(&cmd, "AT+CCWA=0,%d,%d",enabled,class);
2457
2458         err = at_send_command(cmd, NULL);
2459
2460         if (err < 0 ) goto error;
2461
2462         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2463         at_response_free(p_response);
2464         free(cmd);
2465         return;
2466
2467 error:
2468         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2469         at_response_free(p_response);
2470         free(cmd);
2471 }
2472
2473 static void requestQueryCallForwardStatus(RIL_Token t)
2474 {
2475         int err = 0;
2476         int i = 0;
2477         int n = 0;
2478         int tmp = 0;
2479         ATResponse *p_response = NULL;
2480         ATLine *p_cur;
2481         RIL_CallForwardInfo **responses = NULL;
2482         char *cmd;
2483
2484         err = at_send_command_multiline("AT+CCFC=0,2", "+CCFC:", &p_response);
2485
2486         if(err != 0 || p_response->success == 0)
2487                 goto error;
2488
2489         for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next)
2490                 n++;
2491
2492         responses = alloca(n * sizeof(RIL_CallForwardInfo *));
2493
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;
2502         }
2503
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;
2506
2507                 err = at_tok_start(&line);
2508                 if (err < 0) goto error;
2509
2510                 err = at_tok_nextint(&line, &(responses[i]->status));
2511                 if (err < 0) goto error;
2512
2513                 err = at_tok_nextint(&line, &(responses[i]->serviceClass));
2514                 if (err < 0) goto error;
2515
2516                 if(!at_tok_hasmore(&line)) continue;
2517
2518                 err = at_tok_nextstr(&line, &(responses[i]->number));
2519                 if (err < 0) goto error;
2520
2521                 if(!at_tok_hasmore(&line)) continue;
2522
2523                 err = at_tok_nextint(&line, &(responses[i]->toa));
2524                 if (err < 0) goto error;
2525
2526                 if(!at_tok_hasmore(&line)) continue;
2527                 at_tok_nextint(&line,&tmp);
2528
2529                 if(!at_tok_hasmore(&line)) continue;
2530                 at_tok_nextint(&line,&tmp);
2531
2532                 if(!at_tok_hasmore(&line)) continue;
2533                 err = at_tok_nextint(&line, &(responses[i]->timeSeconds));
2534                 if (err < 0) goto error;
2535
2536         }
2537
2538         at_response_free(p_response);
2539         RIL_onRequestComplete(t, RIL_E_SUCCESS, responses, sizeof(RIL_CallForwardInfo **));
2540         return;
2541
2542 error:
2543         at_response_free(p_response);
2544         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2545 }
2546
2547 static void requestSetCallForward(void *data, RIL_Token t)
2548 {
2549         int err = 0;
2550         char *cmd = NULL;
2551         RIL_CallForwardInfo *info = NULL;
2552
2553         info = ((RIL_CallForwardInfo *) data);
2554
2555         if(data == NULL) goto error;
2556
2557         asprintf(&cmd, "AT+CCFC = %d, %d, \"%s\"",
2558                         info->reason, info->status,
2559                         info->number);
2560
2561         err = at_send_command(cmd, NULL);
2562
2563         if (err < 0 ) goto error;
2564
2565         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2566         free(cmd);
2567         return;
2568
2569 error:
2570         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2571         free(cmd);
2572 }
2573
2574 static void requestGetCLIR(void *data, size_t datalen, RIL_Token t)
2575 {
2576         /* Even though data and datalen must be NULL and 0 respectively this
2577          * condition is not verified
2578          */
2579         ATResponse *p_response = NULL;
2580         int response[2];
2581         char *line = NULL;
2582         int err = 0;
2583
2584         err = at_send_command_singleline("AT+CLIR?", "+CLIR:", &p_response);
2585
2586         if (err < 0 || p_response->success == 0) goto error;
2587
2588         line = p_response->p_intermediates->line;
2589         err = at_tok_start(&line);
2590         if (err < 0) goto error;
2591
2592         err = at_tok_nextint(&line, &(response[0]));
2593         if (err < 0) goto error;
2594
2595         err = at_tok_nextint(&line, &(response[1]));
2596         if (err < 0) goto error;
2597
2598         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
2599         at_response_free(p_response);
2600         return;
2601
2602 error:
2603         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2604         at_response_free(p_response);
2605 }
2606
2607 static void requestSetCLIR(void *data, size_t datalen, RIL_Token t)
2608 {
2609         char *cmd = NULL;
2610         int err = 0;
2611
2612         asprintf(&cmd, "AT+CLIR=%d", ((int *)data)[0]);
2613
2614         err = at_send_command(cmd, NULL);
2615         free(cmd);
2616
2617         if (err < 0)
2618                 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
2619         else
2620                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2621 }
2622
2623 static void requestSendSMSExpectMore(void *data, size_t datalen, RIL_Token t)
2624 {
2625         char *cmd = NULL;
2626         asprintf(&cmd, "AT+CMMS=1");
2627         at_send_command(cmd, NULL);
2628         free(cmd);
2629         requestSendSMS(data, datalen, t, 0);
2630 }
2631
2632 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
2633 {
2634         ATResponse *p_response = NULL;
2635         int err = 0;
2636         int len;
2637         cbytes_t ussdRequest;
2638         char *cmd;
2639         bytes_t temp;
2640         char *newUSSDRequest;
2641         if(isgsm) {
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);
2650                 free(temp);
2651                 err = at_send_command(cmd, &p_response);
2652                 free(cmd);
2653                 if (err < 0 || p_response->success == 0) {
2654                         goto error;
2655                 } else {
2656                         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2657                 }
2658                 at_response_free(p_response);
2659         } else {
2660                 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
2661         }
2662         return;
2663
2664 error:
2665         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2666 }
2667
2668 static void  unsolicitedUSSD(const char *s)
2669 {
2670         char *line, *linestart;
2671         int typeCode, count, err, len;
2672         char *message;
2673         char *outputmessage;
2674         char *responseStr[2];
2675
2676         LOGD("unsolicitedUSSD %s\n",s);
2677
2678         linestart=line=strdup(s);
2679         err = at_tok_start(&line);
2680         if(err < 0) goto error;
2681
2682         err = at_tok_nextint(&line, &typeCode);
2683         if(err < 0) goto error;
2684
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);
2694                 count = 2;
2695         } else {
2696                 responseStr[1]=NULL;
2697                 count = 1;
2698         }
2699         free(linestart);
2700         asprintf(&responseStr[0], "%d", typeCode);
2701         
2702         RIL_onUnsolicitedResponse (RIL_UNSOL_ON_USSD, responseStr, count*sizeof(char*));
2703         return;
2704
2705 error:
2706         free(linestart);
2707         LOGE("unexpectedUSSD error\n");
2708 }
2709
2710 static void  unsolicitedERI(const char *s) {
2711         char *line, *origline;
2712         int temp;
2713         char *newEri;
2714
2715         origline = strdup(s);
2716         line = origline;
2717         at_tok_start(&line);
2718
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);
2727
2728         if(strlen(newEri)<50)
2729                 strcpy(erisystem,newEri);
2730
2731         free(origline);
2732 }
2733
2734 static void requestSetFacilityLock(void *data, size_t datalen, RIL_Token t)
2735 {
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
2739          */
2740         int err = 0;
2741         char *cmd = NULL;
2742         char *code = NULL;
2743         char *lock = NULL;
2744         char *password = NULL;
2745         char *class = NULL;
2746
2747         assert (datalen >=  (4 * sizeof(char **)));
2748
2749         code = ((char **)data)[0];
2750         lock = ((char **)data)[1];
2751         password = ((char **)data)[2];
2752         class = ((char **)data)[3];
2753
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;
2757
2758         free(cmd);
2759         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2760         return;
2761
2762 error:
2763         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2764 }
2765
2766 static void requestChangeBarringPassword(void *data, size_t datalen, RIL_Token t)
2767 {
2768         int err = 0;
2769         char *cmd = NULL;
2770         char *string = NULL;
2771         char *old_password = NULL;
2772         char *new_password = NULL;
2773
2774         assert (datalen >=  (3 * sizeof(char **)));
2775
2776         string     = ((char **)data)[0];
2777         old_password = ((char **)data)[1];
2778         new_password = ((char **)data)[2];
2779
2780         asprintf(&cmd, "AT+CPWD=\"%s\",\"%s\",\"%s\"", string, old_password, new_password);
2781         err = at_send_command(cmd, NULL);
2782
2783         free(cmd);
2784
2785         if (err < 0) goto error;
2786
2787         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2788         return;
2789
2790 error:
2791         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2792 }
2793
2794 static void requestSetNetworkSelectionManual(void *data, size_t datalen, RIL_Token t)
2795 {
2796         char *operator = NULL;
2797         char *cmd = NULL;
2798         int err = 0;
2799         ATResponse *p_response = NULL;
2800
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;
2807         }
2808
2809         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2810         at_response_free(p_response);
2811         free(cmd);
2812         return;
2813
2814 error:
2815         at_response_free(p_response);
2816         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2817 }
2818
2819 static void requestQueryCLIP(void *data, size_t datalen, RIL_Token t)
2820 {
2821         ATResponse *p_response = NULL;
2822         int err;
2823         char *line;
2824         int response;
2825
2826         err = at_send_command_singleline("AT+CLIP?","+CLIP:",&p_response);
2827         if(err < 0 || p_response->success == 0) goto error;
2828
2829         line = p_response->p_intermediates->line;
2830         err = at_tok_start(&line);
2831         if(err < 0) goto error;
2832
2833         /* The first number is discarded */
2834         err = at_tok_nextint(&line, &response);
2835         if(err < 0) goto error;
2836
2837         err = at_tok_nextint(&line, &response);
2838         if(err < 0) goto error;
2839
2840         RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
2841         at_response_free(p_response);
2842         return;
2843
2844 error:
2845         at_response_free(p_response);
2846         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2847 }
2848
2849 static void requestResetRadio(RIL_Token t)
2850 {
2851         int err = 0;
2852
2853         err = at_send_command("AT+CFUN=16", NULL);
2854         if(err < 0)
2855                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2856         else
2857                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2858
2859         return;
2860 }
2861
2862 static void requestSetSuppSVCNotification(void *data, size_t datalen, RIL_Token t)
2863 {
2864         int err = 0;
2865         int enabled = 0;
2866         char *cmd = NULL;
2867         enabled = ((int *)data)[0];
2868
2869         asprintf(&cmd, "AT+CSSN=%d,%d", enabled, enabled);
2870         err = at_send_command(cmd,NULL);
2871         free(cmd);
2872         if(err < 0)
2873                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2874         else
2875                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2876 }
2877
2878 static void requestExplicitCallTransfer(RIL_Token t)
2879 {
2880         int err = 0;
2881         err = at_send_command("AT+CHLD=4",NULL);
2882         if(err < 0)
2883                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2884         else
2885                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2886 }
2887
2888 static void requestSetLocationUpdates(void *data, size_t datalen, RIL_Token t)
2889 {
2890         int err = 0;
2891         int updates = 0;
2892         char *cmd = NULL;
2893         ATResponse *p_response = NULL;
2894         updates = ((int *)data)[0] == 1? 2 : 2;
2895
2896         asprintf(&cmd, "AT+CREG=%d", updates);
2897
2898         err = at_send_command_singleline(cmd,"+CLIP:",&p_response);
2899         //if(err < 0 || p_response->success == 0) goto error;
2900
2901         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2902         at_response_free(p_response);
2903         return;
2904
2905 error:
2906         at_response_free(p_response);
2907         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2908 }
2909
2910 static void requestSTKGetprofile(RIL_Token t)
2911 {
2912         int err = 0;
2913         int responselen = 0;
2914         ATResponse *p_response = NULL;
2915         char *response = NULL;
2916         char *line = NULL;
2917
2918         err = at_send_command_singleline("AT+STKPROF?", "+STKPROF:", &p_response);
2919
2920         if(err < 0 || p_response->success == 0) goto error;
2921
2922         line = p_response->p_intermediates->line;
2923         err = at_tok_start(&line);
2924         if(err < 0) goto error;
2925
2926         err = at_tok_nextint(&line, &responselen);
2927         if(err < 0) goto error;
2928
2929         err = at_tok_nextstr(&line, &response);
2930         if(err < 0) goto error;
2931
2932         at_response_free(p_response);
2933         RIL_onRequestComplete(t, RIL_E_SUCCESS, response, responselen * sizeof(char));
2934         return;
2935
2936 error:
2937         at_response_free(p_response);
2938         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2939         return;
2940 }
2941
2942 static void requestSTKSetProfile(void * data, size_t datalen, RIL_Token t)
2943 {
2944         int err = 0;
2945         int length = 0;
2946         char *profile = NULL;
2947         char *cmd = NULL;
2948
2949         profile = (char *)data;
2950         length = strlen(profile);
2951         asprintf(&cmd, "AT+STKPROF=%d,\"%s\"", length, profile);
2952
2953         err = at_send_command(cmd, NULL);
2954         free(cmd);
2955         if(err < 0)
2956                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2957         else
2958                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2959         return;
2960 }
2961
2962 static void requestLastFailCause(RIL_Token t)
2963 {
2964         ATResponse *p_response = NULL;
2965         int err = 0;
2966         int response = 0;
2967         char *tmp = NULL;
2968         char *line = NULL;
2969
2970         err = at_send_command_singleline("AT+CEER", "+CEER:", &p_response);
2971         if(err < 0 || p_response->success == 0) goto error;
2972
2973         line = p_response->p_intermediates->line;
2974         err = at_tok_start(&line);
2975         if(err < 0) goto error;
2976
2977         err = at_tok_nextstr(&line, &tmp);
2978         if(err < 0) goto error;
2979
2980         err = at_tok_nextint(&line, &response);
2981         if(err < 0) goto error;
2982
2983         RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
2984         at_response_free(p_response);
2985         return;
2986
2987 error:
2988         at_response_free(p_response);
2989         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2990 }
2991
2992 static void requestHangupWaitingOrBackground(RIL_Token t)
2993 {
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);
2998
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);
3002 }
3003
3004 static void requestHangupForegroundResumeBackground(RIL_Token t)
3005 {
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");
3011
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);
3015 }
3016
3017 static void requestSwitchWaitingOrHoldingAndActive(RIL_Token t)
3018 {
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."
3022         if (isgsm)
3023                 at_send_command("AT+CHLD=2", NULL);
3024         else
3025                 at_send_command("AT+HTC_SENDFLASH", NULL);
3026
3027 #ifdef WORKAROUND_ERRONEOUS_ANSWER
3028         s_expectAnswer = 1;
3029 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
3030
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);
3034 }
3035
3036 static void requestAnswer(RIL_Token t)
3037 {
3038         at_send_command("ATA", NULL);
3039         writesys("audio","2");
3040
3041 #ifdef WORKAROUND_ERRONEOUS_ANSWER
3042         s_expectAnswer = 1;
3043 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
3044
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);
3048 }
3049
3050 static void requestConference(RIL_Token t)
3051 {
3052         // 3GPP 22.030 6.5.5
3053         // "Adds a held call to the conversation"
3054         at_send_command("AT+CHLD=3", NULL);
3055
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);
3059 }
3060
3061 static void requestUDUB(RIL_Token t)
3062 {
3063         /* user determined user busy */
3064         /* sometimes used: ATH */
3065         at_send_command("ATH", NULL);
3066
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);
3070
3071 }
3072
3073 static void requestSeparateConnection(void * data, size_t datalen, RIL_Token t)
3074 {
3075         char cmd[12];
3076         int party = ((int*)data)[0];
3077
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);