Android-x86
Fork
Spenden

  • R/O
  • HTTP
  • SSH
  • HTTPS

hardware-ril: Commit

hardware/ril


Commit MetaInfo

Revision59b1395df5af65ff9128dd5e28bd2673eed05d80 (tree)
Zeit2014-07-11 15:48:05
AutorChih-Wei Huang <cwhuang@linu...>
CommiterChih-Wei Huang

Log Message

update to huawei-ril 1.0.0.8

Ändern Zusammenfassung

Diff

--- a/huaweigeneric-ril/Android.mk
+++ b/huaweigeneric-ril/Android.mk
@@ -4,12 +4,15 @@ LOCAL_PATH := $(call my-dir)
44 include $(CLEAR_VARS)
55
66 LOCAL_SRC_FILES := \
7+ agc.c \
78 at_tok.c \
89 atchannel.c \
10+ echocancel.c \
911 fcp_parser.c \
1012 gsm.c \
1113 huaweigeneric-ril.c \
1214 misc.c \
15+ net-utils.c \
1316 requestdatahandler.c \
1417 sms.c \
1518 sms_gsm.c \
--- a/huaweigeneric-ril/README
+++ b/huaweigeneric-ril/README
@@ -34,3 +34,52 @@ The modules has still a few problems:
3434 ----
3535
3636 pppd must be suid ROOT, and kernel must include ppp support compiled in
37+ /system/etc/ppp/ip-up and also /system/etc/ppp/ip-down must also be suid ROOT
38+
39+----
40+
41+ You also need the following files in /system/etc/ppp
42+
43+----
44+/system/etc/ppp/ip-up:
45+
46+#!/system/bin/sh
47+case $1 in
48+ ppp1)
49+ /android/bin/iptables --flush;
50+ /android/bin/iptables --table nat --flush;
51+ /android/bin/iptables --delete-chain;
52+ /android/bin/iptables --table nat --append POSTROUTING --out-interface ppp0 -j MASQUERADE;
53+ /android/bin/iptables --append FORWARD --in-interface ppp1 -j ACCEPT;
54+ echo 0 > /proc/sys/net/ipv4/ip_forward;
55+ echo 1 > /proc/sys/net/ipv4/ip_forward;
56+ ;;
57+ ppp0)
58+ /system/bin/setprop "net.interfaces.defaultroute" "$LINKNAME";
59+ ;;
60+esac
61+
62+/system/bin/setprop "net.$LINKNAME.dns1" "$DNS1"
63+/system/bin/setprop "net.$LINKNAME.dns2" "$DNS2"
64+/system/bin/setprop "net.$LINKNAME.local-ip" "$IPLOCAL"
65+/system/bin/setprop "net.$LINKNAME.remote-ip" "$IPREMOTE"
66+/system/bin/setprop "net.$LINKNAME.gw" "$IPREMOTE"
67+/system/bin/setprop "net.$LINKNAME.if" "$IFNAME"
68+
69+
70+----
71+/system/etc/ppp/ip-down:
72+
73+#!/system/bin/sh
74+case $1 in
75+ ppp1)
76+ echo 0 > /proc/sys/net/ipv4/ip_forward;
77+ ;;
78+esac
79+
80+/system/bin/setprop "net.$LINKNAME.dns1" ""
81+/system/bin/setprop "net.$LINKNAME.dns2" ""
82+/system/bin/setprop "net.$LINKNAME.local-ip" ""
83+/system/bin/setprop "net.$LINKNAME.remote-ip" ""
84+/system/bin/setprop "net.$LINKNAME.gw" ""
85+/system/bin/setprop "net.$LINKNAME.if" ""
--- /dev/null
+++ b/huaweigeneric-ril/agc.c
@@ -0,0 +1,130 @@
1+/*
2+* This AGC algorithm was taken from isdn2h323 (http://www.telos.de). It was
3+* converted from C++ to C, and modified to add control over the recording level.
4+* Converted to fixed point by Phil Frisbie, Jr. 4/12/2003
5+*/
6+
7+#include "agc.h"
8+
9+#define LOG_NDEBUG 0
10+#define LOG_TAG "RILAudioAGC"
11+#include <utils/Log.h>
12+
13+void agc_init(struct agc_ctx* ctx, short level /* 16384-32767*/ )
14+{
15+ ALOGD("[%p] Initializing AGC: level: %d",ctx, level);
16+ ctx->sample_max = 1;
17+ ctx->counter = 0;
18+ ctx->igain = 65536;
19+ if (level < 16384) {
20+ level = 16384;
21+ }
22+ ctx->ipeak = (int)(level * 65536);
23+ ctx->silence_counter = 0;
24+}
25+
26+void agc_process_16bit(struct agc_ctx *ctx, short *buffer, int len)
27+{
28+ int i;
29+ for (i=0; i<len; i++) {
30+
31+ long gain_new;
32+ int sample;
33+
34+ /* get the abs of buffer[i] */
35+ sample = buffer[i];
36+ sample = (sample < 0 ? -(sample) : sample);
37+
38+ if(sample > (int)ctx->sample_max) {
39+ /* update the max */
40+ ctx->sample_max = (unsigned int)sample;
41+ }
42+ ctx->counter ++;
43+
44+ /* Will we get an overflow with the current gain factor? */
45+ if (((sample * ctx->igain) >> 16) > ctx->ipeak) {
46+ /* Yes: Calculate new gain. */
47+ ctx->igain = ((ctx->ipeak / ctx->sample_max) * 62259) >> 16;
48+ ctx->silence_counter = 0;
49+ buffer[i] = (short) ((buffer[i] * ctx->igain) >> 16);
50+ continue;
51+ }
52+
53+ /* Calculate new gain factor 10x per second */
54+ if (ctx->counter >= 8000/10) {
55+ if (ctx->sample_max > 800) { /* speaking? */
56+ gain_new = ((ctx->ipeak / ctx->sample_max) * 62259) >> 16;
57+
58+ if (ctx->silence_counter > 40) /* pause -> speaking */
59+ ctx->igain += (gain_new - ctx->igain) >> 2;
60+ else
61+ ctx->igain += (gain_new - ctx->igain) / 20;
62+
63+ ctx->silence_counter = 0;
64+ } else { /* silence */
65+ ctx->silence_counter++;
66+ /* silence > 2 seconds: reduce gain */
67+ if ((ctx->igain > 65536) && (ctx->silence_counter >= 20))
68+ ctx->igain = (ctx->igain * 62259) >> 16;
69+ }
70+ ctx->counter = 0;
71+ ctx->sample_max = 1;
72+ }
73+ buffer[i] = (short) ((buffer[i] * ctx->igain) >> 16);
74+ }
75+
76+ //ALOGD("[%p] Gain: %d",ctx, ctx->igain);
77+}
78+
79+void agc_process_8bit(struct agc_ctx *ctx, unsigned char *buffer, int len)
80+{
81+ int i;
82+ for (i=0; i<len; i++) {
83+
84+ long gain_new;
85+ int sample;
86+
87+ /* get the abs of buffer[i] */
88+ sample = (buffer[i] - 128) << 8;
89+ sample = (sample < 0 ? -(sample) : sample);
90+
91+ if(sample > (int)ctx->sample_max) {
92+ /* update the max */
93+ ctx->sample_max = (unsigned int)sample;
94+ }
95+ ctx->counter ++;
96+
97+ /* Will we get an overflow with the current gain factor? */
98+ if (((sample * ctx->igain) >> 16) > ctx->ipeak) {
99+ /* Yes: Calculate new gain. */
100+ ctx->igain = ((ctx->ipeak / ctx->sample_max) * 62259) >> 16;
101+ ctx->silence_counter = 0;
102+ buffer[i] = (unsigned char) (( ((buffer[i] - 128) << 8) * ctx->igain) >> 24) + 128;
103+ continue;
104+ }
105+
106+ /* Calculate new gain factor 10x per second */
107+ if (ctx->counter >= 8000/10) {
108+ if (ctx->sample_max > 800) { /* speaking? */
109+ gain_new = ((ctx->ipeak / ctx->sample_max) * 62259) >> 16;
110+
111+ if (ctx->silence_counter > 40) /* pause -> speaking */
112+ ctx->igain += (gain_new - ctx->igain) >> 2;
113+ else
114+ ctx->igain += (gain_new - ctx->igain) / 20;
115+
116+ ctx->silence_counter = 0;
117+ } else { /* silence */
118+ ctx->silence_counter++;
119+ /* silence > 2 seconds: reduce gain */
120+ if ((ctx->igain > 65536) && (ctx->silence_counter >= 20))
121+ ctx->igain = (ctx->igain * 62259) >> 16;
122+ }
123+ ctx->counter = 0;
124+ ctx->sample_max = 1;
125+ }
126+ buffer[i] = (unsigned char) (( ((buffer[i] - 128) << 8) * ctx->igain) >> 24) + 128;
127+ }
128+
129+ //ALOGD("[%p] Gain: %d",ctx, ctx->igain);
130+}
--- /dev/null
+++ b/huaweigeneric-ril/agc.h
@@ -0,0 +1,43 @@
1+/*
2+ **
3+ ** Copyright 2006, The Android Open Source Project
4+ ** Copyright 2012 Eduardo Jos[e Tagle <ejtagle@tutopia.com>
5+ **
6+ ** Licensed under the Apache License, Version 2.0 (the "License");
7+ ** you may not use this file except in compliance with the License.
8+ ** You may obtain a copy of the License at
9+ **
10+ ** http://www.apache.org/licenses/LICENSE-2.0
11+ **
12+ ** Unless required by applicable law or agreed to in writing, software
13+ ** distributed under the License is distributed on an "AS IS" BASIS,
14+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ ** See the License for the specific language governing permissions and
16+ ** limitations under the License.
17+ */
18+
19+#ifndef _AGC_H
20+#define _AGC_H
21+
22+struct agc_ctx {
23+ unsigned int sample_max;
24+ int counter;
25+ int igain;
26+ int ipeak;
27+ int silence_counter;
28+};
29+
30+#ifdef __cplusplus
31+extern "C" {
32+#endif
33+
34+void agc_init(struct agc_ctx* ctx, short level /* 16384-32767*/ );
35+void agc_process_16bit(struct agc_ctx *ctx, short *buffer, int samples);
36+void agc_process_8bit(struct agc_ctx *ctx, unsigned char *buffer, int samples);
37+
38+
39+#ifdef __cplusplus
40+}
41+#endif
42+
43+#endif
--- a/huaweigeneric-ril/at_tok.c
+++ b/huaweigeneric-ril/at_tok.c
@@ -27,16 +27,18 @@
2727 */
2828 int at_tok_start(char **p_cur)
2929 {
30- if (*p_cur == NULL)
30+ if (*p_cur == NULL) {
3131 return -1;
32+ }
3233
3334 /* Skip prefix,
3435 consume "^[^:]:". */
3536
3637 *p_cur = strchr(*p_cur, ':');
3738
38- if (*p_cur == NULL)
39+ if (*p_cur == NULL) {
3940 return -1;
41+ }
4042
4143 (*p_cur)++;
4244
@@ -45,33 +47,34 @@ int at_tok_start(char **p_cur)
4547
4648 static void skipWhiteSpace(char **p_cur)
4749 {
48- if (*p_cur == NULL)
49- return;
50+ if (*p_cur == NULL) return;
5051
51- while (**p_cur != '\0' && isspace(**p_cur))
52+ while (**p_cur != '\0' && isspace(**p_cur)) {
5253 (*p_cur)++;
5354 }
55+}
5456
5557 static void skipNextComma(char **p_cur)
5658 {
57- if (*p_cur == NULL)
58- return;
59+ if (*p_cur == NULL) return;
5960
60- while (**p_cur != '\0' && **p_cur != ',')
61+ while (**p_cur != '\0' && **p_cur != ',') {
6162 (*p_cur)++;
63+ }
6264
63- if (**p_cur == ',')
65+ if (**p_cur == ',') {
6466 (*p_cur)++;
6567 }
68+}
6669
6770 /**
6871 * If the first none space character is a quotation mark, returns the string
6972 * between two quotation marks, else returns the content before the first comma.
7073 * Updates *p_cur.
7174 */
72-static char * nextTok(char **p_cur)
75+static char *nextTok(char **p_cur)
7376 {
74- char *ret = NULL;
77+ char *ret;
7578
7679 skipWhiteSpace(p_cur);
7780
@@ -85,47 +88,48 @@ static char * nextTok(char **p_cur)
8588
8689 while (state != END) {
8790 switch (state) {
88- case NORMAL:
89- switch (**p_cur) {
90- case '\\':
91- state = ESCAPE;
91+ case NORMAL:
92+ switch (**p_cur) {
93+ case '\\':
94+ state = ESCAPE;
95+ break;
96+ case '"':
97+ state = END;
98+ break;
99+ case '\0':
100+ /*
101+ * Error case, parsing string is not quoted by ending
102+ * double quote, e.g. "bla bla, this function expects input
103+ * string to be NULL terminated, so that the loop can exit.
104+ */
105+ ret = NULL;
106+ goto exit;
107+ default:
108+ /* Stays in normal case. */
109+ break;
110+ }
92111 break;
93- case '"':
94- state = END;
112+
113+ case ESCAPE:
114+ state = NORMAL;
95115 break;
96- case '\0':
97- /*
98- * Error case, parsing string is not quoted by ending
99- * double quote, e.g. "bla bla, this function expects input
100- * string to be NULL terminated, so that the loop can exit.
101- */
102- ret = NULL;
103- goto exit;
116+
104117 default:
105- /* Stays in normal case. */
118+ /* This should never happen. */
106119 break;
107- }
108- break;
109-
110- case ESCAPE:
111- state = NORMAL;
112- break;
113-
114- default:
115- /* This should never happen. */
116- break;
117120 }
118121
119122 if (state == END) {
120123 **p_cur = '\0';
121124 }
122125
123- (*p_cur)++;
126+ (*p_cur)++;
124127 }
125128 skipNextComma(p_cur);
126129 } else {
127130 ret = strsep(p_cur, ",");
128131 }
132+
129133 exit:
130134 return ret;
131135 }
@@ -148,9 +152,9 @@ static int at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns)
148152
149153 ret = nextTok(p_cur);
150154
151- if (ret == NULL)
155+ if (ret == NULL) {
152156 return -1;
153- else {
157+ } else {
154158 long l;
155159 char *end;
156160
@@ -161,8 +165,9 @@ static int at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns)
161165
162166 *p_out = (int)l;
163167
164- if (end == ret)
168+ if (end == ret) {
165169 return -1;
170+ }
166171 }
167172
168173 return 0;
@@ -197,29 +202,34 @@ int at_tok_nextbool(char **p_cur, char *p_out)
197202
198203 ret = at_tok_nextint(p_cur, &result);
199204
200- if (ret < 0)
205+ if (ret < 0) {
201206 return -1;
207+ }
202208
203209 /* Booleans should be 0 or 1. */
204- if (!(result == 0 || result == 1))
210+ if (!(result == 0 || result == 1)) {
205211 return -1;
212+ }
206213
207- if (p_out != NULL)
214+ if (p_out != NULL) {
208215 *p_out = (char)result;
209- else
216+ } else {
210217 return -1;
218+ }
211219
212220 return ret;
213221 }
214222
215223 int at_tok_nextstr(char **p_cur, char **p_out)
216224 {
217- if (*p_cur == NULL)
225+ if (*p_cur == NULL) {
218226 return -1;
227+ }
219228
220229 *p_out = nextTok(p_cur);
221- if (*p_out == NULL)
230+ if (*p_out == NULL) {
222231 return -1;
232+ }
223233
224234 return 0;
225235 }
@@ -236,8 +246,9 @@ int at_tok_charcounter(char *p_in, char needle, int *p_out)
236246 char *p_cur = p_in;
237247 int num_found = 0;
238248
239- if (p_in == NULL)
249+ if (p_in == NULL) {
240250 return -1;
251+ }
241252
242253 while (*p_cur != '\0') {
243254 if (*p_cur == needle) {
--- a/huaweigeneric-ril/atchannel.c
+++ b/huaweigeneric-ril/atchannel.c
@@ -138,14 +138,12 @@ static int initializeAtContext(void)
138138 ac = (struct atcontext *)pthread_getspecific(key);
139139
140140 if (ac == NULL) {
141- ac = (struct atcontext *) malloc(sizeof(struct atcontext));
141+ ac = (struct atcontext *) calloc(1, sizeof(struct atcontext));
142142 if (ac == NULL) {
143143 ALOGE("%s() Failed to allocate memory", __func__);
144144 goto error;
145145 }
146146
147- memset(ac, 0, sizeof(struct atcontext));
148-
149147 ac->fd = -1;
150148 ac->readerCmdFds[0] = -1;
151149 ac->readerCmdFds[1] = -1;
@@ -223,8 +221,8 @@ void AT_DUMP(const char* prefix, const char* buff, int len)
223221
224222 #ifndef HAVE_ANDROID_OS
225223 int pthread_cond_timeout_np(pthread_cond_t *cond,
226- pthread_mutex_t * mutex,
227- unsigned msecs)
224+ pthread_mutex_t * mutex,
225+ unsigned msecs)
228226 {
229227 struct timespec ts;
230228 clock_gettime(CLOCK_REALTIME, &ts);
@@ -280,6 +278,7 @@ static const char * s_finalResponsesError[] = {
280278 "NO CARRIER", /* Sometimes! */
281279 "NO ANSWER",
282280 "NO DIALTONE",
281+ "COMMAND NOT SUPPORT",
283282 };
284283
285284 static int isFinalResponseError(const char *line)
@@ -425,7 +424,7 @@ static void processLine(const char *line)
425424 *
426425 * returns NULL if there is no complete line.
427426 */
428-static char * findNextEOL(char *cur)
427+static char *findNextEOL(char *cur)
429428 {
430429 if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') {
431430 /* SMS prompt character...not \r terminated */
@@ -458,7 +457,7 @@ static const char *readline(void)
458457 char *ret = NULL;
459458
460459 struct atcontext *ac = getAtContext();
461- read(ac->fd,NULL,0);
460+ read(ac->fd, NULL, 0);
462461
463462 /* This is a little odd. I use *s_ATBufferCur == 0 to mean
464463 * "buffer consumed completely". If it points to a character,
@@ -473,8 +472,9 @@ static const char *readline(void)
473472 /* There's data in the buffer from the last read. */
474473
475474 /* skip over leading newlines */
476- while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n')
475+ while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n') {
477476 ac->ATBufferCur++;
477+ }
478478
479479 p_eol = findNextEOL(ac->ATBufferCur);
480480
@@ -540,14 +540,14 @@ static const char *readline(void)
540540 if (!(pfds[0].revents & POLLIN))
541541 continue;
542542
543- do
543+ do {
544544 /* The size argument should be synchronized to the ditch buffer
545545 * condition above.
546546 */
547547 count = read(ac->fd, p_read,
548548 MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2);
549549
550- while (count < 0 && errno == EINTR);
550+ } while (count < 0 && errno == EINTR);
551551
552552 if (count > 0) {
553553 AT_DUMP( "<< ", p_read, count );
@@ -626,7 +626,7 @@ static void *readerLoop(void *arg)
626626 if (line == NULL)
627627 break;
628628
629- if(isSMSUnsolicited(line)) {
629+ if (isSMSUnsolicited(line)) {
630630 char *line1;
631631 const char *line2;
632632
@@ -645,9 +645,10 @@ static void *readerLoop(void *arg)
645645 ac->unsolHandler(line1, line2);
646646
647647 free(line1);
648- } else
648+ } else {
649649 processLine(line);
650650 }
651+ }
651652
652653 onReaderClosed();
653654 ALOGI("Exiting readerloop!");
@@ -751,21 +752,21 @@ static void clearPendingCommand(void)
751752 ac->response = NULL;
752753 ac->responsePrefix = NULL;
753754 ac->smsPDU = NULL;
754- }
755+}
755756
756757 static AT_Error merror(int type, int error)
757758 {
758759 switch(type) {
759- case AT_ERROR :
760- return (AT_Error)(AT_ERROR_BASE + error);
761- case CME_ERROR :
762- return (AT_Error)(CME_ERROR_BASE + error);
763- case CMS_ERROR:
764- return (AT_Error)(CMS_ERROR_BASE + error);
765- case GENERIC_ERROR:
766- return (AT_Error)(GENERIC_ERROR_BASE + error);
767- default:
768- return (AT_Error)(GENERIC_ERROR_UNSPECIFIED);
760+ case AT_ERROR :
761+ return (AT_Error)(AT_ERROR_BASE + error);
762+ case CME_ERROR :
763+ return (AT_Error)(CME_ERROR_BASE + error);
764+ case CMS_ERROR:
765+ return (AT_Error)(CMS_ERROR_BASE + error);
766+ case GENERIC_ERROR:
767+ return (AT_Error)(GENERIC_ERROR_BASE + error);
768+ default:
769+ return (AT_Error)(GENERIC_ERROR_UNSPECIFIED);
769770 }
770771 }
771772
@@ -796,7 +797,7 @@ static AT_Error at_get_error(const ATResponse *p_response)
796797 if (err < 0)
797798 return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);
798799
799- if(strStartsWith(p_response->finalResponse, "+CME ERROR:"))
800+ if (strStartsWith(p_response->finalResponse, "+CME ERROR:"))
800801 return merror(CME_ERROR, ret);
801802 else if (strStartsWith(p_response->finalResponse, "+CMS ERROR:"))
802803 return merror(CMS_ERROR, ret);
@@ -902,8 +903,8 @@ void at_response_free(ATResponse *p_response)
902903 free(p_toFree);
903904 }
904905
905- free (p_response->finalResponse);
906- free (p_response);
906+ free(p_response->finalResponse);
907+ free(p_response);
907908 }
908909
909910 /**
@@ -932,11 +933,10 @@ static void reverseIntermediates(ATResponse *p_response)
932933 * timeoutMsec == 0 means infinite timeout.
933934 */
934935 static int at_send_command_full_nolock (const char *command, ATCommandType type,
935- const char *responsePrefix, const char *smspdu,
936- long long timeoutMsec, ATResponse **pp_outResponse)
936+ const char *responsePrefix, const char *smspdu,
937+ long long timeoutMsec, ATResponse **pp_outResponse)
937938 {
938939 int err = AT_NOERROR;
939-
940940 struct atcontext *ac = getAtContext();
941941
942942 /* Default to NULL, to allow caller to free securely even if
@@ -962,7 +962,7 @@ static int at_send_command_full_nolock (const char *command, ATCommandType type,
962962 goto finally;
963963 }
964964
965- err = writeline (command);
965+ err = writeline(command);
966966
967967 if (err != AT_NOERROR)
968968 goto finally;
@@ -977,15 +977,15 @@ static int at_send_command_full_nolock (const char *command, ATCommandType type,
977977 err = AT_ERROR_TIMEOUT;
978978 goto finally;
979979 }
980- }
980+ }
981981
982982 if (ac->response->success == 0) {
983983 err = at_get_error(ac->response);
984984 }
985985
986- if (pp_outResponse == NULL)
986+ if (pp_outResponse == NULL) {
987987 at_response_free(ac->response);
988- else {
988+ } else {
989989 /* Line reader stores intermediate responses in reverse order. */
990990 reverseIntermediates(ac->response);
991991 *pp_outResponse = ac->response;
@@ -993,7 +993,7 @@ static int at_send_command_full_nolock (const char *command, ATCommandType type,
993993
994994 ac->response = NULL;
995995
996- if(ac->readerClosed > 0) {
996+ if (ac->readerClosed > 0) {
997997 err = AT_ERROR_CHANNEL_CLOSED;
998998 goto finally;
999999 }
@@ -1013,8 +1013,8 @@ finally:
10131013 * timeoutMsec == 0 means infinite timeout.
10141014 */
10151015 static int at_send_command_full (const char *command, ATCommandType type,
1016- const char *responsePrefix, const char *smspdu,
1017- long long timeoutMsec, ATResponse **pp_outResponse, int useap, va_list ap)
1016+ const char *responsePrefix, const char *smspdu,
1017+ long long timeoutMsec, ATResponse **pp_outResponse, int useap, va_list ap)
10181018 {
10191019 int err;
10201020
@@ -1029,16 +1029,17 @@ static int at_send_command_full (const char *command, ATCommandType type,
10291029 pthread_mutex_lock(&ac->commandmutex);
10301030 if (useap) {
10311031 if (!vsnprintf(strbuf, BUFFSIZE, command, ap)) {
1032- pthread_mutex_unlock(&ac->commandmutex);
1033- return AT_ERROR_STRING_CREATION;
1034- }
1032+ pthread_mutex_unlock(&ac->commandmutex);
1033+ return AT_ERROR_STRING_CREATION;
1034+ }
10351035 ptr = strbuf;
1036- } else
1036+ } else {
10371037 ptr = command;
1038+ }
10381039
10391040 err = at_send_command_full_nolock(ptr, type,
1040- responsePrefix, smspdu,
1041- timeoutMsec, pp_outResponse);
1041+ responsePrefix, smspdu,
1042+ timeoutMsec, pp_outResponse);
10421043
10431044 pthread_mutex_unlock(&ac->commandmutex);
10441045
@@ -1054,9 +1055,9 @@ void at_send_escape (void)
10541055 struct atcontext *ac = getAtContext();
10551056 int written;
10561057
1057- do
1058+ do {
10581059 written = write (ac->fd, "\033" , 1);
1059- while ((written < 0 && errno == EINTR) || (written == 0));
1060+ } while ((written < 0 && errno == EINTR) || (written == 0));
10601061 }
10611062
10621063 /**
@@ -1102,8 +1103,8 @@ int at_send_command_raw (const char *command, ATResponse **pp_outResponse)
11021103 }
11031104
11041105 int at_send_command_singleline (const char *command,
1105- const char *responsePrefix,
1106- ATResponse **pp_outResponse, ...)
1106+ const char *responsePrefix,
1107+ ATResponse **pp_outResponse, ...)
11071108 {
11081109 int err;
11091110
@@ -1111,8 +1112,8 @@ int at_send_command_singleline (const char *command,
11111112 va_list ap;
11121113 va_start(ap, pp_outResponse);
11131114
1114- err = at_send_command_full (command, SINGLELINE, responsePrefix,
1115- NULL, ac->timeoutMsec, pp_outResponse, 1, ap);
1115+ err = at_send_command_full(command, SINGLELINE, responsePrefix,
1116+ NULL, ac->timeoutMsec, pp_outResponse, 1, ap);
11161117
11171118 if (err == AT_NOERROR && pp_outResponse != NULL
11181119 && (*pp_outResponse) != NULL
@@ -1136,14 +1137,14 @@ int at_send_command_singleline (const char *command,
11361137 }
11371138
11381139 int at_send_command_numeric (const char *command,
1139- ATResponse **pp_outResponse)
1140+ ATResponse **pp_outResponse)
11401141 {
11411142 int err;
11421143
11431144 struct atcontext *ac = getAtContext();
11441145
1145- err = at_send_command_full (command, NUMERIC, NULL,
1146- NULL, ac->timeoutMsec, pp_outResponse, 0, empty);
1146+ err = at_send_command_full(command, NUMERIC, NULL,
1147+ NULL, ac->timeoutMsec, pp_outResponse, 0, empty);
11471148
11481149 if (err == AT_NOERROR && pp_outResponse != NULL
11491150 && (*pp_outResponse) != NULL
@@ -1166,16 +1167,16 @@ int at_send_command_numeric (const char *command,
11661167
11671168
11681169 int at_send_command_sms (const char *command,
1169- const char *pdu,
1170- const char *responsePrefix,
1171- ATResponse **pp_outResponse)
1170+ const char *pdu,
1171+ const char *responsePrefix,
1172+ ATResponse **pp_outResponse)
11721173 {
11731174 int err;
11741175
11751176 struct atcontext *ac = getAtContext();
11761177
1177- err = at_send_command_full (command, SINGLELINE, responsePrefix,
1178- pdu, ac->timeoutMsec, pp_outResponse, 0, empty);
1178+ err = at_send_command_full(command, SINGLELINE, responsePrefix,
1179+ pdu, ac->timeoutMsec, pp_outResponse, 0, empty);
11791180
11801181 if (err == AT_NOERROR && pp_outResponse != NULL
11811182 && (*pp_outResponse) != NULL
@@ -1198,8 +1199,8 @@ int at_send_command_sms (const char *command,
11981199
11991200
12001201 int at_send_command_multiline (const char *command,
1201- const char *responsePrefix,
1202- ATResponse **pp_outResponse, ...)
1202+ const char *responsePrefix,
1203+ ATResponse **pp_outResponse, ...)
12031204 {
12041205 int err;
12051206
@@ -1208,7 +1209,7 @@ int at_send_command_multiline (const char *command,
12081209 va_start(ap, pp_outResponse);
12091210
12101211 err = at_send_command_full (command, MULTILINE, responsePrefix,
1211- NULL, ac->timeoutMsec, pp_outResponse, 1, ap);
1212+ NULL, ac->timeoutMsec, pp_outResponse, 1, ap);
12121213 va_end(ap);
12131214
12141215 /* Free response in case of error */
@@ -1304,7 +1305,7 @@ AT_Error at_get_at_error(int error)
13041305 return (AT_Error)(error - AT_ERROR_BASE);
13051306 else
13061307 return AT_ERROR_NON_AT;
1307- }
1308+}
13081309
13091310 AT_CME_Error at_get_cme_error(int error)
13101311 {
@@ -1313,7 +1314,7 @@ AT_CME_Error at_get_cme_error(int error)
13131314 return (AT_CME_Error)(error - CME_ERROR_BASE);
13141315 else
13151316 return CME_ERROR_NON_CME;
1316- }
1317+}
13171318
13181319 AT_CMS_Error at_get_cms_error(int error)
13191320 {
@@ -1331,7 +1332,7 @@ AT_Generic_Error at_get_generic_error(int error)
13311332 return (AT_Generic_Error)(error - GENERIC_ERROR_BASE);
13321333 else
13331334 return GENERIC_ERROR_NON_GENERIC;
1334- }
1335+}
13351336
13361337 AT_Error_type at_get_error_type(int error)
13371338 {
@@ -1352,7 +1353,7 @@ AT_Error_type at_get_error_type(int error)
13521353 return GENERIC_ERROR;
13531354
13541355 return UNKNOWN_ERROR;
1355- }
1356+}
13561357
13571358 #define quote(x) #x
13581359
@@ -1361,17 +1362,17 @@ const char *at_str_err(int error)
13611362 const char *s = "--UNKNOWN--";
13621363
13631364 error = -error;
1364- switch(error) {
1365+ switch (error) {
13651366 #define AT(name, num) case num + AT_ERROR_BASE: s = quote(AT_##name); break;
13661367 #define CME(name, num) case num + CME_ERROR_BASE: s = quote(CME_##name); break;
13671368 #define CMS(name, num) case num + CMS_ERROR_BASE: s = quote(CMS_##name); break;
13681369 #define GENERIC(name, num) case num + GENERIC_ERROR_BASE: s = quote(GENERIC_##name); break;
1369- mbm_error
1370+ mbm_error
13701371 #undef AT
13711372 #undef CME
13721373 #undef CMS
13731374 #undef GENERIC
1374-}
1375+ }
13751376
13761377 return s;
13771378 }
--- a/huaweigeneric-ril/atchannel.h
+++ b/huaweigeneric-ril/atchannel.h
@@ -99,17 +99,17 @@ void at_set_on_reader_closed(void (*onClose)(void));
9999 void at_send_escape(void);
100100
101101 int at_send_command_singleline (const char *command,
102- const char *responsePrefix,
103- ATResponse **pp_outResponse,
104- ...);
102+ const char *responsePrefix,
103+ ATResponse **pp_outResponse,
104+ ...);
105105
106106 int at_send_command_numeric (const char *command,
107- ATResponse **pp_outResponse);
107+ ATResponse **pp_outResponse);
108108
109109 int at_send_command_multiline (const char *command,
110- const char *responsePrefix,
111- ATResponse **pp_outResponse,
112- ...);
110+ const char *responsePrefix,
111+ ATResponse **pp_outResponse,
112+ ...);
113113
114114
115115 int at_handshake(void);
@@ -124,8 +124,8 @@ int at_send_command (const char *command, ...);
124124 int at_send_command_raw (const char *command, ATResponse **pp_outResponse);
125125
126126 int at_send_command_sms (const char *command, const char *pdu,
127- const char *responsePrefix,
128- ATResponse **pp_outResponse);
127+ const char *responsePrefix,
128+ ATResponse **pp_outResponse);
129129
130130 void at_response_free(ATResponse *p_response);
131131
--- a/huaweigeneric-ril/audiochannel.cpp
+++ b/huaweigeneric-ril/audiochannel.cpp
@@ -26,6 +26,16 @@
2626 #include <unistd.h>
2727 #include <fcntl.h>
2828 #include <sys/types.h>
29+#include <sys/epoll.h>
30+#include <semaphore.h>
31+#include <signal.h>
32+#include <linux/socket.h>
33+#include <sys/socket.h>
34+#include <errno.h>
35+#include <stddef.h>
36+#include <sys/time.h>
37+#include <sys/select.h>
38+
2939 #include "audiochannel.h"
3040
3141 #define LOG_NDEBUG 0
@@ -39,237 +49,568 @@
3949
4050 // ---- Android sound streaming ----
4151
42-/* modemAudioOut:
43- Output an audio frame (160 samples) to the 3G audio port of the cell modem
52+/* Audio oversampling factor. To use higher sampling rates reduces latency quite a bit ... */
53+#define AUDIO_OVERSAMPLING 1
4454
45- data = Pointer to audio data to write
55+// #define CHECK_MEM_OVERRUN 1
56+#define AUDIOCHANNEL_DEBUG 0
57+#if AUDIOCHANNEL_DEBUG
58+# define D(...) ALOGD(__VA_ARGS__)
59+#else
60+# define D(...) ((void)0)
61+#endif
4662
47-*/
48-static int modemAudioOut(struct GsmAudioTunnel* ctx,const void* data)
63+static inline int labs(int x)
4964 {
50- if (ctx->fd == -1)
51- return 0;
52-
53- // Write audio to the 3G modem audio port in 320 bytes chunks... This is
54- // required by huawei modems...
55-
56- // Write audio chunk
57- int res = write(ctx->fd, data, ctx->frame_size * (ctx->bits_per_sample/8));
58- if (res < 0)
59- return -1;
60-
61- // Write a 0 length frame to post data
62- res = write(ctx->fd, data, 0);
63- if (res < 0)
64- return -1;
65-
66- return 0;
65+ return (x < 0) ? -x : x;
6766 }
6867
69-/* modemAudioIn:
70- Input an audio frame (160 samples) from the 3G audio port of the cell modem
71-
72- data = Pointer to buffer where data must be stored
68+/* modemAudioIOThread:
69+ Output/inputs an audio frame (160 samples) to the 3G audio port of the cell modem
70+ We need to write to be able to read from modem
7371 */
74-static int modemAudioIn(struct GsmAudioTunnel* ctx, void* data)
72+static void* modemAudioIOThread(void* data)
7573 {
74+ int n;
75+ int max_fd;
76+ fd_set input;
77+ struct timeval timeout;
78+
79+ struct GsmAudioTunnel* ctx = (struct GsmAudioTunnel*)data;
7680 int res = 0;
77- if (ctx->fd == -1)
78- return 0;
81+ int bps = (ctx->bits_per_sample/8);
82+ int frame_bytes = ctx->frame_size * bps;
83+
84+ ALOGD("modemAudioIOThread begin");
85+
86+ // Discard all pending data*/
87+ ALOGD("Discarding old data....");
88+ tcflush(ctx->fd, TCIOFLUSH);
89+ ALOGD("Discarding old data... Done");
90+
91+ // Get audio from the queue and push it into the modem
92+ while (AudioQueue_isrunning(&ctx->rec_q) &&
93+ AudioQueue_isrunning(&ctx->play_q)) {
94+
95+ // Write audio to the 3G modem audio port in 320 bytes chunks... This is
96+ // required by huawei modems...
97+ D("[T]Before AudioQueue_get");
98+ res = AudioQueue_get(&ctx->rec_q,ctx->play_buf,ctx->frame_size, ctx->timeout);
99+ D("[T]After AudioQueue_get: 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x",
100+ ((short*)ctx->play_buf)[0],((short*)ctx->play_buf)[1],
101+ ((short*)ctx->play_buf)[2],((short*)ctx->play_buf)[3],
102+ ((short*)ctx->play_buf)[4]);
103+
104+#ifdef CHECK_MEM_OVERRUN
105+ if (((int*)ctx->rec_buf)[-1] != 0x1A3B5C7D) {
106+ ALOGE("recbuf: Corruption at start: 0x%08x",((int*)ctx->rec_buf)[-1]);
107+ }
108+ if (((int*)ctx->rec_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
109+ ALOGE("recbuf: Corruption at end: 0x%08x",((int*)ctx->rec_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
110+ }
111+ if (((int*)ctx->play_buf)[-1] != 0x1A3B5C7D) {
112+ ALOGE("playbuf: Corruption at start: 0x%08x",((int*)ctx->play_buf)[-1]);
113+ }
114+ if (((int*)ctx->play_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
115+ ALOGE("playbuf: Corruption at end: 0x%08x",((int*)ctx->play_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
116+ }
117+#endif
118+
119+ if (!AudioQueue_isrunning(&ctx->rec_q) ||
120+ !AudioQueue_isrunning(&ctx->play_q))
121+ break;
79122
123+ /* Fill missing samples with silence, if needed */
124+ if ((int)ctx->frame_size > res) {
125+ memset((char*)ctx->play_buf + res * bps, 0, (ctx->frame_size - res) * bps);
126+ }
127+
128+#ifdef CHECK_MEM_OVERRUN
129+ if (((int*)ctx->rec_buf)[-1] != 0x1A3B5C7D) {
130+ ALOGE("recbuf: Corruption at start: 0x%08x",((int*)ctx->rec_buf)[-1]);
131+ }
132+ if (((int*)ctx->rec_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
133+ ALOGE("recbuf: Corruption at end: 0x%08x",((int*)ctx->rec_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
134+ }
135+ if (((int*)ctx->play_buf)[-1] != 0x1A3B5C7D) {
136+ ALOGE("playbuf: Corruption at start: 0x%08x",((int*)ctx->play_buf)[-1]);
137+ }
138+ if (((int*)ctx->play_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
139+ ALOGE("playbuf: Corruption at end: 0x%08x",((int*)ctx->play_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
140+ }
141+#endif
80142
81- while (1) {
82- res = read(ctx->fd, data, ctx->frame_size * (ctx->bits_per_sample/8));
83- if (res == -1) {
143+ // Write audio chunk
144+ D("[T]Before write");
145+ res = write(ctx->fd, ctx->play_buf, frame_bytes);
146+ D("[T]After write: res: %d",res);
84147
85- if (errno != EAGAIN && errno != EINTR) {
86- // A real error, not something that trying again will fix
87- break;
88- }
89- } else {
148+ if (!AudioQueue_isrunning(&ctx->rec_q) ||
149+ !AudioQueue_isrunning(&ctx->play_q) ||
150+ res < 0)
90151 break;
91- }
92- }
93152
94- /* Failure means 0 bytes */
95- if (res < 0)
96- res = 0;
153+ // Read data from the modem
154+ D("[T]Before Select");
97155
98- /* If some samples missing, complete them with silence */
99- if (res < (int) (ctx->frame_size * (ctx->bits_per_sample/8) )) {
156+ do {
157+ // Initialize the input set
158+ FD_ZERO(&input);
159+ FD_SET(ctx->fd, &input);
160+ max_fd = ctx->fd + 1;
100161
101- /* Output silence */
102- memset( (char*)data + res, 0, (ctx->frame_size * (ctx->bits_per_sample/8) - res));
103- }
162+ // Initialize the timeout structure: 40ms is enough for this waiting
163+ timeout.tv_sec = 0;
164+ timeout.tv_usec = 40000;
104165
105- return 0;
106-}
166+ // Do the select
167+ n = select(max_fd, &input, NULL, NULL, &timeout);
107168
108-static void AndroidRecorderCallback(int event, void* userData, void* info)
109-{
110- struct GsmAudioTunnel *ctx = (struct GsmAudioTunnel*) userData;
111- android::AudioRecord::Buffer* uinfo = (android::AudioRecord::Buffer*) info;
112- unsigned nsamples;
113- void *input;
169+ } while (n == 0 &&
170+ AudioQueue_isrunning(&ctx->rec_q) &&
171+ AudioQueue_isrunning(&ctx->play_q));
114172
115- if(!ctx || !uinfo)
116- return;
173+ D("[T]After Select");
117174
118- if (ctx->quit_flag)
119- goto on_break;
175+ /* See if there was an error */
176+ if (!AudioQueue_isrunning(&ctx->rec_q) ||
177+ !AudioQueue_isrunning(&ctx->play_q) ||
178+ n < 0)
179+ break;
120180
121- input = (void *) uinfo->raw;
181+ /* If something to read, read it */
182+ if (FD_ISSET(ctx->fd, &input)) {
183+ D("[T]Before read");
184+ res = read(ctx->fd, ctx->rec_buf, frame_bytes);
185+ D("[T]After read: res: %d",res);
122186
123- // Calculate number of total samples we've got
124- nsamples = uinfo->frameCount + ctx->rec_buf_count;
187+ if (!AudioQueue_isrunning(&ctx->play_q) ||
188+ !AudioQueue_isrunning(&ctx->rec_q) ||
189+ res < 0)
190+ break;
125191
126- if (nsamples >= ctx->frame_size) {
192+#ifdef CHECK_MEM_OVERRUN
193+ if (((int*)ctx->rec_buf)[-1] != 0x1A3B5C7D) {
194+ ALOGE("recbuf: Corruption at start: 0x%08x",((int*)ctx->rec_buf)[-1]);
195+ }
196+ if (((int*)ctx->rec_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
197+ ALOGE("recbuf: Corruption at end: 0x%08x",((int*)ctx->rec_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
198+ }
199+ if (((int*)ctx->play_buf)[-1] != 0x1A3B5C7D) {
200+ ALOGE("playbuf: Corruption at start: 0x%08x",((int*)ctx->play_buf)[-1]);
201+ }
202+ if (((int*)ctx->play_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
203+ ALOGE("playbuf: Corruption at end: 0x%08x",((int*)ctx->play_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
204+ }
205+#endif
127206
128- /* If buffer is not empty, combine the buffer with the just incoming
129- * samples, then call put_frame.
130- */
131- if (ctx->rec_buf_count) {
207+ // If muted, silence audio
208+ if (ctx->ismuted) {
209+ memset( ctx->rec_buf, 0, frame_bytes);
210+ }
132211
133- unsigned chunk_count = ctx->frame_size - ctx->rec_buf_count;
134- memcpy( (char*)ctx->rec_buf + ctx->rec_buf_count * (ctx->bits_per_sample/8), input, chunk_count * (ctx->bits_per_sample/8));
212+#ifdef CHECK_MEM_OVERRUN
213+ if (((int*)ctx->rec_buf)[-1] != 0x1A3B5C7D) {
214+ ALOGE("recbuf: Corruption at start: 0x%08x",((int*)ctx->rec_buf)[-1]);
215+ }
216+ if (((int*)ctx->rec_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
217+ ALOGE("recbuf: Corruption at end: 0x%08x",((int*)ctx->rec_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
218+ }
219+ if (((int*)ctx->play_buf)[-1] != 0x1A3B5C7D) {
220+ ALOGE("playbuf: Corruption at start: 0x%08x",((int*)ctx->play_buf)[-1]);
221+ }
222+ if (((int*)ctx->play_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
223+ ALOGE("playbuf: Corruption at end: 0x%08x",((int*)ctx->play_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
224+ }
225+#endif
226+
227+ // EM770W firmware corrupts received audio... Try to workaround the damage...
228+
229+ // 1st Pass: If received less data than requested, this means voice data corruption.
230+ // More frequent than you could think. We must compensate it, or we end with garbled
231+ // voice...
232+ if (res < frame_bytes) {
233+ int p;
234+ signed char* b;
235+ int tf;
236+
237+
238+ // Try to reconstruct data . Determine variance of low and high nibbles.
239+ b = (signed char*)ctx->rec_buf;
240+ tf = frame_bytes - res;
241+ for (p = 0; p < 317 && tf!=0; p+=2) {
242+ if (labs(b[p+2] - b[p]) < labs(b[p+1] - b[p+3]) ) {
243+ /* Probably, this is the point ... Insert an space */
244+ memmove(b+p+1,b+p,320-p-1);
245+ tf--;
246+ p+=2;
247+ }
248+ }
249+ }
135250
136- /* Send the audio to the modem */
137- modemAudioOut(ctx, ctx->rec_buf);
251+ /* 2nd pass: Detect endianness inversions and correct them */
252+ {
253+ signed short* d = (signed short*)ctx->rec_buf;
254+ signed short ss, sp = 0, s = d[2]; // Handle first sample by reflection
255+ int todo = 160;
256+
257+ while (todo--) {
258+ sp = s; /* keep previous sample */
259+ s = *d++; /* Calculate the other possible samples */
260+ ss = (((unsigned short)s) << 8U) | ((((unsigned short)s) >> 8U) & 0xFFU);
261+
262+ /* Choose the one that creates less volume difference */
263+ if (labs(sp - ss ) < labs(sp - s ) ) {
264+ /* Inverted is closer to original. Keep inverted */
265+ s = ss;
266+ d[-1] = s;
267+ }
268+ }
269+ }
138270
139- input = (char*) input + chunk_count * (ctx->bits_per_sample/8);
140- nsamples -= ctx->frame_size;
141- ctx->rec_buf_count = 0;
271+ /* 3rd pass: Remove clicks - we use a 3 sample window to predict and correct 1-sample clicks...*/
272+ {
273+ signed short* d = (signed short*)ctx->rec_buf;
274+ signed short spp = 0, sp = *d++, s = *d++;
275+ signed short p;
276+ int todo = 158;
277+
278+ while (todo--) {
279+ /* Store previous and get new sample */
280+ spp = sp;
281+ sp = s;
282+ s = *d++;
283+
284+ /* Estimate medium */
285+ p = (s + spp) / 2;
286+
287+ /* If predicted is very different from real, assume noise and replace it */
288+ if ( labs( sp - p ) > labs(p >> 2) ) {
289+ sp = p;
290+ d[-2] = sp;
291+ }
292+ }
293+ }
294+
295+ /* 4th pass: Remove 6 Sample clicks... The modem also sometimes creates them. Detect and remove them if possible */
296+ {
297+ signed short* d = (signed short*)ctx->rec_buf;
298+ signed short sp = 0, s = *d++;
299+ signed short p;
300+ int todo = 154;
301+
302+ while (todo--) {
303+ /* Store previous and get new sample */
304+ sp = s;
305+ s = *d++;
306+
307+ /* If a 4 times jump in value is detected, and 6 samples later we are on track, assume it is a modem generated
308+ click and remove it - We prefer to remove in excess here*/
309+ if (labs(s) > labs(sp )*4 &&
310+ labs(s) > labs(d[6])*4 ) {
311+
312+ /* Detected an undesired click, remove it! */
313+ int step = ((d[6] - sp) << (16 - 3));
314+ int x = sp << 16;
315+ x+= step;
316+ s = d[-1] = x >> 16;
317+ x+= step;
318+ d[ 0] = x >> 16;
319+ x+= step;
320+ d[ 1] = x >> 16;
321+ x+= step;
322+ d[ 2] = x >> 16;
323+ x+= step;
324+ d[ 3] = x >> 16;
325+ x+= step;
326+ d[ 4] = x >> 16;
327+ x+= step;
328+ d[ 5] = x >> 16;
329+ }
330+ }
331+ }
332+
333+#if LOG_MODEM_AUDIO
334+ /* Log audio into SD */
335+ write(ctx->logfd, ctx->rec_buf, frame_bytes);
336+#endif
337+
338+ // Write it to the audio queue
339+ D("[T]Before AudioQueue_add: %04x %04x %04x %04x %04x",
340+ ((short*)ctx->rec_buf)[0] & 0xFFFF,
341+ ((short*)ctx->rec_buf)[1] & 0xFFFF,
342+ ((short*)ctx->rec_buf)[2] & 0xFFFF,
343+ ((short*)ctx->rec_buf)[3] & 0xFFFF,
344+ ((short*)ctx->rec_buf)[4] & 0xFFFF);
345+ AudioQueue_add(&ctx->play_q, ctx->rec_buf, ctx->frame_size);
346+ D("[T]After AudioQueue_add");
347+
348+#ifdef CHECK_MEM_OVERRUN
349+ if (((int*)ctx->rec_buf)[-1] != 0x1A3B5C7D) {
350+ ALOGE("recbuf: Corruption at start: 0x%08x",((int*)ctx->rec_buf)[-1]);
351+ }
352+ if (((int*)ctx->rec_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
353+ ALOGE("recbuf: Corruption at end: 0x%08x",((int*)ctx->rec_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
354+ }
355+ if (((int*)ctx->play_buf)[-1] != 0x1A3B5C7D) {
356+ ALOGE("playbuf: Corruption at start: 0x%08x",((int*)ctx->play_buf)[-1]);
357+ }
358+ if (((int*)ctx->play_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] != 0xD7C5B3A1) {
359+ ALOGE("playbuf: Corruption at end: 0x%08x",((int*)ctx->play_buf)[(ctx->frame_size * (ctx->bits_per_sample/8))>>2]);
360+ }
361+#endif
142362 }
143363
144- // Give all frames we have
145- while (nsamples >= ctx->frame_size) {
364+ };
146365
147- /* Send the audio to the modem */
148- modemAudioOut(ctx, input);
366+ ALOGD("modemAudioIOThread ended");
367+ return NULL;
368+}
149369
150- input = (char*) input + ctx->frame_size * (ctx->bits_per_sample/8);
151- nsamples -= ctx->frame_size;
152- }
370+/* Called with audio sampled from mic */
371+static void AndroidRecorderCallback(int event, void* userData, void* info)
372+{
373+ struct GsmAudioTunnel *ctx = (struct GsmAudioTunnel*) userData;
374+ android::AudioRecord::Buffer *uinfo = (android::AudioRecord::Buffer*) info;
375+ int bps, frames;
376+
377+ if (!ctx || !uinfo || event != android::AudioRecord::EVENT_MORE_DATA)
378+ return;
379+
380+ if (!AudioQueue_isrunning(&ctx->rec_q))
381+ goto on_break;
153382
154- // Store the remaining samples into the buffer
155- if (nsamples) {
156- ctx->rec_buf_count = nsamples;
157- memcpy(ctx->rec_buf, input, nsamples * (ctx->bits_per_sample/8));
383+ /* Bytes per sample */
384+ bps = ctx->bits_per_sample/8;
385+
386+ /* Calculate total frames */
387+ frames = uinfo->size / bps;
388+
389+#if AUDIO_OVERSAMPLING > 1
390+ /* Subsample */
391+ {
392+ short *src = (short *)uinfo->raw + frames - 1;
393+ short *dst = (short *)uinfo->raw + frames - 1;
394+ int p;
395+ short v = *src++,vold = 0;
396+ for (p = 0; p < ctx->frame_size-1; p++) {
397+ int x,d,s;
398+
399+ // Current and target values
400+ vold = v;
401+ v = *src++;
402+
403+ // Calculate delta and start value
404+ d = (v - vold) * (65536 / AUDIO_OVERSAMPLING);
405+ s = vold << 16;
406+
407+ // Interpolate values (linear interpolation)
408+ for (x = 0; x < AUDIO_OVERSAMPLING; x++) {
409+ *dst++ = s >> 16;
410+ s += d;
411+ }
158412 }
159413
160- } else {
161- // Not enough samples, let's just store them in the buffer
162- memcpy((char*)ctx->rec_buf + ctx->rec_buf_count * (ctx->bits_per_sample/8), input, uinfo->frameCount * (ctx->bits_per_sample/8));
163- ctx->rec_buf_count += uinfo->frameCount;
414+ // Last sample can't be interpolated...
415+ for (x = 0; x < AUDIO_OVERSAMPLING; x++) {
416+ *dst++ = v;
417+ }
164418 }
419+#endif
165420
421+ // Post data into the recording queue. Queue should self adapt and adjust sampling rate
422+ D("[A]Before AudioQueue_add");
423+ uinfo->size = AudioQueue_add(&ctx->rec_q, uinfo->raw, frames) * bps;
424+ D("[A]After AudioQueue_add");
166425 return;
167426
168427 on_break:
169- ALOGD("Record thread stopped");
170- ctx->rec_thread_exited = 1;
428+ if (!ctx->rec_thread_exited) {
429+ ALOGD("Record thread stopped");
430+ ctx->rec_thread_exited = 1;
431+ }
171432 return;
172433 }
173434
435+/* Called to get audio samples to playback */
174436 static void AndroidPlayerCallback( int event, void* userData, void* info)
175437 {
176- unsigned nsamples_req;
177- void *output;
178438 struct GsmAudioTunnel *ctx = (struct GsmAudioTunnel*) userData;
179439 android::AudioTrack::Buffer* uinfo = (android::AudioTrack::Buffer*) info;
440+ int bps,frames;
180441
181- if (!ctx || !uinfo)
442+ if (!ctx || !uinfo || event != android::AudioTrack::EVENT_MORE_DATA)
182443 return;
183444
184- if (ctx->quit_flag)
445+ if (!AudioQueue_isrunning(&ctx->play_q))
185446 goto on_break;
186447
187- nsamples_req = uinfo->frameCount;
188- output = (void*) uinfo->raw;
189-
190- // Check if any buffered samples
191- if (ctx->play_buf_count) {
192-
193- // samples buffered >= requested by sound device
194- if (ctx->play_buf_count >= nsamples_req) {
195-
196- memcpy(output, ctx->play_buf, nsamples_req * (ctx->bits_per_sample/8));
197- ctx->play_buf_count -= nsamples_req;
198-
199- memmove(ctx->play_buf,
200- (char*)ctx->play_buf + nsamples_req * (ctx->bits_per_sample/8), ctx->play_buf_count * (ctx->bits_per_sample/8));
201- nsamples_req = 0;
202- return;
448+ // Read data from the Playback audioqueue
449+ D("[A]Before AudioQueue_get");
450+ bps = ctx->bits_per_sample/8;
451+ uinfo->size = (frames = AudioQueue_get(&ctx->play_q, uinfo->raw, uinfo->size / bps, ctx->timeout)) * bps;
452+ D("[A]After AudioQueue_get");
453+
454+#if AUDIO_OVERSAMPLING > 1
455+ /* Oversample to send them to the Android playback channel*/
456+ if (frames) {
457+ short *src = uinfo->raw;
458+ short *dst = uinfo->raw;
459+ int p;
460+ short v = *src++,vold = 0;
461+ for (p = 0; p < frames-1; p++) {
462+ int x,d,s;
463+
464+ // Current and target values
465+ vold = v;
466+ v = *src++;
467+
468+ // Calculate delta and start value
469+ d = (v - vold) * (65536 / AUDIO_OVERSAMPLING);
470+ s = vold << 16;
471+
472+ // Interpolate values (linear interpolation)
473+ for (x = 0; x < AUDIO_OVERSAMPLING; x++) {
474+ *dst++ = s >> 16;
475+ s += d;
476+ }
203477 }
204478
205- // samples buffered < requested by sound device
206- memcpy(output, ctx->play_buf,
207- ctx->play_buf_count * (ctx->bits_per_sample/8));
208- nsamples_req -= ctx->play_buf_count;
209- output = (char*)output + ctx->play_buf_count * (ctx->bits_per_sample/8);
210- ctx->play_buf_count = 0;
211- }
212-
213- // Fill output buffer as requested in chunks
214- while (nsamples_req) {
215- if (nsamples_req >= ctx->frame_size) {
216-
217- /* get a frame from the modem */
218- modemAudioIn(ctx, output);
219-
220- nsamples_req -= ctx->frame_size;
221- output = (char*)output + ctx->frame_size * (ctx->bits_per_sample/8);
222-
223- } else {
224-
225- /* get a frame from the modem */
226- modemAudioIn(ctx, ctx->play_buf);
227-
228- memcpy(output, ctx->play_buf,
229- nsamples_req * (ctx->bits_per_sample/8));
230- ctx->play_buf_count = ctx->frame_size - nsamples_req;
231- memmove(ctx->play_buf,
232- (char*)ctx->play_buf + nsamples_req * (ctx->bits_per_sample/8),
233- ctx->play_buf_count * (ctx->bits_per_sample/8));
234- nsamples_req = 0;
479+ // Last sample can't be interpolated...
480+ for (x = 0; x < AUDIO_OVERSAMPLING; x++) {
481+ *dst++ = v;
235482 }
236483 }
484+#endif
237485
238486 return;
239487
240488 on_break:
241- ALOGD("Play thread stopped");
242- ctx->play_thread_exited = 1;
489+ if (!ctx->play_thread_exited) {
490+ ALOGD("Play thread stopped");
491+ ctx->play_thread_exited = 1;
492+ }
493+
494+ /* Silence output if we are not running */
495+ memset(uinfo->raw, 0, uinfo->size);
243496 return;
244497 }
245498
246499 //AT^DDSETEX=2
247500
248-int gsm_audio_tunnel_start(struct GsmAudioTunnel *ctx,const char* gsmvoicechannel,unsigned int sampling_rate,unsigned int frame_size,unsigned int bits_per_sample)
501+int gsm_audio_tunnel_start(struct GsmAudioTunnel *ctx, const char *gsmvoicechannel, unsigned int sampling_rate, unsigned int frame_size, unsigned int bits_per_sample)
249502 {
503+ pthread_attr_t modem_attr;
250504 struct termios newtio;
251- int format = (bits_per_sample > 8)
252- ? AUDIO_FORMAT_PCM_16_BIT
253- : AUDIO_FORMAT_PCM_8_BIT;
505+ int create_result = 0;
506+ size_t playBuffSize = 0;
507+ size_t playNotifyBuffSize = 0;
508+ size_t recBuffSize = 0;
509+ size_t recNotifyBuffSize = 0;
510+ int play_qsize;
511+ int rec_qsize;
512+
513+ audio_format_t format = (bits_per_sample > 8)
514+ ? AUDIO_FORMAT_PCM_16_BIT
515+ : AUDIO_FORMAT_PCM_8_BIT;
254516
255517 /* If already running, dont do it again */
256- if (ctx->running)
518+ if (AudioQueue_isrunning(&ctx->rec_q) ||
519+ AudioQueue_isrunning(&ctx->play_q))
257520 return 0;
258521
259522 memset(ctx,0,sizeof(struct GsmAudioTunnel));
523+ ctx->fd = -1;
260524
261525 ctx->sampling_rate = sampling_rate;
262526 ctx->frame_size = frame_size;
263527 ctx->bits_per_sample = bits_per_sample;
528+ ctx->timeout = 1000 * frame_size / sampling_rate;
264529
265530 ALOGD("Opening GSM voice channel '%s', sampling_rate:%u hz, frame_size:%u, bits_per_sample:%u ...",
266- gsmvoicechannel,sampling_rate,frame_size,bits_per_sample);
531+ gsmvoicechannel,sampling_rate,frame_size,bits_per_sample);
267532
268- // Open the device(com port) to be non-blocking (read will return immediately)
269- ctx->fd = open(gsmvoicechannel, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
533+#if LOG_MODEM_AUDIO
534+ ctx->logfd = open("/sdcard/modemlog", O_RDWR);
535+#endif
536+
537+ // Compute buffer sizes for record and playback
538+#if 0
539+ playBuffSize = 0;
540+ android::AudioSystem::getInputBufferSize(
541+ ctx->sampling_rate * AUDIO_OVERSAMPLING, // Samples per second
542+ format,
543+ AUDIO_CHANNEL_IN_MONO,
544+ &playBuffSize);
545+ recBuffSize = playBuffSize;
546+#else
547+ android::AudioRecord::getMinFrameCount((int*)&recBuffSize,
548+ ctx->sampling_rate * AUDIO_OVERSAMPLING, // Samples per second
549+ format,
550+ 1);
551+
552+ //android::AudioSystem::getInputBufferSize(
553+ // ctx->sampling_rate, // Samples per second
554+ // format,
555+ // AUDIO_CHANNEL_IN_MONO,
556+ // &recBuffSize);
557+ //recBuffSize <<= 1; // Convert to bytes
558+ //recBuffSize <<= 1; // Convert to bytes
559+ //while (recBuffSize < frame_size) recBuffSize <<= 1;
560+ //while (playBuffSize < frame_size) playBuffSize <<= 1;
561+
562+ android::AudioTrack::getMinFrameCount((int*)&playBuffSize,
563+ AUDIO_STREAM_VOICE_CALL,
564+ ctx->sampling_rate * AUDIO_OVERSAMPLING); // Samples per second
565+
566+ // Do not accept less than the frame size ... Makes no point going lower than that
567+ if (playBuffSize < frame_size)
568+ playBuffSize = frame_size;
569+ if (recBuffSize < frame_size)
570+ recBuffSize = frame_size;
571+
572+ // Compute minimum playback queue size as a power of 2
573+ play_qsize = 0;
574+ while ((1 << play_qsize) < playBuffSize) play_qsize++;
575+ play_qsize += 2; // And quad it
576+
577+ // Compute minimum record queue size as a power of 2
578+ rec_qsize = 0;
579+ while ((1 << rec_qsize) < recBuffSize) rec_qsize++;
580+ rec_qsize += 2; // And quad it
581+
582+#endif
583+
584+ // We use 2 * size of input/output buffer for ping pong use of record/playback buffers.
585+ playNotifyBuffSize = playBuffSize;
586+ playBuffSize <<= 1;
587+ recNotifyBuffSize = recBuffSize;
588+ recBuffSize <<= 1;
589+ ALOGD("play samples: %d [q:%d], record samples: %d [q:%d]",
590+ playNotifyBuffSize, play_qsize, recNotifyBuffSize, rec_qsize);
591+
592+ // Init the audioqueues
593+ if (AudioQueue_init(&ctx->play_q,play_qsize,bits_per_sample>>3) < 0) {
594+ ALOGE("Could not init Playback AudioQueue");
595+ goto error;
596+ }
597+ if (AudioQueue_init(&ctx->rec_q,rec_qsize,bits_per_sample>>3) < 0) {
598+ ALOGE("Could not init Record AudioQueue");
599+ goto error;
600+ }
601+
602+ ALOGD("Opening voice channel....");
603+
604+/* if (echocancel_init(&ctx->echo, recNotifyBuffSize ) < 0) {
605+ ALOGE("Could not init Record AudioQueue");
606+ goto error;
607+ }
608+*/
609+ // Open the device(com port) in blocking mode
610+ ctx->fd = open(gsmvoicechannel, O_RDWR | O_NOCTTY);
270611 if (ctx->fd < 0) {
271612 ALOGE("Could not open '%s'",gsmvoicechannel);
272- return -1;
613+ goto error;
273614 }
274615
275616 // Configure it to get data as raw as possible
@@ -278,122 +619,108 @@ int gsm_audio_tunnel_start(struct GsmAudioTunnel *ctx,const char* gsmvoicechanne
278619 newtio.c_iflag = IGNPAR | IGNBRK | IGNCR | IXOFF;
279620 newtio.c_oflag = 0;
280621 newtio.c_lflag = 0;
281- newtio.c_cc[VMIN]=0;
282- newtio.c_cc[VTIME]=5; // You may want to tweak this; 5 = 1/2 second, 10 = 1 second
622+ newtio.c_cc[VMIN]=1;
623+ newtio.c_cc[VTIME]=1;
283624 tcsetattr(ctx->fd,TCSANOW, &newtio);
284625
285626 ALOGD("Creating streams....");
286- ctx->rec_buf = malloc(ctx->frame_size * (ctx->bits_per_sample/8));
627+#ifdef CHECK_MEM_OVERRUN
628+ ctx->rec_buf = malloc(8 + ctx->frame_size * (ctx->bits_per_sample/8) * AUDIO_OVERSAMPLING);
287629 if (!ctx->rec_buf) {
288- close(ctx->fd);
289- return -1;
630+ ALOGE("Failed to allocate buffer for playback");
631+ goto error;
290632 }
291633
292- ctx->play_buf = malloc(ctx->frame_size * (ctx->bits_per_sample/8));
634+ ctx->play_buf = malloc(8 + ctx->frame_size * (ctx->bits_per_sample/8) * AUDIO_OVERSAMPLING);
293635 if (!ctx->play_buf) {
294- free(ctx->rec_buf);
295- close(ctx->fd);
296- return -1;
636+ ALOGE("Failed to allocate buffer for record");
637+ goto error;
297638 }
298639
299- // Compute buffer size
300- size_t inputBuffSize = 0;
301- android::AudioSystem::getInputBufferSize(
302- ctx->sampling_rate, // Samples per second
303- format,
304- AUDIO_CHANNEL_IN_MONO,
305- &inputBuffSize);
640+ ctx->rec_buf = (int*)ctx->rec_buf + 1;
641+ ((int*)ctx->rec_buf)[-1] = 0x1A3B5C7D;
642+ ((int*)ctx->rec_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] = 0xD7C5B3A1;
643+ ctx->play_buf = (int*)ctx->play_buf + 1;
644+ ((int*)ctx->play_buf)[-1] = 0x1A3B5C7D;
645+ ((int*)ctx->play_buf)[(ctx->frame_size * AUDIO_OVERSAMPLING * (ctx->bits_per_sample/8))>>2] = 0xD7C5B3A1;
306646
307- // We use 2* size of input buffer for ping pong use of record buffer.
308- inputBuffSize = 2 * inputBuffSize;
647+#else
648+ ctx->rec_buf = malloc(ctx->frame_size * (ctx->bits_per_sample/8) * AUDIO_OVERSAMPLING);
649+ if (!ctx->rec_buf) {
650+ ALOGE("Failed to allocate buffer for playback");
651+ goto error;
652+ }
653+
654+ ctx->play_buf = malloc(ctx->frame_size * (ctx->bits_per_sample/8) * AUDIO_OVERSAMPLING);
655+ if (!ctx->play_buf) {
656+ ALOGE("Failed to allocate buffer for record");
657+ goto error;
658+ }
659+#endif
309660
310661 // Create audio record channel
311662 ctx->rec_strm = new android::AudioRecord();
312663 if(!ctx->rec_strm) {
313664 ALOGE("fail to create audio record");
314- free(ctx->play_buf);
315- free(ctx->rec_buf);
316- close(ctx->fd);
317- return -1;
665+ goto error;
666+ }
667+
668+ // Create audio playback channel
669+ ctx->play_strm = new android::AudioTrack();
670+ if(!ctx->play_strm) {
671+ ALOGE("Failed to create AudioTrack");
672+ goto error;
318673 }
319674
320675 // Unmute microphone
321676 // android::AudioSystem::muteMicrophone(false);
322- int create_result = ((android::AudioRecord*)ctx->rec_strm)->set(
323- AUDIO_SOURCE_MIC,
324- ctx->sampling_rate,
325- format,
326- AUDIO_CHANNEL_IN_MONO,
327- inputBuffSize,
328- 0, //flags
329- &AndroidRecorderCallback,
330- (void *) ctx,
331- (inputBuffSize / 2), // Notification frames
332- false,
333- 0);
677+ create_result = ((android::AudioRecord*)ctx->rec_strm)->set(
678+ AUDIO_SOURCE_MIC,
679+ ctx->sampling_rate * AUDIO_OVERSAMPLING,
680+ format,
681+ AUDIO_CHANNEL_IN_MONO,
682+ recBuffSize,
683+ &AndroidRecorderCallback,
684+ (void *) ctx,
685+ recNotifyBuffSize, // Notification frames
686+ false,
687+ 0);
334688
335689 if(create_result != android::NO_ERROR){
336690 ALOGE("fail to check audio record : error code %d", create_result);
337- delete ((android::AudioRecord*)ctx->rec_strm);
338- free(ctx->play_buf);
339- free(ctx->rec_buf);
340- close(ctx->fd);
341- return -1;
691+ goto error;
342692 }
343693
344694 if(((android::AudioRecord*)ctx->rec_strm)->initCheck() != android::NO_ERROR) {
345- ALOGE("fail to check audio record : buffer size is : %d, error code : %d", inputBuffSize, ((android::AudioRecord*)ctx->rec_strm)->initCheck() );
346- delete ((android::AudioRecord*)ctx->rec_strm);
347- free(ctx->play_buf);
348- free(ctx->rec_buf);
349- close(ctx->fd);
350- return -1;
351- }
352-
353- // Create audio playback channel
354- ctx->play_strm = new android::AudioTrack();
355- if(!ctx->play_strm) {
356- ALOGE("Failed to create AudioTrack");
357- delete ((android::AudioRecord*)ctx->rec_strm);
358- free(ctx->play_buf);
359- free(ctx->rec_buf);
360- close(ctx->fd);
361- return -1;
695+ ALOGE("fail to check audio record : buffer size is : %d, error code : %d",
696+ recBuffSize, ((android::AudioRecord*)ctx->rec_strm)->initCheck());
697+ goto error;
362698 }
363699
364700 // android::AudioSystem::setMasterMute(false);
365701 create_result = ((android::AudioTrack*)ctx->play_strm)->set(
366- AUDIO_STREAM_VOICE_CALL,
367- ctx->sampling_rate, //this is sample rate in Hz (16000 Hz for example)
368- format,
369- AUDIO_CHANNEL_OUT_MONO, //For now this is mono (we expect 1)
370- inputBuffSize,
371- 0, //flags
372- &AndroidPlayerCallback,
373- (void *) ctx,
374- (inputBuffSize / 2),
375- 0,
376- false,
377- 0);
378-
379- if(create_result != android::NO_ERROR){
702+ AUDIO_STREAM_VOICE_CALL,
703+ ctx->sampling_rate * AUDIO_OVERSAMPLING, //this is sample rate in Hz (16000 Hz for example)
704+ format,
705+ AUDIO_CHANNEL_OUT_MONO, //For now this is mono (we expect 1)
706+ playBuffSize,
707+ AUDIO_OUTPUT_FLAG_NONE, //flags
708+ &AndroidPlayerCallback,
709+ (void *) ctx,
710+ playNotifyBuffSize,
711+ 0,
712+ false,
713+ 0);
714+
715+ if (create_result != android::NO_ERROR){
380716 ALOGE("fail to check audio record : error code %d", create_result);
381- delete ((android::AudioTrack*)ctx->play_strm);
382- delete ((android::AudioRecord*)ctx->rec_strm);
383- free(ctx->play_buf);
384- free(ctx->rec_buf);
385- close(ctx->fd);
386- return -1;
717+ goto error;
387718 }
388719
389720 if(((android::AudioTrack*)ctx->play_strm)->initCheck() != android::NO_ERROR) {
390- ALOGE("fail to check audio playback : buffer size is : %d, error code : %d", inputBuffSize, ((android::AudioTrack*)ctx->play_strm)->initCheck() );
391- delete ((android::AudioTrack*)ctx->play_strm);
392- delete ((android::AudioRecord*)ctx->rec_strm);
393- free(ctx->play_buf);
394- free(ctx->rec_buf);
395- close(ctx->fd);
396- return -1;
721+ ALOGE("fail to check audio playback : buffer size is : %d, error code : %d",
722+ playBuffSize, ((android::AudioTrack*)ctx->play_strm)->initCheck());
723+ goto error;
397724 }
398725
399726 /* Save the current audio routing setting, then switch it to earpiece. */
@@ -413,44 +740,85 @@ int gsm_audio_tunnel_start(struct GsmAudioTunnel *ctx,const char* gsmvoicechanne
413740 ((android::AudioRecord*)ctx->rec_strm)->start();
414741 }
415742
416- ALOGD("Done");
743+ // Create the playback thread
744+ pthread_attr_init(&modem_attr);
745+ if (pthread_create(&ctx->modem_t,&modem_attr,modemAudioIOThread,ctx) < 0) {
746+ ALOGE("Failed to start modemAudioIO Thread");
747+error:
748+ AudioQueue_end(&ctx->rec_q);
749+ AudioQueue_end(&ctx->play_q);
750+ if (ctx->play_strm) delete ((android::AudioTrack*)ctx->play_strm);
751+ if (ctx->rec_strm) delete ((android::AudioRecord*)ctx->rec_strm);
752+#ifdef CHECK_MEM_OVERRUN
753+ if (ctx->play_buf) free(((int*)ctx->play_buf)-1);
754+ if (ctx->rec_buf) free(((int*)ctx->rec_buf)-1);
755+#else
756+ if (ctx->play_buf) free(ctx->play_buf);
757+ if (ctx->rec_buf) free(ctx->rec_buf);
758+#endif
759+ if (ctx->fd) close(ctx->fd);
760+#if LOG_MODEM_AUDIO
761+ if (ctx->logfd) close(ctx->logfd);
762+#endif
417763
418- ctx->running = 1;
764+ return -1;
765+ }
766+
767+ ALOGD("Done");
419768
420769 // OK, done
421770 return 0;
422771 }
423772
773+/* API: mute audio record channel */
774+int gsm_audio_tunnel_mute(struct GsmAudioTunnel *ctx, int muteit)
775+{
776+ ctx->ismuted = muteit;
777+ return 0;
778+}
779+
780+/* API: query if tunnel is running */
781+int gsm_audio_tunnel_running(struct GsmAudioTunnel *ctx)
782+{
783+ if (AudioQueue_isrunning(&ctx->rec_q) ||
784+ AudioQueue_isrunning(&ctx->play_q))
785+ return 1;
786+ return 0;
787+}
788+
424789 /* API: destroy ctx. */
425790 int gsm_audio_tunnel_stop(struct GsmAudioTunnel *ctx)
426791 {
427- int i = 0;
792+ int i;
428793
429794 /* If not running, dont do it again */
430- if (!ctx->running)
795+ if (!AudioQueue_isrunning(&ctx->rec_q) ||
796+ !AudioQueue_isrunning(&ctx->play_q))
431797 return 0;
432798
799+ ALOGD("Signal all audio threads to stop");
800+ AudioQueue_end(&ctx->play_q);
801+ AudioQueue_end(&ctx->rec_q);
433802
434- ALOGD("Will Stop ctx, wait for all audio callback clean");
435- ctx->quit_flag = 1;
436- for (i=0; !ctx->rec_thread_exited && i<100; ++i){
437- usleep(100000);
438- }
439- for (i=0; !ctx->play_thread_exited && i<100; ++i){
803+ // Wait until android audio threads are "idling"
804+ for (i=0; (!ctx->rec_thread_exited || !ctx->play_thread_exited) && i<100; ++i) {
440805 usleep(100000);
441806 }
807+ // After all sleep for 0.2 seconds since android device can be slow
808+ usleep(200000);
809+ ALOGD("Android audio threads are idle");
442810
443- // After all sleep for 0.1 seconds since android device can be slow
444- usleep(100000);
445-
446- ALOGD("Stopping ctx..");
447811 if (ctx->rec_strm) {
448812 ((android::AudioRecord*)ctx->rec_strm)->stop();
449813 }
450-
451814 if (ctx->play_strm) {
452815 ((android::AudioTrack*)ctx->play_strm)->stop();
453816 }
817+ usleep(200000);
818+ ALOGD("Stopped android audio streaming");
819+
820+ pthread_join(ctx->modem_t,NULL);
821+ ALOGD("End modemIO thread");
454822
455823 // Restore the audio routing setting
456824 // android::AudioSystem::setRouting(ctx->saved_audio_mode,
@@ -460,20 +828,21 @@ int gsm_audio_tunnel_stop(struct GsmAudioTunnel *ctx)
460828
461829 ALOGD("Closing streaming");
462830
463- if (ctx->play_strm) {
464- delete ((android::AudioTrack*)ctx->play_strm);
465- ctx->play_strm = NULL;
466- }
467-
468- if (ctx->rec_strm) {
469- delete ((android::AudioRecord*)ctx->rec_strm);
470- ctx->rec_strm = NULL;
471- }
472-
473- free(ctx->play_buf);
474- free(ctx->rec_buf);
831+ if (ctx->play_strm) delete ((android::AudioTrack*)ctx->play_strm);
832+ if (ctx->rec_strm) delete ((android::AudioRecord*)ctx->rec_strm);
833+#ifdef CHECK_MEM_OVERRUN
834+ if (ctx->play_buf) free(((int*)ctx->play_buf)-1);
835+ if (ctx->rec_buf) free(((int*)ctx->rec_buf)-1);
836+#else
837+ if (ctx->play_buf) free(ctx->play_buf);
838+ if (ctx->rec_buf) free(ctx->rec_buf);
839+#endif
840+ if (ctx->fd) close(ctx->fd);
841+
842+#if LOG_MODEM_AUDIO
843+ if (ctx->logfd) close(ctx->logfd);
844+#endif
475845
476- close(ctx->fd);
477846 memset(ctx,0,sizeof(struct GsmAudioTunnel));
478847
479848 ALOGD("Done");
--- a/huaweigeneric-ril/audiochannel.h
+++ b/huaweigeneric-ril/audiochannel.h
@@ -1,6 +1,6 @@
11 /*
22 **
3-** Copyright (C) 2010 Eduardo José Tagle <ejtagle@tutopia.com>
3+** Copyright (C) 2012 Eduardo José Tagle <ejtagle@tutopia.com>
44 **
55 ** Licensed under the Apache License, Version 2.0 (the "License");
66 ** you may not use this file except in compliance with the License.
@@ -14,50 +14,67 @@
1414 ** See the License for the specific language governing permissions and
1515 ** limitations under the License.
1616 **
17-** Author: Christian Bejram <christian.bejram@stericsson.com>
1817 */
1918 #ifndef _AUDIOCHANNEL_H
2019 #define _AUDIOCHANNEL_H 1
2120
21+#include "audioqueue.h"
22+#include "echocancel.h"
23+#include <pthread.h>
24+
25+#define LOG_MODEM_AUDIO 0
26+
2227 struct GsmAudioTunnel {
23- int running; // If running
2428
2529 // 3G voice modem
2630 int fd; // Voice data serial port handler
2731
32+#if LOG_MODEM_AUDIO
33+ int logfd;
34+#endif
35+
2836 // Common properties
29- volatile int quit_flag; // If threads should quit
3037 unsigned int frame_size; // Frame size
3138 unsigned int sampling_rate; // Sampling rate
3239 unsigned int bits_per_sample; // Bits per sample. valid values = 16/8
40+ unsigned int timeout; // Maximum wait timeout
41+ pthread_t modem_t; // 3G modem playback/record thread
42+ int ismuted; // If audio record is muted
3343
3444 // Playback
3545 void* play_strm; // Playback stream
3646 volatile int play_thread_exited;// If play thread has exited
3747 void* play_buf; // Pointer to the playback buffer
38- unsigned int play_buf_count; // Count of already stored samples in the playback buffer
48+ struct AudioQueue play_q; // Audio playback queue
3949
4050 // Record
4151 void* rec_strm; // Record stream
4252 volatile int rec_thread_exited; // If record thread has exited
4353 void* rec_buf; // Pointer to the recording buffer
44- unsigned int rec_buf_count; // Count of already stored samples in the recording buffer
54+ struct AudioQueue rec_q; // Audio record queue
55+
56+ // Echo cancellation
57+ struct echocancel_ctx echo; // Echo cancellator
4558 };
4659
47-#define GSM_AUDIO_CHANNEL_STATIC_INIT { 0, 0, 0,0,0,0, 0,0,0,0 ,0,0,0,0 }
60+#define GSM_AUDIO_CHANNEL_STATIC_INIT { -1, 0,0,0,0,0,0, 0,0,0,{0} ,0,0,0,{0}, {0} }
4861
4962 #ifdef __cplusplus
5063 extern "C" {
5164 #endif
5265
5366 int gsm_audio_tunnel_start(struct GsmAudioTunnel *stream,
54- const char* gsmvoicechannel,
55- unsigned int sampling_rate,
56- unsigned int frame_size,
57- unsigned int bits_per_sample);
67+ const char* gsmvoicechannel,
68+ unsigned int sampling_rate,
69+ unsigned int frame_size,
70+ unsigned int bits_per_sample);
5871
5972 int gsm_audio_tunnel_stop(struct GsmAudioTunnel *stream);
6073
74+int gsm_audio_tunnel_running(struct GsmAudioTunnel *ctx);
75+
76+int gsm_audio_tunnel_mute(struct GsmAudioTunnel *stream, int muteit);
77+
6178 #ifdef __cplusplus
6279 }
6380 #endif
--- /dev/null
+++ b/huaweigeneric-ril/audioqueue.c
@@ -0,0 +1,421 @@
1+#include "audioqueue.h"
2+#include <string.h>
3+#include <stdio.h>
4+
5+#define LOG_NDEBUG 0
6+#define LOG_TAG "RILAudioQueue"
7+#include <utils/Log.h>
8+
9+#define f_mul(a,b) (((long long)(a))*(b) >> 28)
10+#define f_div(a,b) ((((long long)(a)) << 28) / (b))
11+#define f_fract(a) ((a) & ((1<<28)-1))
12+#define f_intp(a) ((a) >> 28)
13+#define F_ONE (1<<28)
14+#define F_NBR(x) ((int)((1<<28) * (x)))
15+
16+//#define CHECK_MEM_OVERRUN
17+#define AUDIOQUEUE_DEBUG 0
18+#if AUDIOQUEUE_DEBUG
19+# define D(...) ALOGD(__VA_ARGS__)
20+#else
21+# define D(...) ((void)0)
22+#endif
23+
24+/* Return count in buffer. */
25+#define CIRC_CNT(wr_pos,rd_pos,size) (((wr_pos) - (rd_pos)) & ((size)-1))
26+
27+/* Return space available, 0..size-1. We always leave one free char
28+ as a completely full buffer has wr_pos == rd_pos, which is the same as
29+ empty. */
30+#define CIRC_SPACE(wr_pos,rd_pos,size) CIRC_CNT((rd_pos),((wr_pos)+1),(size))
31+
32+/* Return count up to the end of the buffer. Carefully avoid
33+ accessing wr_pos and rd_pos more than once, so they can change
34+ underneath us without returning inconsistent results. */
35+#define CIRC_CNT_TO_END(wr_pos,rd_pos,size) \
36+ ({int end = (size) - (rd_pos); \
37+ int n = ((wr_pos) + end) & ((size)-1); \
38+ n < end ? n : end;})
39+
40+/* Return space available up to the end of the buffer. */
41+#define CIRC_SPACE_TO_END(wr_pos,rd_pos,size) \
42+ ({int end = (size) - 1 - (wr_pos); \
43+ int n = (end + (rd_pos)) & ((size)-1); \
44+ n <= end ? n : end+1;})
45+
46+
47+
48+// Init the audio queue
49+int AudioQueue_init(struct AudioQueue* ctx,unsigned int p2maxsamples, unsigned int sample_sz)
50+{
51+ unsigned int maxsamples = 1U << p2maxsamples;
52+ memset(ctx,0,sizeof(*ctx));
53+
54+ ctx->size = maxsamples;
55+#if NEW_SYNC_ALGO
56+ ctx->waitidx = 1;
57+#endif
58+ ctx->sample_sz = sample_sz;
59+
60+ /* Linear resampler */
61+ ctx->ratio = F_ONE;
62+
63+ ALOGD("[%p] Initializing audio queue: size: %d, low: %d, high: %d, sample_sz: %d",
64+ ctx,ctx->size,ctx->low,ctx->high,ctx->sample_sz);
65+
66+#ifdef CHECK_MEM_OVERRUN
67+ ctx->data = malloc(8 + maxsamples * sample_sz);
68+ if (!ctx->data) {
69+ ALOGE("{%p} Failed to allocate %d memory",ctx, 8 + maxsamples * sample_sz);
70+ return -1;
71+ }
72+ ctx->data = (int*)ctx->data + 1;
73+ ((int*)ctx->data)[-1] = 0x1A2B6C7D;
74+ ((int*)ctx->data)[(ctx->size*ctx->sample_sz)>>2] = 0xD7C6B2A1;
75+#else
76+ ctx->data = malloc(maxsamples * sample_sz);
77+ if (!ctx->data) {
78+ ALOGE("{%p} Failed to allocate %d memory",ctx, maxsamples * sample_sz);
79+ return -1;
80+ }
81+#endif
82+
83+ // Init audio AGC
84+ agc_init(&ctx->agc, 31000);
85+
86+ ctx->running = 1;
87+
88+ return 0;
89+}
90+
91+int AudioQueue_isrunning(struct AudioQueue* ctx)
92+{
93+ return ctx->running;
94+}
95+
96+int AudioQueue_add(struct AudioQueue* ctx, void* data,unsigned int samples)
97+{
98+ unsigned int samples_todo = samples;
99+
100+ // If exited, avoid adding
101+ if (!ctx->running)
102+ return 0;
103+
104+ D("add[%p]: begin: Store %d samples",ctx,samples);
105+
106+ // Not filled, add to the queue.
107+ while (ctx->running && samples_todo) {
108+
109+ // Calculate remaining space until end of buffer. We always leave a byte free
110+ // so we can differenciate between empty and full buffers
111+ unsigned int rem = CIRC_SPACE_TO_END(ctx->wr_pos,ctx->rd_pos,ctx->size);
112+
113+ D("add[%p]: samples_todo: %u, rem: %u, rd: %u, wr: %u, sz: %u",
114+ ctx, samples_todo, rem, ctx->rd_pos, ctx->wr_pos, ctx->size);
115+
116+ if (rem == 0) {
117+ /* not enough data... Ignore the part we can't store */
118+ D("add[%p]: Not enough space on queue...",ctx);
119+ break;
120+
121+ } else {
122+ // Do not store more than needed
123+ if (rem > samples_todo) {
124+ rem = samples_todo;
125+ }
126+
127+ // Store data in queue
128+ memcpy( (char*)ctx->data + ctx->wr_pos * ctx->sample_sz, data, rem * ctx->sample_sz);
129+ data = (char*) data + rem * ctx->sample_sz;
130+ ctx->wr_pos = (ctx->wr_pos + rem) & (ctx->size-1);
131+ samples_todo -= rem;
132+ }
133+ }
134+
135+ D("add[%p]: end: Stored %d samples, size %d, rd:%d, wr:%d",ctx,samples - samples_todo,ctx->size, ctx->rd_pos, ctx->wr_pos);
136+
137+#if !NEW_SYNC_ALGO
138+ // Adjust ratio if queue is getting full, to keep fullness under control
139+ if (ctx->high && CIRC_CNT(ctx->wr_pos,ctx->rd_pos,ctx->size) > ctx->high) {
140+ unsigned int ratio = ctx->ratio;
141+
142+ // Adjust ratio to avoid this the next time
143+ ratio += ratio/200;
144+
145+ // Limit to sensible values
146+ if (ratio > F_NBR(1.05)) {
147+ ratio = F_NBR(1.05);
148+ }
149+ ctx->ratio = ratio;
150+ D("add[%p]: Adjusting ratio to keep queue 3/4 full: New ratio: %u",ctx, ratio);
151+ }
152+#endif
153+
154+#ifdef CHECK_MEM_OVERRUN
155+ if (((int*)ctx->data)[-1] != 0x1A2B6C7D) {
156+ ALOGE("add[%p] Memory corruption at start: Found: %08x",ctx, ((int*)ctx->data)[-1]);
157+ }
158+
159+ if (((int*)ctx->data)[(ctx->size*ctx->sample_sz)>>2] != 0xD7C6B2A1) {
160+ ALOGE("add[%p] Memory corruption at end: Found: %08x",ctx, ((int*)ctx->data)[ctx->size*ctx->sample_sz]);
161+ }
162+#endif
163+
164+ // Return the count of stored samples
165+ return samples - samples_todo;
166+}
167+
168+int AudioQueue_get(struct AudioQueue* ctx, void* data,unsigned int samples,unsigned int timeoutms)
169+{
170+ unsigned int maxgetreq;
171+ unsigned int samples_todo = samples;
172+ void* pdata = data;
173+#if NEW_SYNC_ALGO
174+ struct timeval startop;
175+ struct timeval curr;
176+ unsigned int deltatm = 0;
177+#endif
178+
179+ // If exited, avoid adding
180+ if (!ctx->running)
181+ return 0;
182+
183+ D("get[%p]: begin: Read of %d samples",ctx,samples);
184+
185+#if !NEW_SYNC_ALGO
186+ /* Keep track of the maximum read size, as we will use it as low/high limit */
187+ maxgetreq = ctx->maxgetreq;
188+ if (samples > maxgetreq) {
189+ maxgetreq = samples;
190+ ctx->maxgetreq = maxgetreq;
191+
192+ /* Limit to something we can use */
193+ if (maxgetreq > ctx->size / 4) {
194+ maxgetreq = ctx->size / 4;
195+ }
196+
197+ ctx->low = maxgetreq*2; // Low limit: 2 read pending
198+ ctx->high = maxgetreq*3; // High limit: 3 reads pending
199+
200+ D("get[%p]: new limits: low:%u, high:%u",ctx,ctx->low,ctx->high);
201+ }
202+#endif
203+
204+#if NEW_SYNC_ALGO
205+ // Store the time of the start of this operation
206+ gettimeofday(&startop,NULL);
207+#endif
208+
209+ // While samples to be read
210+ while (ctx->running && samples_todo) {
211+
212+ // Read the first free position
213+ int av = CIRC_CNT(ctx->wr_pos,ctx->rd_pos,ctx->size);
214+ unsigned int step = ctx->step, mask = ctx->size-1;
215+ unsigned int rd_pos = ctx->rd_pos;
216+
217+ D("get[%p]: [1] samples_todo: %u, rd: %u, wr: %u, sz: %u",
218+ ctx, samples_todo, ctx->rd_pos, ctx->wr_pos, ctx->size);
219+
220+ // linear interpolation resampling until all requested data is provided
221+ if (ctx->sample_sz == 2) {
222+
223+ short const *psrc = ctx->data;
224+ short *pdst = (short*)pdata;
225+
226+ /* We use the current one and next one samples */
227+ while (samples_todo) {
228+ int ipart = f_intp(step);
229+ rd_pos = (rd_pos + ipart) & mask;
230+ av -= ipart;
231+ step = f_fract(step);
232+
233+ // If not enough data, break now
234+ if (av < 2)
235+ break;
236+
237+ *pdst++ = psrc[rd_pos] + f_mul(psrc[(rd_pos+1) & mask] - psrc[rd_pos], step);
238+ samples_todo--;
239+ step += ctx->ratio;
240+
241+ // Update buffer pointers and linear resampler step
242+ ctx->step = step;
243+ ctx->rd_pos = rd_pos;
244+ }
245+ pdata = pdst;
246+
247+ } else {
248+ unsigned char const *psrc = ctx->data;
249+ unsigned char *pdst = (unsigned char*)pdata;
250+
251+ /* We use the current one and next one samples */
252+ while (samples_todo) {
253+ int ipart = f_intp(step);
254+ rd_pos = (rd_pos + ipart) & mask;
255+ av -= ipart;
256+ step = f_fract(step);
257+
258+ // If not enough data, break now
259+ if (av < 2)
260+ break;
261+
262+ *pdst++ = psrc[rd_pos] + f_mul(psrc[(rd_pos+1) & mask] - psrc[rd_pos], step);
263+ samples_todo--;
264+ step += ctx->ratio;
265+
266+ // Update buffer pointers and linear resampler step
267+ ctx->step = step;
268+ ctx->rd_pos = rd_pos;
269+ }
270+ pdata = pdst;
271+ }
272+
273+ D("get[%p]: [2] samples_todo: %u, rd: %u, wr: %u, sz: %u",
274+ ctx, samples_todo, ctx->rd_pos, ctx->wr_pos, ctx->size);
275+ if (samples_todo) {
276+
277+#if NEW_SYNC_ALGO
278+ /* Get actual time */
279+ gettimeofday(&curr,NULL);
280+
281+ /* Yield a bit - 1 ms */
282+ usleep(1000);
283+
284+ /* Calculate waiting time */
285+ deltatm = (curr.tv_sec - startop.tv_sec) * 1000000 + (curr.tv_usec - startop.tv_usec);
286+
287+ /* If we are allowed to wait a bit to get those samples, keep trying */
288+ if (deltatm < timeoutms)
289+ continue;
290+#endif
291+
292+ // No more samples to provide....
293+ D("get[%p]: Not enough data on queue...",ctx);
294+
295+ // Return what we have...
296+ break;
297+ }
298+ };
299+
300+ D("get[%p]: end: got %d samples, total: %d, rd:%d, wr:%d",
301+ ctx, samples - samples_todo, ctx->size,ctx->rd_pos, ctx->wr_pos);
302+
303+#if NEW_SYNC_ALGO
304+ // The idea is that we want to keep nearly in sync adds with gets, but this is not easy, as
305+ // there is a lot of jitter in the add and get operations. So, instead of that, what we strive
306+ // is to adjust sampling rate so if we had to wait, wait more than 0 but less than 2ms.
307+
308+ if (deltatm == 0) {
309+ // We didn't had to wait. Everything could be fine, or we could be running the queue
310+ // too slow. try to speed it up a bit: We want to hit the 1ms waiting mark...
311+
312+ unsigned int ratio = ctx->ratio;
313+
314+ // Adjust ratio to avoid this the next time.
315+ ratio += ratio * ctx->waitidx / samples;
316+
317+ // Limit to sensible values
318+ if (ratio > F_NBR(1.05)) {
319+ ratio = F_NBR(1.05);
320+ }
321+ ctx->ratio = ratio;
322+
323+ // Increment the nowaitctr, as this time we did not had to wait
324+ if (ctx->nowaitctr < 50)
325+ ctx->nowaitctr ++;
326+
327+ D("get[%p]: Adjusting ratio to try to queue as empty as possible: New ratio: %u",ctx, ratio);
328+
329+ } else {
330+ // We had to wait. The queue is running too fast. Adjust it so the next time we don´t
331+ // have to wait...
332+ unsigned int waitidx = ctx->waitidx;
333+ unsigned int ratio = ctx->ratio;
334+ ratio -= ratio * deltatm / samples;
335+
336+ // Limit to sensible values
337+ if (ratio < F_NBR(0.95)) {
338+ ratio = F_NBR(0.95);
339+ }
340+ ctx->ratio = ratio;
341+
342+ // We had to wait... Adjust the wait index to try to make it nonwait most of the time
343+ if (ctx->nowaitctr < 50) {
344+ if (waitidx > 1)
345+ waitidx --;
346+ } else if (ctx->nowaitctr > 50) {
347+ if (waitidx < 50)
348+ waitidx ++;
349+ }
350+ ctx->waitidx = waitidx;
351+
352+ // And restart counting
353+ ctx->nowaitctr = 0;
354+
355+ D("get[%p]: Adjusting rate to try to avoid waiting: New ratio: %u, waitidx: %u",ctx,ratio,waitidx);
356+ }
357+#endif
358+
359+#if !NEW_SYNC_ALGO
360+ // Adjust ratio if queue is getting empty, to keep fullness under control
361+ if (samples != samples_todo && /* Something output */
362+ ctx->low && /* Limit set */
363+ CIRC_CNT(ctx->wr_pos,ctx->rd_pos,ctx->size) < ctx->low) {
364+
365+ unsigned int ratio = ctx->ratio;
366+ ratio -= ratio / 200;
367+
368+ // Limit to sensible values
369+ if (ratio < F_NBR(0.95)) {
370+ ratio = F_NBR(0.95);
371+ }
372+ ctx->ratio = ratio;
373+
374+ D("get[%p]: Adjusting rate to keep queue at least 1/4 full: New ratio: %u",ctx,ratio);
375+ }
376+#endif
377+
378+ // Apply AGC to the samples
379+ if (ctx->sample_sz == 2 ) {
380+ agc_process_16bit(&ctx->agc,(short*) data, samples - samples_todo);
381+ } else {
382+ agc_process_8bit(&ctx->agc,(unsigned char*) data, samples - samples_todo);
383+ }
384+
385+#ifdef CHECK_MEM_OVERRUN
386+ if (((int*)ctx->data)[-1] != 0x1A2B6C7D) {
387+ ALOGE("get[%p] Memory corruption at start: Found: %08x",ctx, ((int*)ctx->data)[-1]);
388+ }
389+
390+ if (((int*)ctx->data)[(ctx->size*ctx->sample_sz)>>2] != 0xD7C6B2A1) {
391+ ALOGE("get[%p] Memory corruption at end: Found: %08x",ctx, ((int*)ctx->data)[ctx->size*ctx->sample_sz]);
392+ }
393+#endif
394+
395+
396+ // Return the count of read samples
397+ return samples - samples_todo;
398+}
399+
400+int AudioQueue_end(struct AudioQueue* ctx)
401+{
402+
403+ // If exited, avoid reexecuting deinitialization
404+ if (!ctx->running)
405+ return 0;
406+
407+ // Signal end
408+ ctx->running = 0;
409+
410+ // Some delay to let add and get end...
411+ sleep(1);
412+
413+#ifdef CHECK_MEM_OVERRUN
414+ free(((int*)ctx->data)-1);
415+#else
416+ free(ctx->data);
417+#endif
418+
419+ memset(ctx,0,sizeof(struct AudioQueue));
420+ return 0;
421+}
--- /dev/null
+++ b/huaweigeneric-ril/audioqueue.h
@@ -0,0 +1,64 @@
1+/*
2+**
3+** Copyright (C) 2012 Eduardo José Tagle <ejtagle@tutopia.com>
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+
19+/* A resampling Audio queue with AGC */
20+
21+#ifndef __AUDIOQUEUE_H
22+#define __AUDIOQUEUE_H 1
23+
24+#include <pthread.h>
25+#include <sys/time.h>
26+#include "agc.h"
27+
28+#define NEW_SYNC_ALGO 0
29+
30+struct AudioQueue {
31+ volatile int running; // != 0 if running
32+ unsigned int size; // Queue size in samples
33+#if !NEW_SYNC_ALGO
34+ unsigned int maxgetreq; // Maximum request size
35+ unsigned int low; // Low limit
36+ unsigned int high; // High limit
37+#else
38+ unsigned int nowaitctr; // No waiting counter
39+ unsigned int waitidx; // Wait index
40+#endif
41+ unsigned int sample_sz; // Sample size in bytes
42+ unsigned int wr_pos; // Write position in samples
43+ unsigned int rd_pos; // Read position in samples
44+ unsigned int ratio; // Resampling ratio including speedup/speeddown due to fullness
45+ unsigned int step; // Linear interpolation step
46+ struct agc_ctx agc; // AGC control
47+ void* data; // Queue Data buffer
48+};
49+
50+#ifdef __cplusplus
51+extern "C" {
52+#endif
53+
54+int AudioQueue_init(struct AudioQueue* ctx,unsigned int p2maxsamples, unsigned int sample_sz);
55+int AudioQueue_isrunning(struct AudioQueue* ctx);
56+int AudioQueue_add(struct AudioQueue* ctx, void* data,unsigned int samples);
57+int AudioQueue_get(struct AudioQueue* ctx, void* data,unsigned int samples,unsigned int timeout);
58+int AudioQueue_end(struct AudioQueue* ctx);
59+
60+#ifdef __cplusplus
61+}
62+#endif
63+
64+#endif
\ No newline at end of file
--- /dev/null
+++ b/huaweigeneric-ril/echocancel.c
@@ -0,0 +1,205 @@
1+/*
2+ * Copyrightm (C) 2010 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#include <stdio.h>
18+#include <string.h>
19+#include <stdint.h>
20+#include <string.h>
21+#include <math.h>
22+
23+#define LOG_TAG "EchoCancel"
24+#include <utils/Log.h>
25+
26+#include "echocancel.h"
27+
28+// It is very difficult to do echo cancellation at this level due to the lack of
29+// the timing information of the samples being played and recorded. Therefore,
30+// for the first release only echo suppression is implemented.
31+
32+// The algorithm is derived from the "previous works" summarized in
33+// A new class of doubletalk detectors based on cross-correlation,
34+// J Benesty, DR Morgan, JH Cho, IEEE Trans. on Speech and Audio Processing.
35+// The method proposed in that paper is not used because of its high complexity.
36+
37+// It is well known that cross-correlation can be computed using convolution,
38+// but unfortunately not every mobile processor has a (fast enough) FPU. Thus
39+// we use integer arithmetic as much as possible and do lots of bookkeeping.
40+// Again, parameters and thresholds are chosen by experiments.
41+
42+int echocancel_init(struct echocancel_ctx* ctx,int sampleCount, int tailLength)
43+{
44+ int shift;
45+
46+ tailLength += sampleCount * 4;
47+
48+ shift = 0;
49+ while ((sampleCount >> shift) > 1 && (tailLength >> shift) > 256) {
50+ ++shift;
51+ }
52+
53+ ctx->Shift = shift + 4;
54+ ctx->Scale = 1 << shift;
55+ ctx->SampleCount = sampleCount;
56+ ctx->WindowSize = sampleCount >> shift;
57+ ctx->TailLength = tailLength >> shift;
58+ ctx->RecordLength = tailLength * 2 / sampleCount;
59+ ctx->RecordOffset = 0;
60+
61+ ctx->Xs = calloc(sizeof(*ctx->Xs), (ctx->TailLength + ctx->WindowSize));
62+ ctx->XSums = calloc(sizeof(*ctx->XSums), (ctx->TailLength));
63+ ctx->X2Sums = calloc(sizeof(*ctx->X2Sums), ctx->TailLength);
64+ ctx->XRecords = calloc(sizeof(*ctx->XRecords), (ctx->RecordLength * ctx->WindowSize));
65+
66+ ctx->YSum = 0;
67+ ctx->Y2Sum = 0;
68+ ctx->YRecords = calloc(sizeof(*ctx->YRecords), ctx->RecordLength);
69+ ctx->Y2Records = calloc(sizeof (*ctx->Y2Records), ctx->RecordLength);
70+
71+ ctx->XYSums = calloc(sizeof(*ctx->XYSums), ctx->TailLength);
72+ ctx->XYRecords = calloc(sizeof(*ctx->XYRecords), ctx->RecordLength * ctx->TailLength);
73+
74+ ctx->LastX = 0;
75+ ctx->LastY = 0;
76+ ctx->Weight = 1.0f / (ctx->RecordLength * ctx->WindowSize);
77+
78+ return 0;
79+}
80+
81+void echocancel_end(struct echocancel_ctx* ctx)
82+{
83+ free(ctx->Xs);
84+ free(ctx->XSums);
85+ free(ctx->X2Sums);
86+ free(ctx->XRecords);
87+ free(ctx->YRecords);
88+ free(ctx->Y2Records);
89+ free(ctx->XYSums);
90+ free(ctx->XYRecords);
91+ memset(ctx, 0, sizeof(*ctx));
92+}
93+
94+void echocancel_run(struct echocancel_ctx* ctx,int16_t *playbacked, int16_t *recorded)
95+{
96+ uint16_t *xRecords;
97+ uint16_t ys[ctx->WindowSize];
98+ uint32_t ySum = 0;
99+ uint32_t y2Sum = 0;
100+ uint32_t *xyRecords;
101+ int latency = 0;
102+ float corr2 = 0.0f;
103+ float varX = 0.0f;
104+ float varY;
105+ int i,j;
106+
107+ // Update Xs.
108+ for (i = ctx->TailLength - 1; i >= 0; --i) {
109+ ctx->Xs[i + ctx->WindowSize] = ctx->Xs[i];
110+ }
111+ for (i = ctx->WindowSize - 1, j = 0; i >= 0; --i, j += ctx->Scale) {
112+ uint32_t sum = 0;
113+ int k;
114+ for (k = 0; k < ctx->Scale; ++k) {
115+ int32_t x = playbacked[j + k] << 15;
116+ ctx->LastX += x;
117+ sum += ((ctx->LastX >= 0) ? ctx->LastX : -ctx->LastX) >> 15;
118+ ctx->LastX -= (ctx->LastX >> 10) + x;
119+ }
120+ ctx->Xs[i] = sum >> ctx->Shift;
121+ }
122+
123+ // Update XSums, X2Sums, and XRecords.
124+ for (i = ctx->TailLength - ctx->WindowSize - 1; i >= 0; --i) {
125+ ctx->XSums[i + ctx->WindowSize] = ctx->XSums[i];
126+ ctx->X2Sums[i + ctx->WindowSize] = ctx->X2Sums[i];
127+ }
128+ xRecords = &ctx->XRecords[ctx->RecordOffset * ctx->WindowSize];
129+ for (i = ctx->WindowSize - 1; i >= 0; --i) {
130+ uint16_t x = ctx->Xs[i];
131+ ctx->XSums[i] = ctx->XSums[i + 1] + x - xRecords[i];
132+ ctx->X2Sums[i] = ctx->X2Sums[i + 1] + x * x - xRecords[i] * xRecords[i];
133+ xRecords[i] = x;
134+ }
135+
136+ // Compute Ys.
137+ for (i = ctx->WindowSize - 1, j = 0; i >= 0; --i, j += ctx->Scale) {
138+ uint32_t sum = 0;
139+ int k;
140+ for (k = 0; k < ctx->Scale; ++k) {
141+ int32_t y = recorded[j + k] << 15;
142+ ctx->LastY += y;
143+ sum += ((ctx->LastY >= 0) ? ctx->LastY : -ctx->LastY) >> 15;
144+ ctx->LastY -= (ctx->LastY >> 10) + y;
145+ }
146+ ys[i] = sum >> ctx->Shift;
147+ }
148+
149+ // Update YSum, Y2Sum, YRecords, and Y2Records.
150+ ySum = 0;
151+ y2Sum = 0;
152+ for (i = ctx->WindowSize - 1; i >= 0; --i) {
153+ ySum += ys[i];
154+ y2Sum += ys[i] * ys[i];
155+ }
156+ ctx->YSum += ySum - ctx->YRecords[ctx->RecordOffset];
157+ ctx->Y2Sum += y2Sum - ctx->Y2Records[ctx->RecordOffset];
158+ ctx->YRecords[ctx->RecordOffset] = ySum;
159+ ctx->Y2Records[ctx->RecordOffset] = y2Sum;
160+
161+ // Update XYSums and XYRecords.
162+ xyRecords = &ctx->XYRecords[ctx->RecordOffset * ctx->TailLength];
163+ for (i = ctx->TailLength - 1; i >= 0; --i) {
164+ uint32_t xySum = 0;
165+ for (j = ctx->WindowSize - 1; j >= 0; --j) {
166+ xySum += ctx->Xs[i + j] * ys[j];
167+ }
168+ ctx->XYSums[i] += xySum - xyRecords[i];
169+ xyRecords[i] = xySum;
170+ }
171+
172+ // Compute correlations.
173+ latency = 0;
174+ corr2 = 0.0f;
175+ varX = 0.0f;
176+ varY = ctx->Y2Sum - ctx->Weight * ctx->YSum * ctx->YSum;
177+ for (i = ctx->TailLength - 1; i >= 0; --i) {
178+ float cov = ctx->XYSums[i] - ctx->Weight * ctx->XSums[i] * ctx->YSum;
179+ if (cov > 0.0f) {
180+ float varXi = ctx->X2Sums[i] - ctx->Weight * ctx->XSums[i] * ctx->XSums[i];
181+ float corr2i = cov * cov / (varXi * varY + 1);
182+ if (corr2i > corr2) {
183+ varX = varXi;
184+ corr2 = corr2i;
185+ latency = i;
186+ }
187+ }
188+ }
189+ //ALOGI("corr^2 %.5f, var %8.0f %8.0f, latency %d", corr2, varX, varY,
190+ // latency * mScale);
191+
192+ // Do echo suppression.
193+ if (corr2 > 0.1f && varX > 10000.0f) {
194+ int factor = (corr2 > 1.0f) ? 0 : (1.0f - sqrtf(corr2)) * 4096;
195+ for (i = 0; i < ctx->SampleCount; ++i) {
196+ recorded[i] = recorded[i] * factor >> 16;
197+ }
198+ }
199+
200+ // Increase RecordOffset.
201+ ++ctx->RecordOffset;
202+ if (ctx->RecordOffset == ctx->RecordLength) {
203+ ctx->RecordOffset = 0;
204+ }
205+}
--- /dev/null
+++ b/huaweigeneric-ril/echocancel.h
@@ -0,0 +1,63 @@
1+/*
2+ * Copyrightm (C) 2010 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#ifndef __ECHO_CANCEL_H
18+#define __ECHO_CANCEL_H
19+
20+#include <stdint.h>
21+
22+struct echocancel_ctx {
23+ int Shift;
24+ int Scale;
25+ int SampleCount;
26+ int WindowSize;
27+ int TailLength;
28+ int RecordLength;
29+ int RecordOffset;
30+
31+ uint16_t *Xs;
32+ uint32_t *XSums;
33+ uint32_t *X2Sums;
34+ uint16_t *XRecords;
35+
36+ uint32_t YSum;
37+ uint32_t Y2Sum;
38+ uint32_t *YRecords;
39+ uint32_t *Y2Records;
40+
41+ uint32_t *XYSums;
42+ uint32_t *XYRecords;
43+
44+ int32_t LastX;
45+ int32_t LastY;
46+
47+ float Weight;
48+};
49+
50+#ifdef __cplusplus
51+extern "C" {
52+#endif
53+
54+// The sampleCount must be power of 2.
55+int echocancel_init(struct echocancel_ctx* ctx,int sampleCount, int tailLength);
56+void echocancel_end(struct echocancel_ctx* ctx);
57+void echocancel_run(struct echocancel_ctx* ctx,int16_t *playbacked, int16_t *recorded);
58+
59+#ifdef __cplusplus
60+}
61+#endif
62+
63+#endif
--- a/huaweigeneric-ril/fcp_parser.c
+++ b/huaweigeneric-ril/fcp_parser.c
@@ -124,6 +124,6 @@ int fcp_to_ts_51011(/*in*/ const char *stream, /*in*/ size_t len,
124124
125125 except:
126126 #undef FCP_CVT_THROW
127- ALOGE("%s() FCP to TS 510 11: Specification violation: %s.", __func__, what);
127+ ALOGW("%s() FCP to TS 510 11: Specification violation: %s.", __func__, what);
128128 goto finally;
129129 }
--- a/huaweigeneric-ril/gsm.c
+++ b/huaweigeneric-ril/gsm.c
@@ -171,7 +171,7 @@ gsm_hex_to_bytes( cbytes_t hex, int hexlen, bytes_t dst )
171171 int nn;
172172
173173 for (nn = 0; nn < hexlen/2; nn++ ) {
174- dst[nn] = (byte_t) gsm_hex2_to_byte0( hex+2*nn );
174+ dst[nn] = (byte_t) gsm_hex2_to_byte0( (char const*) hex+2*nn );
175175 }
176176 if (hexlen & 1) {
177177 dst[nn] = gsm_hexchar_to_int0( hex[2*nn] ) << 4;
@@ -282,7 +282,8 @@ gsm_rope_can_grow( GsmRope rope, int count )
282282 if (!rope->data || rope->error)
283283 return 0;
284284
285- if (rope->pos + count > rope->max) {
285+ if (rope->pos + count > rope->max)
286+ {
286287 if (rope->data == NULL)
287288 rope->max = rope->pos + count;
288289
@@ -316,7 +317,8 @@ gsm_rope_reserve( GsmRope rope, int count )
316317 {
317318 void* result = NULL;
318319
319- if (gsm_rope_can_grow(rope, count)) {
320+ if (gsm_rope_can_grow(rope, count))
321+ {
320322 if (rope->data != NULL)
321323 result = rope->data + rope->pos;
322324 }
@@ -1100,7 +1102,7 @@ sim_adn_record_from_bytes( SimAdnRecord rec, cbytes_t data, int len )
11001102 /* alpha is optional */
11011103 if (len > ADN_FOOTER_SIZE) {
11021104 cbytes_t dataend = data + len - ADN_FOOTER_SIZE;
1103- int count = sim_adn_alpha_to_utf8(data, dataend, NULL);
1105+ unsigned int count = sim_adn_alpha_to_utf8(data, dataend, NULL);
11041106
11051107 if (count > sizeof(rec->adn.alpha)-1) /* too long */
11061108 return -1;
@@ -1116,7 +1118,7 @@ sim_adn_record_from_bytes( SimAdnRecord rec, cbytes_t data, int len )
11161118 /* decode TON and number to ASCII, NOTE: this is lossy !! */
11171119 {
11181120 int ton = footer[ADN_OFFSET_TON_NPI];
1119- bytes_t number = rec->adn.number;
1121+ bytes_t number = (bytes_t) rec->adn.number;
11201122 int len = sizeof(rec->adn.number)-1;
11211123 int count;
11221124
@@ -1141,13 +1143,13 @@ sim_adn_record_to_bytes( SimAdnRecord rec, bytes_t data, int datalen )
11411143 bytes_t end = data + datalen;
11421144 bytes_t footer = end - ADN_FOOTER_SIZE;
11431145 int ton = 0x81;
1144- cbytes_t number = rec->adn.number;
1146+ cbytes_t number = (cbytes_t) rec->adn.number;
11451147 int len;
11461148
11471149 if (number[0] == '+') {
11481150 ton = 0x91;
11491151 number += 1;
11501152 }
1151- footer[0] = (strlen(number)+1)/2 + 1;
1153+ footer[0] = (strlen((const char*) number)+1)/2 + 1;
11521154 return 0;
11531155 }
--- a/huaweigeneric-ril/huaweigeneric-ril.c
+++ b/huaweigeneric-ril/huaweigeneric-ril.c
@@ -1,4 +1,4 @@
1-/* //device/system/htcgeneric-ril/htcgeneric-ril.c
1+/*
22 **
33 ** Copyright 2006, The Android Open Source Project
44 ** Copyright 2012 Eduardo Jos[e Tagle <ejtagle@tutopia.com>
@@ -16,38 +16,10 @@
1616 ** limitations under the License.
1717 */
1818
19-/*
20-AT^CURC=0
21-ATQ0V1
22-
23-^MODE:
24-^RSSI:
25-^SRVST:
26-+CCCM:
27-^CONN:
28-^CEND:
29-+CDSI:
30-^SMMEMFULL:
31-+CSSU:
32-^DCONN
33-^DEND
34-^SIMST ¡
35-+CRING:
36-AT^SYSCFG=2,3,%s,1,2
37-^RSSI
38-^SMMEMFULL
39-*/
40-
41-/*
42-AT^SYSCFG=2,1,3FFFFFFF,1,2 for GPRS/EDGE Preferred
43-AT^SYSCFG=2,2,3FFFFFFF,1,2 for 3G Preferred
44-AT^SYSCFG=13,1,3FFFFFFF,1,2 for GPRS/EDGE Only
45-AT^SYSCFG=14,2,3FFFFFFF,1,2 for 3G Only
46-
47-The third parameter, 0x3FFFFFFF tells the card to use all bands. A value of 0x400380 here means GSM900/1800/WCDMA2100 only and a value of 0x200000 here means GSM1900 only.
19+//#define BYPASS_AUDIO_CHECK 1
4820
49-I don't know what the final "1,2" parameter is for. But for some it has to be "2,4" instead for some reason.
5021
22+/*
5123 The status updates from the second port are prefixed with a caret and are of these forms:
5224
5325 ^MODE:3,2 indicates GPRS
@@ -92,6 +64,23 @@ then I plug in on my Linux Ubuntu computer, use minicom and type AT^U2DIAG=0 to
9264 Maybe it's better to first type AT^U2DIAG=0 and then AT^U2DIAG=5 ...
9365
9466 Regards, Phil.
67+
68+
69+-----
70+1)with unaccepted sim
71+-> AT^CARDLOCK?
72+<-^CARDLOCK: 1,10,0 ............ locked
73+<-^CARDLOCK: 2,10,0 ............ unlocked
74+Quote:
75+Originally Posted by sergeymkl
76+4. second number of reply to CARDLOCK inquiry.
77+<-^CARDLOCK: 1,10,0 ............ locked
78+<-^CARDLOCK: 2,10,0 ............ unlocked
79+<-^CARDLOCK: A,B,C ............
80+A = is to verify if locked or unlocked
81+B = attempts left? or total given attempts?
82+C = is for?
83+
9584 */
9685
9786 #define LOG_NDEBUG 0
@@ -112,6 +101,7 @@ Regards, Phil.
112101 #include "atchannel.h"
113102 #include "at_tok.h"
114103 #include "misc.h"
104+#include "net-utils.h"
115105 #include "gsm.h"
116106 #include "requestdatahandler.h"
117107 #include "fcp_parser.h"
@@ -121,11 +111,18 @@ Regards, Phil.
121111 #include <cutils/sockets.h>
122112 #include <termios.h>
123113 #include <cutils/properties.h>
114+#include <log/logger.h>
124115 #include <stdbool.h>
116+#include <stddef.h>
125117
126-#define D ALOGD
118+#include <linux/if.h>
119+#include <linux/sockios.h>
120+#include <linux/route.h>
121+#include <linux/wireless.h>
127122
128-#define RIL_VERSION_STRING "Huawei-ril 1.0.0.0"
123+#define D ALOGI
124+
125+#define RIL_VERSION_STRING "Huawei-ril 1.0.0.8 (Built on " __DATE__" " __TIME__ ")"
129126
130127 #define timespec_cmp(a, b, op) \
131128 ((a).tv_sec == (b).tv_sec \
@@ -136,10 +133,6 @@ Regards, Phil.
136133 #define TIMEOUT_EMRDY 10 /* Module should respond at least within 10s */
137134 #define MAX_BUF 1024
138135
139-/* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
140-#define PPP_TTY_PATH "ppp0"
141-
142-
143136 /** declarations */
144137 static const char *getVersion();
145138 static void signalCloseQueues(void);
@@ -154,8 +147,9 @@ static int getCardStatus(RIL_CardStatus_v6 **pp_card_status);
154147 static void freeCardStatus(RIL_CardStatus_v6 *p_card_status);
155148 static void onDataCallListChanged(void *param);
156149 static int killConn(const char * cid);
157-static int wait_for_property(const char *name, const char *desired_value, int maxwait);
150+static int wait_for_property(const char *name, const char *desired_value, int maxwait, int allowempty);
158151 static void checkMessageStorageReady(void *p);
152+static int pppSupported(void);
159153 static void onSIMReady(void *p);
160154 static void pollSIMState(void *param);
161155 static void checkMessageStorageReady(void *p);
@@ -172,6 +166,19 @@ static const RIL_RadioFunctions s_callbacks = {
172166 getVersion
173167 };
174168
169+static char* rndis_iface_dev = "/dev/ttyUSB0";
170+static char* ppp_iface_dev = "/dev/ttyUSB0";
171+static int using_rndis = 0;
172+
173+/* Last call index status */
174+static int lastCallIdx = 0;
175+
176+/* Last call fail cause */
177+static int lastCallFailCause = CALL_FAIL_NORMAL;
178+
179+#define RNDIS_IFACE "rmnet0"
180+#define PPP_IFACE "ppp0"
181+
175182 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
176183 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
177184 static const struct timespec TIMEVAL_SIMPOLL = {1,0};
@@ -223,12 +230,15 @@ static RequestQueue *s_requestQueues[] = {
223230 };
224231
225232 /* The Audio channel */
226-static struct GsmAudioTunnel sAudioChannel = GSM_AUDIO_CHANNEL_STATIC_INIT;
233+static struct GsmAudioTunnel sAudioChannel;
227234 static char sAudioDevice[64] = {0};
228235
236+static int audioTunnelMuted = 0; // If audio tunnel is muted
237+
229238 /* Starts the audio tunnel channel */
230-static void startAudioTunnel(void)
239+static void startAudioTunnel(void* param)
231240 {
241+ ALOGD("call startAudioTunnel");
232242 #if 0
233243 ATResponse *atResponse = NULL;
234244 int err;
@@ -236,16 +246,16 @@ static void startAudioTunnel(void)
236246 int voice_disabled = 0, sampling_rate = 8000,
237247 bits_per_sample = 16, framesize_ms = 20;
238248
239- if (sAudioChannel.running)
249+ if (gsm_audio_tunnel_running(&sAudioChannel))
240250 return;
241251
242- // Enable voice function
252+ // Enable voice function - Some firmwares fail this command, but
253+ // nevertheless, it works. Leave validation for the next one.
243254 err = at_send_command("AT^CVOICE=0");
244- if (err != AT_NOERROR)
245- goto error;
246255
247- // Check status.
248- err = at_send_command_singleline("AT^CVOICE=?", "^CVOICE:", &atResponse);
256+#ifndef BYPASS_AUDIO_CHECK
257+ // Check status - This is the check that matters!
258+ err = at_send_command_singleline("AT^CVOICE?", "^CVOICE:", &atResponse);
249259 if (err != AT_NOERROR)
250260 goto error;
251261
@@ -256,6 +266,9 @@ static void startAudioTunnel(void)
256266 err = at_tok_nextint(&line, &voice_disabled);
257267 if (err < 0) goto error;
258268
269+ // Check if voice was really enabled
270+ if (voice_disabled != 0) goto error;
271+
259272 err = at_tok_nextint(&line, &sampling_rate);
260273 if (err < 0) goto error;
261274
@@ -264,11 +277,17 @@ static void startAudioTunnel(void)
264277
265278 err = at_tok_nextint(&line, &framesize_ms);
266279 if (err < 0) goto error;
280+#else
281+ sampling_rate = 8000;
282+ bits_per_sample = 16;
283+ framesize_ms = 20;
284+#endif
267285
268- /* Switch to audio from USB1 */
269- err = at_send_command("AT^DDSETEX=2");
270- if (err != AT_NOERROR)
271- goto error;
286+ /* Increase volume to maximum. Some modems do not set the volume if not
287+ actually changing values.... And some of them do not understand the
288+ command at all. Try to switch volume to maximum - DerArtem */
289+ err = at_send_command("AT+CLVL=1"); /* Lo volume */
290+ err = at_send_command("AT+CLVL=5"); /* Maximum volume */
272291
273292 /* Start the audio channel */
274293 err = gsm_audio_tunnel_start(&sAudioChannel,sAudioDevice,
@@ -276,7 +295,10 @@ static void startAudioTunnel(void)
276295 if (err)
277296 goto error;
278297
279- ALOGE("Audio Tunnel enabled");
298+ // Mute/Ummute audioTunnel as requested
299+ gsm_audio_tunnel_mute(&sAudioChannel,audioTunnelMuted);
300+
301+ ALOGD("Audio Tunnel enabled");
280302 at_response_free(atResponse);
281303 return;
282304
@@ -284,21 +306,37 @@ error:
284306 ALOGE("Failed to start audio tunnel");
285307
286308 at_response_free(atResponse);
287- return;
288309 #endif
310+ return;
289311 }
290312
291313 /* Stops the audio tunnel channel */
292-static void stopAudioTunnel(void)
314+static void stopAudioTunnel(void* param)
293315 {
294316 #if 0
295- if (!sAudioChannel.running)
317+ if (!gsm_audio_tunnel_running(&sAudioChannel))
296318 return;
297319
298320 // Stop the audio tunnel
299321 gsm_audio_tunnel_stop(&sAudioChannel);
322+#endif
323+
324+ ALOGD("Audio Tunnel disabled");
325+}
326+
327+static void muteAudioTunnel(int muteit)
328+{
329+ ALOGD("call muteAudioTunnel");
330+#if 0
331+ audioTunnelMuted = muteit;
300332
301- D("Audio Tunnel disabled");
333+ ALOGD("Audio Tunnel %smuted",muteit?"":"un");
334+
335+ if (!gsm_audio_tunnel_running(&sAudioChannel))
336+ return;
337+
338+ // Mute/Ummute audioTunnel if requested
339+ gsm_audio_tunnel_mute(&sAudioChannel,audioTunnelMuted);
302340 #endif
303341 }
304342
@@ -313,15 +351,14 @@ static void enqueueRILEvent(void (*callback) (void *param),
313351 char done = 0;
314352 RequestQueue *q = NULL;
315353
316- RILEvent *e = (RILEvent *) malloc(sizeof(RILEvent));
317- memset(e, 0, sizeof(RILEvent));
354+ RILEvent *e = (RILEvent *) calloc(1, sizeof(RILEvent));
318355
319356 e->eventCallback = callback;
320357 e->param = param;
321358
322359 if (relativeTime == NULL) {
323360 relativeTime = (const struct timespec *) alloca(sizeof(struct timespec));
324- memset((struct timespec *) relativeTime, 0, sizeof(struct timespec));
361+ memset((void *) relativeTime, 0, sizeof(struct timespec));
325362 }
326363
327364 clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -376,16 +413,16 @@ again:
376413
377414 }
378415
416+
379417 /** returns 1 if on, 0 if off, and -1 on error */
380418 static int isRadioOn()
381419 {
382420 ATResponse *atResponse = NULL;
383- int err,ison;
421+ int err;
384422 char *line;
385- char ret1,ret2;
386-
387- err = at_send_command_singleline("AT^RFSWITCH?", "^RFSWITCH:", &atResponse);
423+ char ret1;
388424
425+ err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &atResponse);
389426 if (err != AT_NOERROR) {
390427 // assume radio is off
391428 goto error;
@@ -399,20 +436,14 @@ static int isRadioOn()
399436 err = at_tok_nextbool(&line, &ret1);
400437 if (err < 0) goto error;
401438
402- err = at_tok_nextbool(&line, &ret2);
403- if (err < 0) goto error;
404-
405439 at_response_free(atResponse);
406440
407- /* 1 is ON, 0 is OFF */
408- ison = (ret1 == 1 && ret2 == 1);
441+ ALOGD("Radio is %s", (ret1 == 1) ? "On" : "Off");
409442
410- ALOGD("Radio is %s", ison ? "On" : "Off");
411-
412- return ison;
443+ /* 1=means online, all the others, mean offline */
444+ return (ret1 == 1) ? 1 : 0;
413445
414446 error:
415-
416447 at_response_free(atResponse);
417448 return -1;
418449 }
@@ -423,39 +454,39 @@ static const char *radioStateToString(RIL_RadioState radioState)
423454 const char *state;
424455
425456 switch (radioState) {
426- case RADIO_STATE_OFF:
427- state = "RADIO_STATE_OFF";
428- break;
429- case RADIO_STATE_UNAVAILABLE:
430- state = "RADIO_STATE_UNAVAILABLE";
431- break;
432- case RADIO_STATE_SIM_NOT_READY:
433- state = "RADIO_STATE_SIM_NOT_READY";
434- break;
435- case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
436- state = "RADIO_STATE_SIM_LOCKED_OR_ABSENT";
437- break;
438- case RADIO_STATE_SIM_READY:
439- state = "RADIO_STATE_SIM_READY";
440- break;
441- case RADIO_STATE_RUIM_NOT_READY:
442- state = "RADIO_STATE_RUIM_NOT_READY";
443- break;
444- case RADIO_STATE_RUIM_READY:
445- state = "RADIO_STATE_RUIM_READY";
446- break;
447- case RADIO_STATE_RUIM_LOCKED_OR_ABSENT:
448- state = "RADIO_STATE_RUIM_READY";
449- break;
450- case RADIO_STATE_NV_NOT_READY:
451- state = "RADIO_STATE_NV_NOT_READY";
452- break;
453- case RADIO_STATE_NV_READY:
454- state = "RADIO_STATE_NV_READY";
455- break;
456- default:
457- state = "RADIO_STATE_<> Unknown!";
458- break;
457+ case RADIO_STATE_OFF:
458+ state = "RADIO_STATE_OFF";
459+ break;
460+ case RADIO_STATE_UNAVAILABLE:
461+ state = "RADIO_STATE_UNAVAILABLE";
462+ break;
463+ case RADIO_STATE_SIM_NOT_READY:
464+ state = "RADIO_STATE_SIM_NOT_READY";
465+ break;
466+ case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
467+ state = "RADIO_STATE_SIM_LOCKED_OR_ABSENT";
468+ break;
469+ case RADIO_STATE_SIM_READY:
470+ state = "RADIO_STATE_SIM_READY";
471+ break;
472+ case RADIO_STATE_RUIM_NOT_READY:
473+ state = "RADIO_STATE_RUIM_NOT_READY";
474+ break;
475+ case RADIO_STATE_RUIM_READY:
476+ state = "RADIO_STATE_RUIM_READY";
477+ break;
478+ case RADIO_STATE_RUIM_LOCKED_OR_ABSENT:
479+ state = "RADIO_STATE_RUIM_READY";
480+ break;
481+ case RADIO_STATE_NV_NOT_READY:
482+ state = "RADIO_STATE_NV_NOT_READY";
483+ break;
484+ case RADIO_STATE_NV_READY:
485+ state = "RADIO_STATE_NV_READY";
486+ break;
487+ default:
488+ state = "RADIO_STATE_<> Unknown!";
489+ break;
459490 }
460491
461492 return state;
@@ -471,7 +502,6 @@ static RIL_RadioState getRadioState()
471502 return sState;
472503 }
473504
474-
475505 static void setRadioState(RIL_RadioState newState)
476506 {
477507 RIL_RadioState oldState;
@@ -483,7 +513,7 @@ static void setRadioState(RIL_RadioState newState)
483513 oldState = sState;
484514
485515 ALOGI("%s() oldState=%s newState=%s", __func__, radioStateToString(oldState),
486- radioStateToString(newState));
516+ radioStateToString(newState));
487517
488518 sState = newState;
489519
@@ -493,16 +523,63 @@ static void setRadioState(RIL_RadioState newState)
493523 /* Do these outside of the mutex. */
494524 if (sState != oldState || sState == RADIO_STATE_SIM_LOCKED_OR_ABSENT) {
495525 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
496- NULL, 0);
526+ NULL, 0);
497527
498528 if (sState == RADIO_STATE_SIM_READY) {
499529 enqueueRILEvent(checkMessageStorageReady, NULL, NULL);
500530 enqueueRILEvent(onSIMReady, NULL, NULL);
501- } else if (sState == RADIO_STATE_SIM_NOT_READY)
531+ } else if (sState == RADIO_STATE_SIM_NOT_READY) {
502532 enqueueRILEvent(pollSIMState, NULL, NULL);
533+ }
534+ }
535+}
536+
537+/*
538+-> AT^CARDLOCK?
539+<-^CARDLOCK: 1,10,0 ............ locked to an operator: Can be unlocked by code
540+<-^CARDLOCK: 2,10,0 ............ unlocked
541+<-^CARDLOCK: 3,10,0 ............ locked: Datacard is locked forever to an operator
542+<-^CARDLOCK: A,B,C ............
543+A = is to verify if locked or unlocked
544+B = attempts left? or total given attempts?
545+C = is for?
546+*/
547+
548+static int getSimLockStatus(int* status, int* times)
549+{
550+ ATResponse *atResponse = NULL;
551+ int err;
552+ char *line;
553+
554+ err = at_send_command_singleline("AT^CARDLOCK?", "^CARDLOCK:", &atResponse);
555+
556+ if (err != AT_NOERROR) {
557+ // assume locked
558+ goto error;
503559 }
560+
561+ line = atResponse->p_intermediates->line;
562+
563+ err = at_tok_start(&line);
564+ if (err < 0) goto error;
565+
566+ err = at_tok_nextint(&line, status);
567+ if (err < 0) goto error;
568+
569+ err = at_tok_nextint(&line, times);
570+ if (err < 0) goto error;
571+
572+ at_response_free(atResponse);
573+
574+ ALOGD("Card %s, times: %d", *status == 1 ? "Locked" : "Unlocked" , *times);
575+ return 0;
576+
577+error:
578+ at_response_free(atResponse);
579+ return -1;
504580 }
505581
582+
506583 typedef enum {
507584 SIM_ABSENT = 0, /* SIM card is not inserted */
508585 SIM_NOT_READY = 1, /* SIM card is not ready */
@@ -534,6 +611,8 @@ typedef enum {
534611 UICC_TYPE_UIM,
535612 } UICC_Type;
536613
614+
615+
537616 /** Returns one of SIM_*. Returns SIM_NOT_READY on error. */
538617 static SIM_Status getSIMStatus(void)
539618 {
@@ -542,6 +621,7 @@ static SIM_Status getSIMStatus(void)
542621 SIM_Status ret = SIM_ABSENT;
543622 char *cpinLine;
544623 char *cpinResult;
624+ int status, times;
545625
546626 if (getRadioState() == RADIO_STATE_OFF ||
547627 getRadioState() == RADIO_STATE_UNAVAILABLE) {
@@ -557,51 +637,51 @@ static SIM_Status getSIMStatus(void)
557637 }
558638
559639 switch (at_get_cme_error(err)) {
560- case CME_SIM_NOT_INSERTED:
561- ret = SIM_ABSENT;
562- break;
563- case CME_SIM_PIN_REQUIRED:
564- ret = SIM_PIN;
565- break;
566- case CME_SIM_PUK_REQUIRED:
567- ret = SIM_PUK;
568- break;
569- case CME_SIM_PIN2_REQUIRED:
570- ret = SIM_PIN2;
571- break;
572- case CME_SIM_PUK2_REQUIRED:
573- ret = SIM_PUK2;
574- break;
575- case CME_NETWORK_PERSONALIZATION_PIN_REQUIRED:
576- ret = SIM_NETWORK_PERSO;
577- break;
578- case CME_NETWORK_PERSONALIZATION_PUK_REQUIRED:
579- ret = SIM_NETWORK_PERSO_PUK;
580- break;
581- case CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED:
582- ret = SIM_NETWORK_SUBSET_PERSO;
583- break;
584- case CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED:
585- ret = SIM_NETWORK_SUBSET_PERSO_PUK;
586- break;
587- case CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED:
588- ret = SIM_SERVICE_PROVIDER_PERSO;
589- break;
590- case CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED:
591- ret = SIM_SERVICE_PROVIDER_PERSO_PUK;
592- break;
593- case CME_PH_SIMLOCK_PIN_REQUIRED: /* PUK not in use by modem */
594- ret = SIM_SIM_PERSO;
595- break;
596- case CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED:
597- ret = SIM_CORPORATE_PERSO;
598- break;
599- case CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED:
600- ret = SIM_CORPORATE_PERSO_PUK;
601- break;
602- default:
603- ret = SIM_NOT_READY;
604- break;
640+ case CME_SIM_NOT_INSERTED:
641+ ret = SIM_ABSENT;
642+ break;
643+ case CME_SIM_PIN_REQUIRED:
644+ ret = SIM_PIN;
645+ break;
646+ case CME_SIM_PUK_REQUIRED:
647+ ret = SIM_PUK;
648+ break;
649+ case CME_SIM_PIN2_REQUIRED:
650+ ret = SIM_PIN2;
651+ break;
652+ case CME_SIM_PUK2_REQUIRED:
653+ ret = SIM_PUK2;
654+ break;
655+ case CME_NETWORK_PERSONALIZATION_PIN_REQUIRED:
656+ ret = SIM_NETWORK_PERSO;
657+ break;
658+ case CME_NETWORK_PERSONALIZATION_PUK_REQUIRED:
659+ ret = SIM_NETWORK_PERSO_PUK;
660+ break;
661+ case CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED:
662+ ret = SIM_NETWORK_SUBSET_PERSO;
663+ break;
664+ case CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED:
665+ ret = SIM_NETWORK_SUBSET_PERSO_PUK;
666+ break;
667+ case CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED:
668+ ret = SIM_SERVICE_PROVIDER_PERSO;
669+ break;
670+ case CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED:
671+ ret = SIM_SERVICE_PROVIDER_PERSO_PUK;
672+ break;
673+ case CME_PH_SIMLOCK_PIN_REQUIRED: /* PUK not in use by modem */
674+ ret = SIM_SIM_PERSO;
675+ break;
676+ case CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED:
677+ ret = SIM_CORPORATE_PERSO;
678+ break;
679+ case CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED:
680+ ret = SIM_CORPORATE_PERSO_PUK;
681+ break;
682+ default:
683+ ret = SIM_NOT_READY;
684+ break;
605685 }
606686 return ret;
607687 }
@@ -625,6 +705,11 @@ static SIM_Status getSIMStatus(void)
625705
626706 if (0 == strcmp(cpinResult, "READY")) {
627707 ret = SIM_READY;
708+ if (getSimLockStatus(&status,&times) < 0)
709+ goto done;
710+ if (status == 1 || status == 3) {
711+ ret = SIM_NETWORK_PERSO;
712+ }
628713 } else if (0 == strcmp(cpinResult, "SIM PIN")) {
629714 ret = SIM_PIN;
630715 } else if (0 == strcmp(cpinResult, "SIM PUK")) {
@@ -681,41 +766,39 @@ static void pollSIMState(void *param)
681766 return;
682767
683768 switch (getSIMStatus()) {
684- case SIM_NOT_READY:
685- ALOGI("SIM_NOT_READY, poll for sim state.");
686- enqueueRILEvent(pollSIMState, NULL, &TIMEVAL_SIMPOLL);
687- return;
769+ case SIM_NOT_READY:
770+ ALOGI("SIM_NOT_READY, poll for sim state.");
771+ enqueueRILEvent(pollSIMState, NULL, &TIMEVAL_SIMPOLL);
772+ return;
688773
689- case SIM_PIN2:
690- case SIM_PUK2:
691- case SIM_PUK2_PERM_BLOCKED:
692- case SIM_READY:
693- setRadioState(RADIO_STATE_SIM_READY);
694- return;
695- case SIM_ABSENT:
696- case SIM_PIN:
697- case SIM_PUK:
698- case SIM_NETWORK_PERSO:
699- case SIM_NETWORK_SUBSET_PERSO:
700- case SIM_SERVICE_PROVIDER_PERSO:
701- case SIM_CORPORATE_PERSO:
702- case SIM_SIM_PERSO:
703- case SIM_STERICSSON_LOCK:
704- case SIM_BLOCKED:
705- case SIM_PERM_BLOCKED:
706- case SIM_NETWORK_PERSO_PUK:
707- case SIM_NETWORK_SUBSET_PERSO_PUK:
708- case SIM_SERVICE_PROVIDER_PERSO_PUK:
709- case SIM_CORPORATE_PERSO_PUK:
710- /* pass through, do not break */
711- default:
712- setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
713- return;
774+ case SIM_PIN2:
775+ case SIM_PUK2:
776+ case SIM_PUK2_PERM_BLOCKED:
777+ case SIM_READY:
778+ setRadioState(RADIO_STATE_SIM_READY);
779+ return;
780+ case SIM_ABSENT:
781+ case SIM_PIN:
782+ case SIM_PUK:
783+ case SIM_NETWORK_PERSO:
784+ case SIM_NETWORK_SUBSET_PERSO:
785+ case SIM_SERVICE_PROVIDER_PERSO:
786+ case SIM_CORPORATE_PERSO:
787+ case SIM_SIM_PERSO:
788+ case SIM_STERICSSON_LOCK:
789+ case SIM_BLOCKED:
790+ case SIM_PERM_BLOCKED:
791+ case SIM_NETWORK_PERSO_PUK:
792+ case SIM_NETWORK_SUBSET_PERSO_PUK:
793+ case SIM_SERVICE_PROVIDER_PERSO_PUK:
794+ case SIM_CORPORATE_PERSO_PUK:
795+ /* pass through, do not break */
796+ default:
797+ setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
798+ return;
714799 }
715800 }
716801
717-
718-
719802 static void sendCallStateChanged(void *param)
720803 {
721804 RIL_onUnsolicitedResponse (
@@ -725,9 +808,8 @@ static void sendCallStateChanged(void *param)
725808
726809
727810 static int clccStateToRILState(int state, RIL_CallState *p_state)
728-
729811 {
730- switch(state) {
812+ switch (state) {
731813 case 0: *p_state = RIL_CALL_ACTIVE; return 0;
732814 case 1: *p_state = RIL_CALL_HOLDING; return 0;
733815 case 2: *p_state = RIL_CALL_DIALING; return 0;
@@ -868,16 +950,20 @@ static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
868950
869951 ALOGI("Calls=%d,Valid=%d", countCalls, countValidCalls);
870952
871- /* If some voice calls are active, enable audio tunnel */
953+ RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
954+ countValidCalls * sizeof (RIL_Call *));
955+
956+ /* Start/stop audio tunnel if a valid voice call is detected -
957+ This will restart the audiotunnel when we preventively shut it
958+ down after user hangs call (but should be restarted if in conference
959+ Stopping should be handled by the connection end notification, but,
960+ just in case, we also handle it here*/
872961 if (countValidCalls) {
873- startAudioTunnel();
962+ startAudioTunnel(NULL);
874963 } else {
875- stopAudioTunnel();
964+ stopAudioTunnel(NULL);
876965 }
877966
878- RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
879- countValidCalls * sizeof (RIL_Call *));
880-
881967 at_response_free(atResponse);
882968
883969 if (needRepoll) {
@@ -946,204 +1032,770 @@ error:
9461032
9471033
9481034 /* wait for a propertyvalue change */
949-static int wait_for_property(const char *name, const char *desired_value, int maxwait)
1035+static int wait_for_property(const char *name, const char *desired_value, int maxwait, int allowempty)
9501036 {
9511037 char value[PROPERTY_VALUE_MAX] = {'\0'};
952- int maxnaps = maxwait / 1;
1038+ int maxnaps = maxwait;
9531039
9541040 if (maxnaps < 1) {
9551041 maxnaps = 1;
9561042 }
9571043
9581044 while (maxnaps-- > 0) {
959- usleep(1000000);
9601045 if (property_get(name, value, NULL)) {
961- if (desired_value == NULL ||
962- strcmp(value, desired_value) == 0) {
963- return 0;
1046+ if (allowempty || (!allowempty && value[0]!=0)) {
1047+ if (desired_value == NULL ||
1048+ strcmp(value, desired_value) == 0) {
1049+ return 0;
1050+ }
9641051 }
9651052 }
1053+ sleep(1);
9661054 }
9671055 return -1; /* failure */
9681056 }
9691057
970-static int killConn(const char * cid)
1058+/* Write an string to the modem */
1059+static int dial_at_modem(const char* cmd, int skipanswerwait)
9711060 {
972- int err;
973- int fd;
974- int i=0;
1061+ int i, n, ret;
1062+ int fd = -1;
1063+ char buf[64+1];
1064+
1065+ ALOGD("dial_at_modem: opening modem %s", ppp_iface_dev);
1066+ do {
1067+ fd = open( ppp_iface_dev, O_RDWR | O_NOCTTY | O_NDELAY); /* nonblocking */
1068+ } while (fd < 0 && errno == EINTR);
1069+
1070+ if (fd < 0) {
1071+ ALOGE("could not open modem %s: %s", ppp_iface_dev, strerror(errno) );
1072+ return -1;
1073+ }
1074+
1075+ // disable echo on serial lines and set a 10 second timeout
1076+ if ( isatty( fd ) ) {
1077+ struct termios ios;
1078+ tcgetattr( fd, &ios );
1079+ ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
1080+ ios.c_oflag &= (~ONLCR); /* Stop \n -> \r\n translation on output */
1081+ ios.c_iflag &= (~(ICRNL | INLCR)); /* Stop \r -> \n & \n -> \r translation on input */
1082+ ios.c_iflag |= (IGNCR | IXOFF); /* Ignore \r & XON/XOFF on input */
1083+ ios.c_cc[VTIME] = 10; /* Timeout in 1/10 of a second */
1084+ ios.c_cc[VMIN] = 0; /* Minimum number of chars returned: 0*/
1085+ tcsetattr( fd, TCSANOW, &ios );
1086+ }
1087+
1088+ // Discard all pending data */
1089+ tcflush(fd, TCIOFLUSH);
1090+
1091+ // If hangup sequence, wait a bit...
1092+ if (!strcmp(cmd,"+++")) {
1093+ sleep(1);
1094+ }
1095+
1096+ // Write command to modem
1097+ ALOGD("dial_at_modem: writing command: %s", cmd);
1098+ i = strlen(cmd);
1099+ n = 0;
1100+ do {
1101+ ret = write(fd, cmd + n, i - n);
1102+ if (ret < 0 && errno == EINTR)
1103+ continue;
1104+ if (ret < 0) {
1105+ ALOGE("Error writing to modem: %s", strerror(errno) );
1106+ close(fd);
1107+ return -1;
1108+ }
1109+ n += ret;
1110+ } while (n < i);
9751111
976- D("killConn");
1112+ // Force all the data to be transmitted
1113+ tcdrain(fd);
1114+
1115+ // If hangup sequence, wait a bit... and we are done. Modem won't answer it
1116+ if (!strcmp(cmd,"+++")) {
1117+ sleep(1);
1118+
1119+ // Leave line ready */
1120+ write(fd, "\r\n", 2);
1121+ tcdrain(fd);
9771122
978-#if 0
979- while ((fd = open("/sys/class/net/ppp0/ifindex",O_RDONLY)) > 0)
980- {
981- if(i%5 == 0)
982- system("killall pppd");
983- if(i>25)
984- goto error;
985- i++;
9861123 close(fd);
987- sleep(2);
988- }
989-#elif 0
990- // Requires root access...
991- property_set("ctl.stop", "pppd_gprs");
992- if (wait_for_property("init.svc.pppd_gprs", "stopped", 10) < 0) {
993- goto error;
1124+ return 0;
9941125 }
995-#endif
9961126
997- D("killall pppd finished");
1127+ // If we must skip waiting for an answer
1128+ if (skipanswerwait) {
1129+ close(fd);
1130+ return 0;
1131+ }
9981132
999- err = at_send_command("AT+CGACT=0,%s", cid);
1000- if (err != AT_NOERROR)
1001- goto error;
1133+ // Read answer with timeout
1134+ ALOGD("dial_at_modem: waiting for response");
1135+ do {
10021136
1003- at_send_command("ATH");
1004- return 0;
1137+ /* Receive a line with timeout */
1138+ int waitc = 5;
1139+ n = 0;
1140+ do {
1141+ ret = read(fd, &buf[n], 1);
1142+ if (ret < 0 && (errno == EINTR || errno == EAGAIN))
1143+ continue;
10051144
1006-error:
1007- return -1;
1008-}
1145+ if (ret < 0) {
1146+ ALOGE("dial_at_modem: Error reading from serial port: %d",errno);
1147+ close(fd);
1148+ return -1;
1149+ }
10091150
1151+ if (ret == 0) {
1152+ waitc --;
1153+ if (waitc <= 0) {
1154+ ALOGE("dial_at_modem: No answer from modem");
1155+ close(fd);
1156+ return -1;
1157+ }
10101158
1011-//static char userPassStatic[512] = "preload";
1159+ // not timed out yet, sleep a second
1160+ sleep(1);
1161+ } else {
1162+ /* Something received, restart timeout */
1163+ waitc = 5;
1164+ }
10121165
1013-static void requestSetupDefaultPDP(void *data, size_t datalen, RIL_Token t)
1014-{
1015- const char *apn;
1016- const char *user = NULL;
1017- const char *pass = NULL;
1018- char pppdcmd[512] = "/system/bin/pppd ";
1019- int err;
1020- int fd, pppstatus,i;
1021- FILE *pppconfig;
1022- size_t cur = 0;
1023- ssize_t written, rlen;
1024- char status[32] = {0};
1025- char *buffer;
1026- long buffSize, len;
1027- int retry = 10;
1028-
1029- int n = 1;
1030- RIL_Data_Call_Response_v6 responses;
1031- char ppp_dnses[(PROPERTY_VALUE_MAX * 2) + 3] = {'\0'};
1032- char ppp_local_ip[PROPERTY_VALUE_MAX] = {'\0'};
1033- char ppp_dns1[PROPERTY_VALUE_MAX] = {'\0'};
1034- char ppp_dns2[PROPERTY_VALUE_MAX] = {'\0'};
1035- char ppp_gw[PROPERTY_VALUE_MAX] = {'\0'};
1166+ // Count of read chars
1167+ n += ret;
1168+ } while (n < 64 && buf[n-1] != '\n');
10361169
1037- apn = ((const char **)data)[2];
1038- user = ((char **)data)[3];
1039- if (user == NULL || strlen(user) < 2) {
1040- user = "dummy";
1041- }
1170+ /*buf[n] = 0; ALOGD("dial_at_modem: read %d bytes ['%s']",n,&buf[0]);*/
10421171
1043- pass = ((char **)data)[4];
1044- if (pass == NULL || strlen(pass) < 2) {
1045- pass = "dummy";
1046- }
1172+ // Remove the trailing spaces
1173+ while (n > 0 && buf[n-1] <= ' ' && buf[n-1] != 0)
1174+ n--;
1175+ buf[n] = 0;
10471176
1048- D("requesting data connection to APN '%s'", apn);
1177+ // Remove the leading spaces
1178+ n = 0;
1179+ while (buf[n]<= ' ' && buf[n] != 0)
1180+ n++;
10491181
1050- // Make sure there is no existing connection or pppd instance running
1051- if (killConn("1") < 0) {
1052- ALOGE("killConn Error!");
1053- goto error;
1054- }
1182+ } while (buf[0] == 0); // Ignore blank lines
10551183
1056- /* Switch radio ON */
1057- err = at_send_command("AT^RFSWITCH=1");
1058- err = at_send_command("AT+CFUN=1");
1184+ close(fd);
10591185
1060- /* Define the PDP context */
1061- err = at_send_command("AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
1186+ ALOGD("dial_at_modem: got answer : '%s'",&buf[n]);
1187+ if (strstr(&buf[n],"OK")) return 0;
1188+ if (strstr(&buf[n],"CONNECT")) return 0;
10621189
1063- /* Set required QoS params to default */
1064- err = at_send_command("AT+CGQREQ=1");
1190+ return -1;
1191+}
10651192
1066- /* Set minimum QoS params to default */
1067- err = at_send_command("AT+CGQMIN=1");
1193+static int killConn(const char* cididx)
1194+{
1195+ /* Leave NDIS mode */
1196+ if (!pppSupported())
1197+ at_send_command("AT^NDISDUP=%s,0",cididx);
10681198
1069- /* packet-domain event reporting */
1070- err = at_send_command("AT+CGEREP=1,0");
1199+ /* Leave Data context mode */
1200+ at_send_command("AT+CGACT=0,%s", cididx);
10711201
1072- /* Hangup anything that's happening there now */
1073- err = at_send_command("AT+CGACT=0,1");
1202+ /* Hang up */
1203+ at_send_command("ATH");
10741204
1075- /* Start data on PDP context 1 */
1076- err = at_send_command("ATD*99***1#");
1077-// if (err != AT_NOERROR) {
1078-// goto error;
1079-// }
1080- sleep(2); //Wait for the modem to finish
1205+ /* Kill pppd daemon (just in case)*/
1206+ system("killall pppd");
10811207
1082- // set up the pap/chap secrets file
1083-// sprintf(userpass, "%s * %s", user, pass);
1208+ /* Hang up modem, if needed */
1209+ //dial_at_modem("+++",1);
1210+ dial_at_modem("ATH\r\n",1);
10841211
1085- /* start the gprs pppd */
1086-#if 1
1087- property_get("rild.ppp.tty", pppdcmd + strlen(pppdcmd), "/dev/ttyUSB0");
1088- strcat(pppdcmd, " call gprs");
1089- system(pppdcmd);
1090-#else
1091- // Requires root access...
1092- property_set("ctl.start", "ppp");
1093- if (wait_for_property("init.svc.ppp", "running", 10) < 0) {
1094- ALOGE("Timeout waiting init.svc.ppp - giving up!");
1095- goto error;
1212+ /* Bring down all interfaces */
1213+ if (ifc_init() == 0) {
1214+ ifc_down(RNDIS_IFACE);
1215+ ifc_down(PPP_IFACE);
1216+ ifc_close();
10961217 }
1097-#endif
10981218
1099- sleep(10); // Allow time for ip-up to complete
1219+ return 0;
1220+}
11001221
1101- if (wait_for_property("net.ppp0.local-ip", NULL, 10) < 0) {
1102- ALOGE("Timeout waiting net.ppp0.local-ip - giving up!");
1103- goto error;
1104- }
1222+#define LOG_FILE_DIR "/dev/log/"
11051223
1106- property_get("net.ppp0.local-ip", ppp_local_ip, NULL);
1107- property_get("net.dns1", ppp_dns1, NULL);
1108- property_get("net.dns2", ppp_dns2, NULL);
1109- property_get("net.ppp0.gw", ppp_gw, NULL);
1110- sprintf(ppp_dnses, "%s %s", ppp_dns1, ppp_dns2);
1224+struct lc_entry {
1225+ union {
1226+ unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
1227+ struct logger_entry entry __attribute__((aligned(4)));
1228+ };
1229+};
11111230
1112- ALOGI("Got net.ppp0.local-ip: %s", ppp_local_ip);
1231+/* Get the connection data used by pppd from the android logcat */
1232+int get_pppd_info(struct timeval* from, char* local_ip, char* dns1, char* dns2, char* gw)
1233+{
1234+ struct lc_entry* lce;
11131235
1114- responses.status = 0;
1115- responses.suggestedRetryTime = -1;
1116- responses.cid = 1;
1117- responses.active = 2;
1118- responses.type = (char*)"PPP";
1119- responses.ifname = (char*)PPP_TTY_PATH;
1120- responses.addresses = ppp_local_ip;
1121- responses.dnses = ppp_dnses;
1122- responses.gateways = ppp_gw;
1236+ const char mainlog[] = LOG_FILE_DIR "main";
1237+ const char pppd_str[] = "pppd";
1238+ const char local_ip_str[] = "local IP address ";
1239+ const char remote_ip_str[] = "remote IP address ";
1240+ const char primary_dns_str[] = "primary DNS address ";
1241+ const char secondary_dns_str[] = "secondary DNS address ";
11231242
1124- RIL_onRequestComplete(t, RIL_E_SUCCESS, &responses, sizeof(RIL_Data_Call_Response_v6));
1125- return;
1243+ int fd;
1244+ int result;
1245+ fd_set readset;
1246+ int search_tmout = 500; //
11261247
1127-error:
1128- ALOGE("Unable to setup PDP");
1129- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1248+ local_ip[0] = 0;
1249+ dns1[0] = 0;
1250+ dns2[0] = 0;
1251+ gw[0] = 0;
11301252
1131-}
1253+ lce = malloc(sizeof(struct lc_entry));
1254+ if (!lce) {
1255+ ALOGE("Failed to allocate logcat entry buffer");
1256+ return -1;
1257+ }
11321258
1133-/* CHECK There are several error cases if PDP deactivation fails
1134- * 24.008: 8, 25, 36, 38, 39, 112
1135- */
1136-static void requestDeactivateDefaultPDP(void *data, size_t datalen, RIL_Token t)
1137-{
1138- char * cid;
1259+ fd = open(mainlog, O_RDONLY);
1260+ if (fd < 0) {
1261+ ALOGE("Unable to open log device '%s': %s", mainlog, strerror(errno));
1262+ free(lce);
1263+ return -1;
1264+ }
11391265
1140- D("requestDeactivateDefaultPDP()");
1266+ /*ALOGD("filter: sec:%d, usec:%d", from->tv_sec, from->tv_usec);*/
11411267
1142- cid = ((char **)data)[0];
1143- if (killConn(cid) < 0)
1144- goto error;
1268+ while (1) {
11451269
1146- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1270+ do {
1271+ struct timeval timeout = { 0, 10000 /* 10ms */ };
1272+ FD_ZERO(&readset);
1273+ FD_SET(fd, &readset);
1274+ result = select(fd + 1, &readset, NULL, NULL, &timeout);
1275+ } while (result < 0 && errno == EINTR);
1276+
1277+ // Wait until we find something...
1278+ if (result == 0) {
1279+ if (search_tmout > 0) {
1280+ search_tmout --;
1281+ continue;
1282+ } else
1283+ break;
1284+ }
1285+
1286+ if (result > 0 && FD_ISSET(fd, &readset)) {
1287+
1288+ /* NOTE: driver guarantees we read exactly one full entry */
1289+ int ret = read(fd, lce, LOGGER_ENTRY_MAX_LEN);
1290+ if (ret < 0) {
1291+ if (errno == EINTR) {
1292+ continue;
1293+ }
1294+ if (errno == EAGAIN) {
1295+ continue;
1296+ }
1297+ ALOGE("logcat read");
1298+ continue;
1299+ }
1300+ else if (!ret) {
1301+ ALOGE("read: Unexpected EOF!");
1302+ continue;
1303+ }
1304+ else if (lce->entry.len != ret - sizeof(struct logger_entry)) {
1305+ ALOGE("read: unexpected length. Expected %d, got %d",
1306+ lce->entry.len, ret - sizeof(struct logger_entry));
1307+ continue;
1308+ }
1309+
1310+ lce->entry.msg[lce->entry.len] = '\0';
1311+
1312+ /*
1313+ * format: <priority:1><tag:N>\0<message:N>\0
1314+ *
1315+ * tag str
1316+ * starts at buf->msg+1
1317+ * msg
1318+ * starts at buf->msg+1+len(tag)+1
1319+ *
1320+ * The message may have been truncated by the kernel log driver.
1321+ * When that happens, we must null-terminate the message ourselves.
1322+ */
1323+
1324+ /*ALOGD("entry: tag:%d[%c], sec:%d, usec:%d, n:%s, m:%s", lce->entry.msg[0], lce->entry.msg[0], lce->entry.sec, lce->entry.nsec/1000, &lce->entry.msg[1],(&lce->entry.msg[1])+strlen(&lce->entry.msg[1])+1); */
1325+
1326+ // We are interested in pppd entries with I priority newer than specified
1327+ if ((lce->entry.msg[0] == 'i' || lce->entry.msg[0] == 'I' || lce->entry.msg[0] == 4) &&
1328+ (lce->entry.sec > from->tv_sec ||
1329+ (lce->entry.sec == from->tv_sec && (lce->entry.nsec/1000) >= from->tv_usec)) &&
1330+ !strcmp(&lce->entry.msg[1],pppd_str)) {
1331+ char * pos = NULL;
1332+
1333+ // Dealing with PPPD entries in logcat - Get a pointer to the message
1334+ char * msg = (&lce->entry.msg[1]) + strlen(&lce->entry.msg[1]) + 1;
1335+
1336+ // Strip leading spaces
1337+ while (*msg != 0 && *msg <= ' ') msg++;
1338+
1339+ // And also strip trailing spaces...
1340+ pos = msg + strlen(msg);
1341+ while (pos != msg && pos[-1] <= ' ') pos--;
1342+ *pos = 0;
1343+
1344+ // An entry we are interested in ?
1345+ if ((pos = strstr(msg,local_ip_str)) != NULL) {
1346+ strcpy(local_ip,msg + sizeof(local_ip_str) - 1);
1347+ strcpy(gw,msg + sizeof(local_ip_str) - 1);
1348+ } else
1349+ if ((pos = strstr(msg,remote_ip_str)) != NULL) {
1350+ // We found the remote_ip address ... Give no more than 3 seconds for the next entry to appear
1351+ // (those entries are not mandatory)
1352+ search_tmout = 300;
1353+ } else
1354+ if ((pos = strstr(msg,primary_dns_str)) != NULL) {
1355+ strcpy(dns1,msg + sizeof(primary_dns_str) - 1);
1356+ } else
1357+ if ((pos = strstr(msg,secondary_dns_str)) != NULL) {
1358+ strcpy(dns2,msg + sizeof(secondary_dns_str) - 1);
1359+ }
1360+ }
1361+
1362+ // If we have all required data, break now!
1363+ if (local_ip[0] && gw[0] && dns1[0] && dns2[0]) {
1364+ break;
1365+ }
1366+ }
1367+ }
1368+
1369+ close(fd);
1370+ free(lce);
1371+
1372+ // Return if we succeeded or not
1373+ return local_ip[0] ? 0 : -1;
1374+}
1375+
1376+
1377+/* Setup connection using PPP */
1378+static int setupPPP(RIL_Token t,const char* ctxid,const char* user,const char* pass)
1379+{
1380+ int err;
1381+ char* cmd = NULL;
1382+ const char* fmt;
1383+ in_addr_t addr;
1384+ in_addr_t mask;
1385+ unsigned flags = 0;
1386+ int ctr = 10;
1387+ struct timeval from_tm;
1388+
1389+ RIL_Data_Call_Response_v6 responses;
1390+ char ppp_ifname[PROPERTY_VALUE_MAX] = {'\0'};
1391+ char ppp_local_ip[PROPERTY_VALUE_MAX] = {'\0'};
1392+ char ppp_dns1[PROPERTY_VALUE_MAX] = {'\0'};
1393+ char ppp_dns2[PROPERTY_VALUE_MAX] = {'\0'};
1394+ char ppp_dnses[(PROPERTY_VALUE_MAX * 2) + 3] = {'\0'};
1395+ char ppp_gw[PROPERTY_VALUE_MAX] = {'\0'};
1396+ char pbuf[32] = {'\0'};
1397+
1398+
1399+ ALOGD("Trying to setup PPP connnection...");
1400+
1401+#if 1
1402+ /* PDP context activation */
1403+ //err = at_send_command("AT+CGACT=0,%s",ctxid);
1404+ err = at_send_command("ATD*99***%s#", ctxid);
1405+#else
1406+ /* Try just with data context activation */
1407+ asprintf(&cmd,"AT+CGDATA=\"PPP\",%s\r\n",ctxid);
1408+ err = dial_at_modem(cmd,0);
1409+ free(cmd);
1410+ if (err) {
1411+ /* If failed, retry with dial command */
1412+ asprintf(&cmd,"ATD*99***%s#\r\n",ctxid);
1413+ err = dial_at_modem(cmd,0);
1414+ free(cmd);
1415+ if (err) {
1416+ ALOGE("Failed to dial");
1417+ return -1;
1418+ }
1419+ }
1420+#endif
1421+
1422+ /* Wait for the modem to finish */
1423+ sleep(2);
1424+
1425+ /* original options
1426+ "nodetach debug noauth defaultroute usepeerdns "
1427+ "connect-delay 1000 "
1428+ "user NotUsed@nobody.com password NotUsed "
1429+ "crtscts lcp-echo-failure 0 lcp-echo-interval 0 ipcp-max-configure 30 "
1430+ "ipcp-max-failure 30 ipcp-max-terminate 10 novj linkname ril";
1431+ */
1432+
1433+#if 0
1434+ /* start the gprs pppd - pppd must be suid root */
1435+ if (user == NULL || user[0] == 0 ||
1436+ pass == NULL || pass[0] == 0 ) {
1437+
1438+ fmt = "/system/bin/pppd %s "
1439+ "115200 "
1440+ "crtscts modem "
1441+ "linkname ril%s "
1442+ "noauth "
1443+ "user %s password %s "
1444+ "defaultroute usepeerdns noipdefault "
1445+ "novj novjccomp nobsdcomp "
1446+ "ipcp-accept-remote ipcp-accept-local "
1447+ "dump debug "
1448+ "lcp-echo-failure 0 lcp-echo-interval 0 ipcp-max-configure 30 "
1449+ "ipcp-max-failure 30 ipcp-max-terminate 10";
1450+
1451+ } else {
1452+
1453+ fmt = "/system/bin/pppd %s "
1454+ "115200 "
1455+ "crtscts modem "
1456+ "linkname ril%s "
1457+ "user %s password %s "
1458+ "defaultroute usepeerdns noipdefault "
1459+ "novj novjccomp nobsdcomp "
1460+ "ipcp-accept-remote ipcp-accept-local "
1461+ "dump debug "
1462+ "lcp-echo-failure 0 lcp-echo-interval 0 ipcp-max-configure 30 "
1463+ "ipcp-max-failure 30 ipcp-max-terminate 10";
1464+ }
1465+
1466+ asprintf(&cmd,fmt,ppp_iface_dev,ctxid, ((user && user[0])? user: "guest"), ((pass && pass[0])? pass: "guest") );
1467+#else
1468+ fmt = "/system/bin/pppd %s call gprs";
1469+ asprintf(&cmd, fmt, ppp_iface_dev);
1470+#endif
1471+
1472+ ALOGD("Starting pppd w/command line: '%s'", cmd);
1473+
1474+ // Get current time
1475+ gettimeofday(&from_tm,NULL);
1476+
1477+ // Start PPPD
1478+ system(cmd);
1479+ free(cmd);
1480+
1481+#if 0
1482+ /* Try not to depend on ip-up/down scripts ... */
1483+
1484+ // Wait until network interface is up and running
1485+ if (ifc_init() < 0) {
1486+ ALOGE("Failed initialization of net ifc");
1487+ return -1;
1488+ }
1489+
1490+ ALOGD("Waiting until net ifc %s is up", PPP_IFACE);
1491+ ctr = 20;
1492+ do {
1493+ sleep(1); // wait one second...
1494+ flags = 0;
1495+ ifc_get_info(PPP_IFACE, &addr, &mask, &flags);
1496+ } while (--ctr > 0 && !(flags & IFF_UP));
1497+ ifc_close();
1498+
1499+ if (ctr <= 0) {
1500+ ALOGE("Net ifc %s was never upped!", PPP_IFACE);
1501+ return -1;
1502+ }
1503+
1504+ /* Get PPP information by reading and parsing the PPPD log */
1505+ if (get_pppd_info(&from_tm, ppp_local_ip, ppp_dns1, ppp_dns2, ppp_gw) < 0) {
1506+ ALOGE("Unable to get dns/gw");
1507+ return -1;
1508+ }
1509+
1510+ strcpy(ppp_ifname,PPP_IFACE);
1511+
1512+#elif 0
1513+ // Wait until ppp ip-up script has completely executed...
1514+ sprintf(pbuf,"net.ril%s.if",ctxid);
1515+ if (wait_for_property(pbuf, NULL, 20, 0) < 0) {
1516+ ALOGE("Timeout waiting %s - giving up!", pbuf);
1517+ return -1;
1518+ }
1519+ property_get(pbuf, ppp_ifname, NULL);
1520+
1521+ // Get local IP
1522+ sprintf(pbuf,"net.ril%s.local-ip",ctxid);
1523+ property_get(pbuf, ppp_local_ip, NULL);
1524+
1525+ sprintf(pbuf,"net.ril%s.dns1",ctxid);
1526+ property_get(pbuf, ppp_dns1, NULL);
1527+
1528+ sprintf(pbuf,"net.ril%s.dns2",ctxid);
1529+ property_get(pbuf, ppp_dns2, NULL);
1530+
1531+ sprintf(pbuf,"net.ril%s.gw",ctxid);
1532+ property_get(pbuf, ppp_gw, NULL);
1533+
1534+#else
1535+ strcpy(ppp_ifname,PPP_IFACE);
1536+ strcpy(pbuf, "net." PPP_IFACE ".local-ip");
1537+ if (wait_for_property(pbuf, NULL, 20, 0) < 0) {
1538+ ALOGE("Timeout waiting %s - giving up!", pbuf);
1539+ return -1;
1540+ }
1541+ property_get("net.ppp0.local-ip", ppp_local_ip, NULL);
1542+ property_get("net.ppp0.gw", ppp_gw, NULL);
1543+ property_get("net.dns1", ppp_dns1, NULL);
1544+ property_get("net.dns2", ppp_dns2, NULL);
1545+
1546+#endif
1547+
1548+ sprintf(ppp_dnses, "%s %s", ppp_dns1, ppp_dns2);
1549+
1550+ ALOGI("Got ifname: %s, local-ip: %s, dns1: %s, dns2: %s, gw: %s",
1551+ ppp_ifname, ppp_local_ip, ppp_dns1, ppp_dns2, ppp_gw);
1552+
1553+ responses.status = 0;
1554+ responses.suggestedRetryTime = -1;
1555+ responses.cid = (ctxid[0] - '0');
1556+ responses.active = 2;
1557+ responses.type = (char*)"PPP";
1558+ responses.ifname = ppp_ifname;
1559+ responses.addresses = ppp_local_ip;
1560+ responses.dnses = ppp_dnses;
1561+ responses.gateways = ppp_gw;
1562+
1563+ using_rndis = 0;
1564+
1565+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &responses, sizeof(RIL_Data_Call_Response_v6));
1566+ return 0;
1567+}
1568+
1569+/* Converts a hex encoded addr to an std addr */
1570+static void str2addr(char* addr,const char* str)
1571+{
1572+ unsigned int val = (unsigned int) strtoul(str, NULL, 16);
1573+ sprintf(addr,"%u.%u.%u.%u",
1574+ (val & 0x000000ffU),
1575+ (val & 0x0000ff00U) >> 8U,
1576+ (val & 0x00ff0000U) >> 16U,
1577+ (val & 0xff000000U) >> 24U);
1578+}
1579+
1580+/* Setup connection using NDIS */
1581+static int setupNDIS(RIL_Token t,const char* ctxid)
1582+{
1583+ ATResponse *atResponse = NULL;
1584+ RIL_Data_Call_Response_v6 responses;
1585+ char rndis_dnses[64 + 3] = {'\0'};
1586+ char rndis_local_ip[32] = {'\0'};
1587+ char rndis_dns1[32] = {'\0'};
1588+ char rndis_dns2[32] = {'\0'};
1589+ char rndis_gw[32] = {'\0'};
1590+
1591+ in_addr_t in_addr;
1592+ in_addr_t in_gateway;
1593+
1594+ int err;
1595+ char *line;
1596+ char *ip = NULL;
1597+ char *netmask = NULL;
1598+ char *gateway = NULL;
1599+ char *unk = NULL;
1600+ char *dns1 = NULL;
1601+ char *dns2 = NULL;
1602+
1603+ ALOGD("Trying to setup NDIS connnection...");
1604+
1605+ /* Enter data state using context #1 as NDIS */
1606+ err = at_send_command("AT^NDISDUP=%s,1",ctxid);
1607+ if (err != AT_NOERROR)
1608+ return -1;
1609+
1610+ /* Leave 10 seconds for startup */
1611+ sleep(10);
1612+
1613+ /* Check DHCP status */
1614+ err = at_send_command_singleline("AT^DHCP?", "^DHCP:", &atResponse);
1615+ if (err != AT_NOERROR)
1616+ goto error;
1617+
1618+ line = atResponse->p_intermediates->line;
1619+ err = at_tok_start(&line);
1620+ if (err < 0) goto error;
1621+
1622+ err = at_tok_nextstr(&line, &ip);
1623+ if (err < 0) goto error;
1624+
1625+ err = at_tok_nextstr(&line, &netmask);
1626+ if (err < 0) goto error;
1627+
1628+ err = at_tok_nextstr(&line, &gateway);
1629+ if (err < 0) goto error;
1630+
1631+ err = at_tok_nextstr(&line, &unk);
1632+ if (err < 0) goto error;
1633+
1634+ err = at_tok_nextstr(&line, &dns1);
1635+ if (err < 0) goto error;
1636+
1637+ err = at_tok_nextstr(&line, &dns2);
1638+ if (err < 0) goto error;
1639+
1640+ ALOGD("IP: %s, netmask: %s, gateway: %s, dns1:%s, dns2:%s",ip,netmask,gateway,dns1,dns2);
1641+
1642+ str2addr(rndis_local_ip, ip);
1643+ if (inet_pton(AF_INET, rndis_local_ip, &in_addr) <= 0) {
1644+ ALOGE("%s() inet_pton() failed for %s!", __func__, rndis_local_ip);
1645+ goto error;
1646+ }
1647+
1648+ str2addr(rndis_dns1, dns1);
1649+ str2addr(rndis_dns2, dns2);
1650+ sprintf(rndis_dnses, "%s %s", rndis_dns1, rndis_dns2);
1651+
1652+ str2addr(rndis_gw, gateway);
1653+ if (inet_pton(AF_INET, rndis_gw, &in_gateway) <= 0) {
1654+ ALOGE("%s() inet_pton() failed for %s!", __func__, rndis_gw);
1655+ goto error;
1656+ }
1657+
1658+ at_response_free(atResponse);
1659+
1660+ responses.status = 0;
1661+ responses.suggestedRetryTime = -1;
1662+ responses.cid = 1;
1663+ responses.active = 2;
1664+ responses.type = (char*)"RNDIS";
1665+ responses.ifname = (char*)RNDIS_IFACE;
1666+ responses.addresses = rndis_local_ip;
1667+ responses.dnses = rndis_dnses;
1668+ responses.gateways = rndis_gw;
1669+
1670+ /* Don't use android netutils. We use our own and get the routing correct.
1671+ * Carl Nordbeck */
1672+ if (ifc_configure(RNDIS_IFACE, in_addr, in_gateway))
1673+ ALOGE("%s() Failed to configure the interface %s", __func__, RNDIS_IFACE);
1674+
1675+ using_rndis = 1;
1676+
1677+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &responses, sizeof(RIL_Data_Call_Response_v6));
1678+ return 0;
1679+
1680+error:
1681+ ALOGE("Failed to start NDIS mode");
1682+
1683+ at_response_free(atResponse);
1684+ return -1;
1685+}
1686+
1687+/* Query if modem supports PPP. Otherwise, RNDIS will be used */
1688+static int pppSupported(void)
1689+{
1690+ ATResponse *atResponse = NULL;
1691+
1692+ int err;
1693+ int supp_mode = 0; // PPP
1694+ char *line;
1695+
1696+ ALOGD("Identifying modem capabilities...");
1697+
1698+ /* Check Modem capabilities */
1699+ err = at_send_command_singleline("AT^DIALMODE?", "^DIALMODE:", &atResponse);
1700+ if (err != AT_NOERROR)
1701+ goto error;
1702+
1703+ line = atResponse->p_intermediates->line;
1704+ err = at_tok_start(&line);
1705+ if (err < 0) goto error;
1706+
1707+ err = at_tok_nextint(&line, &supp_mode);
1708+ if (err < 0) goto error;
1709+
1710+ ALOGD("Modem mode: %d [0=ppp,1=ndis,2=ppp&ndis]",supp_mode);
1711+
1712+ at_response_free(atResponse);
1713+
1714+ return supp_mode != 1; // ppp supported
1715+
1716+error:
1717+ ALOGD("Assuming PPP mode");
1718+ at_response_free(atResponse);
1719+ return 1;
1720+}
1721+
1722+static void requestSetupDefaultPDP(void *data, size_t datalen, RIL_Token t)
1723+{
1724+ const char *apn;
1725+ const char *user = NULL;
1726+ const char *pass = NULL;
1727+ int err;
1728+ const char* ctxid = "1";
1729+ int use_ppp;
1730+
1731+ apn = ((const char **)data)[2];
1732+ user = ((char **)data)[3];
1733+ if (user == NULL || strlen(user) < 2) {
1734+ user = "dummy";
1735+ }
1736+
1737+ pass = ((char **)data)[4];
1738+ if (pass == NULL || strlen(pass) < 2) {
1739+ pass = "dummy";
1740+ }
1741+
1742+ /* Check if PPP is supported */
1743+ use_ppp = pppSupported();
1744+
1745+ D("requesting data connection to APN '%s' use_ppp=%d", apn, use_ppp);
1746+
1747+ // Make sure there is no existing connection
1748+ killConn(ctxid);
1749+
1750+
1751+ /* packet-domain event reporting */
1752+ err = at_send_command("AT+CGEREP=1,0");
1753+
1754+ /* Define the PDP context #1*/
1755+ err = at_send_command("AT+CGDCONT=%s,\"IP\",\"%s\"",ctxid, apn);
1756+
1757+ /* Set required QoS params to default */
1758+ err = at_send_command("AT+CGQREQ=%s",ctxid);
1759+
1760+ /* Set minimum QoS params to default */
1761+ err = at_send_command("AT+CGQMIN=%s",ctxid);
1762+
1763+ /* Attach to GPRS network */
1764+ err = at_send_command("AT+CGATT=1");
1765+
1766+ if (use_ppp) {
1767+ if (setupPPP(t,ctxid,user,pass) < 0) {
1768+ goto error;
1769+ }
1770+ } else {
1771+ if (setupNDIS(t,ctxid) < 0) {
1772+ goto error;
1773+ }
1774+ }
1775+
1776+ ALOGD("Data connection established!");
1777+ return;
1778+
1779+error:
1780+ ALOGE("Unable to setup PDP");
1781+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1782+
1783+}
1784+
1785+/* CHECK There are several error cases if PDP deactivation fails
1786+ * 24.008: 8, 25, 36, 38, 39, 112
1787+ */
1788+static void requestDeactivateDefaultPDP(void *data, size_t datalen, RIL_Token t)
1789+{
1790+ char * cid;
1791+
1792+ D("requestDeactivateDefaultPDP()");
1793+
1794+ cid = ((char **)data)[0];
1795+ if (killConn(cid) < 0)
1796+ goto error;
1797+
1798+ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
11471799 return;
11481800
11491801 error:
@@ -1204,7 +1856,7 @@ static void requestOrSendPDPContextList(RIL_Token *t)
12041856 responses[i].cid = -1;
12051857 responses[i].active = -1;
12061858 responses[i].type = (char*)"";
1207- responses[i].ifname = (char*)PPP_TTY_PATH;
1859+ responses[i].ifname = using_rndis ? (char*)RNDIS_IFACE : (char*)PPP_IFACE;
12081860 responses[i].addresses = (char*)"";
12091861 responses[i].dnses = (char*)"";
12101862 responses[i].gateways = (char*)"";
@@ -1277,7 +1929,7 @@ static void requestOrSendPDPContextList(RIL_Token *t)
12771929 if (err < 0)
12781930 goto error;
12791931
1280- responses[i].ifname = (char*)PPP_TTY_PATH;
1932+ responses[i].ifname = using_rndis ? (char*)RNDIS_IFACE : (char*)PPP_IFACE;
12811933
12821934 err = at_tok_nextstr(&line, &out);
12831935 if (err < 0)
@@ -1291,6 +1943,27 @@ static void requestOrSendPDPContextList(RIL_Token *t)
12911943 at_response_free(atResponse);
12921944 atResponse = NULL;
12931945
1946+ /* Make sure interface is UP and running. If not, invalidate datacall to
1947+ force Android to reconnect - This will happen when resuming from suspend, as pppd
1948+ has probably ended as a consequence of the USB bus being suspended and the terminal
1949+ disappearing. So, that is why we have this check here. Not only the modem has to
1950+ report an active connection, also linux has to export an active net interface !*/
1951+ if (ifc_init() >= 0) {
1952+ in_addr_t addr;
1953+ in_addr_t mask;
1954+ unsigned flags = 0;
1955+ ifc_get_info( responses[i].ifname, &addr, &mask, &flags);
1956+ if (!(flags & IFF_UP)) {
1957+ for (i = 0; i < n; i++) {
1958+ if (responses[i].active) {
1959+ ALOGD("DataCall cid:%d forced to inactive, as associated interface [%s] is DOWN", responses[i].cid, responses[i].ifname );
1960+ responses[i].active = 0;
1961+ }
1962+ }
1963+ }
1964+ ifc_close();
1965+ }
1966+
12941967 if (t != NULL)
12951968 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
12961969 n * sizeof(RIL_Data_Call_Response_v6));
@@ -1440,13 +2113,12 @@ static struct held_pdu *dequeue_held_pdu(void)
14402113
14412114 static void enqueue_held_pdu(char type, const char *sms_pdu)
14422115 {
1443- struct held_pdu *hpdu = (struct held_pdu *) malloc(sizeof(*hpdu));
2116+ struct held_pdu *hpdu = (struct held_pdu *) calloc(1, sizeof(*hpdu));
14442117 if (hpdu == NULL) {
14452118 ALOGE("%s() failed to allocate memory!", __func__);
14462119 return;
14472120 }
14482121
1449- memset(hpdu, 0, sizeof(*hpdu));
14502122 hpdu->type = type;
14512123 hpdu->sms_pdu = strdup(sms_pdu);
14522124 if (NULL == hpdu->sms_pdu) {
@@ -1454,9 +2126,9 @@ static void enqueue_held_pdu(char type, const char *sms_pdu)
14542126 return;
14552127 }
14562128
1457- if (s_held_pdus == NULL)
2129+ if (s_held_pdus == NULL) {
14582130 s_held_pdus = hpdu;
1459- else {
2131+ } else {
14602132 struct held_pdu *p = s_held_pdus;
14612133 while (p->next != NULL)
14622134 p = p->next;
@@ -1514,12 +2186,12 @@ exit:
15142186 * SIM SMS storage area is full, cannot receive
15152187 * more messages until memory freed
15162188 */
1517-void onNewSmsIndication(void)
2189+static void onNewSmsIndication(void)
15182190 {
15192191 enqueueRILEvent(isSimSmsStorageFull, NULL, NULL);
15202192 }
15212193
1522-void onNewSms(const char *sms_pdu)
2194+static void onNewSms(const char *sms_pdu)
15232195 {
15242196 pthread_mutex_lock(&s_held_pdus_mutex);
15252197
@@ -1533,13 +2205,13 @@ void onNewSms(const char *sms_pdu)
15332205 } else {
15342206 s_outstanding_acknowledge = 1;
15352207 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS,
1536- sms_pdu, strlen(sms_pdu));
2208+ sms_pdu, strlen(sms_pdu));
15372209 }
15382210
15392211 pthread_mutex_unlock(&s_held_pdus_mutex);
15402212 }
15412213
1542-void onNewStatusReport(const char *sms_pdu)
2214+static void onNewStatusReport(const char *sms_pdu)
15432215 {
15442216 char *response = NULL;
15452217 int err;
@@ -1563,13 +2235,13 @@ void onNewStatusReport(const char *sms_pdu)
15632235 } else {
15642236 s_outstanding_acknowledge = 1;
15652237 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
1566- response, strlen(response));
2238+ response, strlen(response));
15672239 }
15682240 free(response);
15692241 pthread_mutex_unlock(&s_held_pdus_mutex);
15702242 }
15712243
1572-void onNewBroadcastSms(const char *pdu)
2244+static void onNewBroadcastSms(const char *pdu)
15732245 {
15742246 char *message = NULL;
15752247 D("%s() Length : %d", __func__, strlen(pdu));
@@ -1602,7 +2274,7 @@ void onNewBroadcastSms(const char *pdu)
16022274 } else {
16032275 s_outstanding_acknowledge = 1;
16042276 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
1605- message, BSM_LENGTH);
2277+ message, BSM_LENGTH);
16062278 }
16072279
16082280 pthread_mutex_unlock(&s_held_pdus_mutex);
@@ -1611,7 +2283,7 @@ error:
16112283 return;
16122284 }
16132285
1614-void onNewSmsOnSIM(const char *s)
2286+static void onNewSmsOnSIM(const char *s)
16152287 {
16162288 char *line;
16172289 char *mem;
@@ -1636,8 +2308,14 @@ void onNewSmsOnSIM(const char *s)
16362308 if (err < 0)
16372309 goto error;
16382310
2311+ /* Huawei modems use a 0-based message slot index, but the SIM record is 1-based.
2312+ We will translate Huawei indices to Record indices, to make the Android RIL
2313+ able to read SMS stored in SIM using SimIo with the same indices as the Sms
2314+ delete command and NewSmsOnSim index */
2315+ index += 1;
2316+
16392317 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM,
1640- &index, sizeof(int *));
2318+ &index, sizeof(int *));
16412319
16422320 finally:
16432321 free(line);
@@ -1715,9 +2393,9 @@ static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
17152393 smsc[4+length] = '\0';
17162394 }
17172395 at_response_free(atResponse);
2396+ } else {
2397+ strcpy(smsc, testSmsc);
17182398 }
1719- else
1720- strcpy(smsc,testSmsc);
17212399
17222400 asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
17232401 asprintf(&cmd2, "%s%s", smsc, pdu);
@@ -1754,15 +2432,15 @@ finally:
17542432
17552433 error:
17562434 switch (at_get_cms_error(aterr)) {
1757- case CMS_NO_NETWORK_SERVICE:
1758- case CMS_NETWORK_TIMEOUT:
1759- ret = RIL_E_SMS_SEND_FAIL_RETRY;
1760- break;
1761- default:
1762- ret = RIL_E_GENERIC_FAILURE;
1763- break;
1764- }
1765- RIL_onRequestComplete(t, ret, NULL, 0);
2435+ case CMS_NO_NETWORK_SERVICE:
2436+ case CMS_NETWORK_TIMEOUT:
2437+ ret = RIL_E_SMS_SEND_FAIL_RETRY;
2438+ break;
2439+ default:
2440+ ret = RIL_E_GENERIC_FAILURE;
2441+ break;
2442+ }
2443+ RIL_onRequestComplete(t, ret, NULL, 0);
17662444 goto finally;
17672445 }
17682446
@@ -1845,7 +2523,18 @@ static void requestDeleteSmsOnSim(void *data, size_t datalen, RIL_Token t)
18452523 {
18462524 int err;
18472525
1848- err = at_send_command("AT+CMGD=%d", ((int *) data)[0]);
2526+ /* Huawei modems use a 0-based message slot index, but the SIM record is 1-based.
2527+ We will translate Huawei indices to Record indices, to make the Android RIL
2528+ able to read SMS stored in SIM using SimIo with the same indices as the Sms
2529+ delete command and NewSmsOnSim index */
2530+ int idx = ((int *) data)[0] - 1;
2531+ if (idx < 0) {
2532+ ALOGE("DeleteSmsOnSim: Invalid index! (%d)",idx);
2533+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2534+ return;
2535+ }
2536+
2537+ err = at_send_command("AT+CMGD=%d", idx);
18492538 if (err != AT_NOERROR)
18502539 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
18512540 else
@@ -1921,20 +2610,20 @@ static void requestSmsStorageFull(void *data, size_t datalen, RIL_Token t)
19212610 * 1. memory was full and been cleaned up, inform modem memory is available now.
19222611 */
19232612 switch (ack) {
1924- case 0:
1925- /* Android will handle this, no need to inform modem. always return success. */
1926- ALOGI("SMS storage full");
1927- break;
1928-
1929- case 1:
1930- /* Since we are not using +CNMA command. It's fine to return without informing network */
1931- ALOGI("Failed to inform network for Message Cleanup. Need cmd : ESMSMEMAVAIL");
1932- break;
1933-
1934- default:
1935- ALOGE("%s() Invalid parameter", __func__);
1936- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1937- return;
2613+ case 0:
2614+ /* Android will handle this, no need to inform modem. always return success. */
2615+ ALOGI("SMS storage full");
2616+ break;
2617+
2618+ case 1:
2619+ /* Since we are not using +CNMA command. It's fine to return without informing network */
2620+ ALOGI("Failed to inform network for Message Cleanup. Need cmd : ESMSMEMAVAIL");
2621+ break;
2622+
2623+ default:
2624+ ALOGE("%s() Invalid parameter", __func__);
2625+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2626+ return;
19382627 }
19392628
19402629 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
@@ -1982,7 +2671,7 @@ static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
19822671 unsolResponse = RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT;
19832672
19842673 RIL_onUnsolicitedResponse(unsolResponse, hpdu->sms_pdu,
1985- strlen(hpdu->sms_pdu));
2674+ strlen(hpdu->sms_pdu));
19862675
19872676 free(hpdu->sms_pdu);
19882677 free(hpdu);
@@ -2262,234 +2951,246 @@ error:
22622951 * This is similar to the TS 27.007 "restricted SIM" operation
22632952 * where it assumes all of the EF selection will be done by the
22642953 * callee.
2954+ *
2955+ * Reverse Engineered from Kuawei generic RIL *
22652956 */
22662957
2267-
2268-/* All files listed under ADF_USIM in 3GPP TS 31.102 */
2269-static const int ef_usim_files[] = {
2270- 0x6F05, 0x6F06, 0x6F07, 0x6F08, 0x6F09,
2271- 0x6F2C, 0x6F31, 0x6F32, 0x6F37, 0x6F38,
2272- 0x6F39, 0x6F3B, 0x6F3C, 0x6F3E, 0x6F3F,
2273- 0x6F40, 0x6F41, 0x6F42, 0x6F43, 0x6F45,
2274- 0x6F46, 0x6F47, 0x6F48, 0x6F49, 0x6F4B,
2275- 0x6F4C, 0x6F4D, 0x6F4E, 0x6F4F, 0x6F50,
2276- 0x6F55, 0x6F56, 0x6F57, 0x6F58, 0x6F5B,
2277- 0x6F5C, 0x6F60, 0x6F61, 0x6F62, 0x6F73,
2278- 0x6F78, 0x6F7B, 0x6F7E, 0x6F80, 0x6F81,
2279- 0x6F82, 0x6F83, 0x6FAD, 0x6FB1, 0x6FB2,
2280- 0x6FB3, 0x6FB4, 0x6FB5, 0x6FB6, 0x6FB7,
2281- 0x6FC3, 0x6FC4, 0x6FC5, 0x6FC6, 0x6FC7,
2282- 0x6FC8, 0x6FC9, 0x6FCA, 0x6FCB, 0x6FCC,
2283- 0x6FCD, 0x6FCE, 0x6FCF, 0x6FD0, 0x6FD1,
2284- 0x6FD2, 0x6FD3, 0x6FD4, 0x6FD5, 0x6FD6,
2285- 0x6FD7, 0x6FD8, 0x6FD9, 0x6FDA, 0x6FDB,
2958+typedef struct _tagSW1SW2{
2959+ unsigned char mask[2];
2960+ unsigned char sw[2];
2961+ char *text;
2962+} SW1SW2;
2963+
2964+static const SW1SW2 sim_answ[]=
2965+{
2966+ /* Response to commands which are correctly executed */
2967+ { { 0xff, 0xff }, { 0x90, 0x00 } , "Ok" },
2968+ { { 0xff, 0x00 }, { 0x9f, 0x00 } , "%d response bytes available" },
2969+ /* Memory management */
2970+ { { 0xff, 0x00 }, { 0x92, 0x00 } , "Update successful but after using an internal retry of %d times" },
2971+ { { 0xff, 0xff }, { 0x92, 0x40 } , "memory problem" },
2972+ /* Referencing management */
2973+ { { 0xff, 0xff }, { 0x94, 0x00 } , "no EF selected" },
2974+ { { 0xff, 0xff }, { 0x94, 0x02 } , "out of range (invalid address)" },
2975+ { { 0xff, 0xff }, { 0x94, 0x04 } , "file ID or pattern not found" },
2976+ { { 0xff, 0xff }, { 0x94, 0x08 } , "file is inconsistent with the command" },
2977+ /* Security management */
2978+ { { 0xff, 0xff }, { 0x98, 0x02 } , "no CHV initialised" },
2979+ { { 0xff, 0xff }, { 0x98, 0x04 } , "access condition not fulfilled,authentication failed at least one attempt left" },
2980+ { { 0xff, 0xff }, { 0x98, 0x08 } , "in contradiction with CHV status" },
2981+ { { 0xff, 0xff }, { 0x98, 0x10 } , "in contradiction with invalidation stats" },
2982+ { { 0xff, 0xff }, { 0x98, 0x40 } , "unsuccessful CHV verification,no attempt left. CHV blocked" },
2983+ { { 0xff, 0xff }, { 0x98, 0x50 } , "increase cannot be performed,Max value reached" },
2984+
2985+ { { 0xff, 0x00 }, { 0x61, 0x00 } , "%d response bytes available" },
2986+
2987+ { { 0xff, 0xff }, { 0x62, 0x81 } , "returned data may be corrupt" },
2988+ { { 0xff, 0xff }, { 0x62, 0x82 } , "EOF reached prematurely" },
2989+ { { 0xff, 0xff }, { 0x62, 0x83 } , "selected file invalid" },
2990+ { { 0xff, 0xff }, { 0x62, 0x84 } , "FCI not formated" },
2991+ { { 0xff, 0x00 }, { 0x62, 0x00 } , "nvmem unchanged" },
2992+
2993+ { { 0xff, 0x00 }, { 0x63, 0x00 } , "nvmem changed" },
2994+ { { 0xff, 0x00 }, { 0x63, 0x81 } , "file filled up by last write" },
2995+ { { 0xff, 0xf0 }, { 0x63, 0xc0 } , "Counter=%1.1X" },
2996+
2997+ { { 0xff, 0xff }, { 0x64, 0x00 } , "nvmem unchanged" },
2998+ { { 0xff, 0x00 }, { 0x64, 0x00 } , "nvmem unchanged - RFU" },
2999+
3000+ { { 0xff, 0xff }, { 0x65, 0x00 } , "nvmem changed" },
3001+ { { 0xff, 0xff }, { 0x65, 0x81 } , "nvmem changed - memory failure" },
3002+ { { 0xff, 0x00 }, { 0x65, 0x00 } , "nvmem changed - unknown?" },
3003+
3004+ { { 0xff, 0x00 }, { 0x66, 0x00 } , "security related %d" },
3005+
3006+ { { 0xff, 0xff }, { 0x67, 0x00 } , "wrong length" },
3007+ { { 0xff, 0x00 }, { 0x67, 0x00 } , "wrong length - %d expected" },
3008+
3009+ { { 0xff, 0xff }, { 0x68, 0x81 } , "wrong cla - logical channel not supported" },
3010+ { { 0xff, 0xff }, { 0x68, 0x82 } , "wrong cla - secure messaging not supported" },
3011+ { { 0xff, 0x00 }, { 0x68, 0x00 } , "cla not supported" },
3012+
3013+ { { 0xff, 0xff }, { 0x69, 0x81 } , "command incompatible with file structure" },
3014+ { { 0xff, 0xff }, { 0x69, 0x82 } , "security status not satisfied" },
3015+ { { 0xff, 0xff }, { 0x69, 0x83 } , "authentication method blocked" },
3016+ { { 0xff, 0xff }, { 0x69, 0x84 } , "referenced data invalid" },
3017+ { { 0xff, 0xff }, { 0x69, 0x85 } , "conditions of use not satisfied" },
3018+ { { 0xff, 0xff }, { 0x69, 0x86 } , "command not allowed - no current EF" },
3019+ { { 0xff, 0xff }, { 0x69, 0x87 } , "expected SM data objects missing" },
3020+ { { 0xff, 0xff }, { 0x69, 0x88 } , "SM data objects incorrect" },
3021+ { { 0xff, 0x00 }, { 0x69, 0x00 } , "command not allowed" },
3022+
3023+ { { 0xff, 0xff }, { 0x6a, 0x80 } , "P1-P2: incorrect parameters in data field" },
3024+ { { 0xff, 0xff }, { 0x6a, 0x81 } , "P1-P2: function not supported" },
3025+ { { 0xff, 0xff }, { 0x6a, 0x82 } , "P1-P2: file not found" },
3026+ { { 0xff, 0xff }, { 0x6a, 0x83 } , "P1-P2: record not found" },
3027+ { { 0xff, 0xff }, { 0x6a, 0x84 } , "P1-P2: not enough memory space in file" },
3028+ { { 0xff, 0xff }, { 0x6a, 0x85 } , "P1-P2: Lc inconsistent with TLV" },
3029+ { { 0xff, 0xff }, { 0x6a, 0x86 } , "P1-P2 incorrect" },
3030+ { { 0xff, 0xff }, { 0x6a, 0x87 } , "P1-P2 inconsistent with Lc" },
3031+ { { 0xff, 0xff }, { 0x6a, 0x88 } , "Referenced data not found" },
3032+ { { 0xff, 0x00 }, { 0x6a, 0x00 } , "P1-P2 invalid" },
3033+
3034+ { { 0xff, 0x00 }, { 0x6b, 0x00 } , "P1-P2 invalid" },
3035+
3036+ { { 0xff, 0x00 }, { 0x6c, 0x00 } , "wrong length - %d expected" },
3037+
3038+ { { 0xff, 0x00 }, { 0x6d, 0x00 } , "INS code not supported or invalid" },
3039+
3040+ { { 0xff, 0x00 }, { 0x6e, 0x00 } , "CLA %02X not supported" },
3041+
3042+ { { 0xff, 0x00 }, { 0x6f, 0x00 } , "no precise diagnosis" },
3043+
3044+ { { 0x00, 0x00 }, { 0x00, 0x00 } , "Unknown response" }
22863045 };
22873046
2288-static const int ef_telecom_files[] = {
2289- 0x6F3A, 0x6F3D, 0x6F44, 0x6F4A, 0x6F54,
2290-};
3047+/* Interpret and print SIM_IO command result */
3048+static void print_simansw(unsigned char sw1, unsigned char sw2)
3049+{
3050+ unsigned j;
3051+
3052+ ALOGD("sw1: 0x%02x, sw2: 0x%02x", sw1, sw2);
3053+ for (j = 0; j < sizeof(sim_answ)/sizeof(sim_answ[0]); j++) {
3054+ if ((sw1 & sim_answ[j].mask[0]) == sim_answ[j].sw[0] &&
3055+ (sw2 & sim_answ[j].mask[1]) == sim_answ[j].sw[1]) {
3056+ ALOGD(sim_answ[j].text, sw2);
3057+ return;
3058+ }
3059+ }
3060+
3061+ ALOGD("Unknown error");
3062+}
22913063
2292-#define PATH_ADF_USIM_DIRECTORY "3F007FFF"
2293-#define PATH_ADF_TELECOM_DIRECTORY "3F007F10"
3064+static unsigned int hex2int(char dig)
3065+{
3066+ if (dig >= '0' && dig <= '9')
3067+ return dig - '0';
3068+ if (dig >= 'a' && dig <= 'f')
3069+ return dig - 'a' + 10;
3070+ if (dig >= 'A' && dig <= 'F')
3071+ return dig - 'A' + 10;
3072+ return 0;
3073+}
22943074
2295-/* RID: A000000087 = 3GPP, PIX: 1002 = 3GPP USIM */
2296-#define USIM_APPLICATION_ID "A0000000871002"
3075+static void hexStringToBytes(unsigned char* b, const char* str)
3076+{
3077+ int len = strlen(str);
3078+ len >>= 1;
3079+ while (len--) {
3080+ *b++ = (hex2int(str[0]) << 4) | hex2int(str[1]);
3081+ str += 2;
3082+ };
3083+}
22973084
2298-static int sendSimIOCmdICC(const RIL_SIM_IO_v6 *ioargs, ATResponse **atResponse, RIL_SIM_IO_Response *sr)
3085+static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
22993086 {
3087+ ATResponse *atResponse = NULL;
3088+ RIL_SIM_IO_Response sr;
23003089 int err;
2301- char *fmt;
2302- char *arg6;
2303- char *arg7;
3090+ RIL_SIM_IO_v6 *p_args;
23043091 char *line;
3092+ char *fmt;
3093+
3094+ /* FIXME handle pin2 */
3095+ memset(&sr, 0, sizeof(sr));
23053096
2306- /* FIXME Handle pin2. */
2307- memset(sr, 0, sizeof(*sr));
3097+ p_args = (RIL_SIM_IO_v6 *)data;
23083098
2309- arg6 = ioargs->data;
2310- arg7 = ioargs->path;
3099+ if (!p_args)
3100+ goto error;
3101+
3102+ if (p_args->path != NULL && (strlen(p_args->path) & 3) != 0)
3103+ goto error;
23113104
2312- if (arg7 && arg6) {
2313- fmt = "AT+CRSM=%d,%d,%d,%d,%d,\"%s\",\"%s\"";
2314- } else if (arg7) {
2315- fmt = "AT+CRSM=%d,%d,%d,%d,%d,,\"%s\"";
2316- arg6 = arg7;
2317- } else if (arg6) {
2318- fmt = "AT+CRSM=%d,%d,%d,%d,%d,\"%s\"";
3105+ if (p_args->fileid == 0x4F30) {
3106+ if (!p_args->data) {
3107+ fmt = "AT+CRSM=%d,%d,%d,%d,%d,,\"3F007F105F3A\"";
3108+ } else {
3109+ fmt = "AT+CRSM=%d,%d,%d,%d,%d,%s,\"3F007F105F3A\"";
3110+ }
23193111 } else {
2320- fmt = "AT+CRSM=%d,%d,%d,%d,%d";
3112+ if (!p_args->data) {
3113+ fmt = "AT+CRSM=%d,%d,%d,%d,%d";
3114+ } else {
3115+ fmt = "AT+CRSM=%d,%d,%d,%d,%d,%s";
3116+ }
23213117 }
23223118
2323- err = at_send_command_singleline(fmt, "+CRSM:", atResponse,ioargs->command,
2324- ioargs->fileid, ioargs->p1,
2325- ioargs->p2, ioargs->p3,
2326- arg6, arg7);
3119+ err = at_send_command_singleline(fmt, "+CRSM:", &atResponse,
3120+ p_args->command,
3121+ p_args->fileid, p_args->p1,
3122+ p_args->p2, p_args->p3,
3123+ p_args->data);
23273124
23283125 if (err != AT_NOERROR)
2329- return err;
3126+ goto error;
23303127
2331- line = (*atResponse)->p_intermediates->line;
3128+ line = atResponse->p_intermediates->line;
23323129
23333130 err = at_tok_start(&line);
2334- if (err < 0)
2335- goto finally;
3131+ if (err < 0) goto error;
23363132
2337- err = at_tok_nextint(&line, &(sr->sw1));
2338- if (err < 0)
2339- goto finally;
3133+ err = at_tok_nextint(&line, &(sr.sw1));
3134+ if (err < 0) goto error;
23403135
2341- err = at_tok_nextint(&line, &(sr->sw2));
2342- if (err < 0)
2343- goto finally;
3136+ err = at_tok_nextint(&line, &(sr.sw2));
3137+ if (err < 0) goto error;
23443138
23453139 if (at_tok_hasmore(&line)) {
2346- err = at_tok_nextstr(&line, &(sr->simResponse));
2347- if (err < 0)
2348- goto finally;
2349- }
2350-
2351-finally:
2352- return err;
2353-}
2354-
2355-static int convertSimIoFcp(RIL_SIM_IO_Response *sr, char **cvt)
2356-{
2357- int err;
2358- /* size_t pos; */
2359- size_t fcplen;
2360- struct ts_51011_921_resp resp;
2361- void *cvt_buf = NULL;
2362-
2363- if (!sr->simResponse || !cvt) {
2364- err = -EINVAL;
2365- goto error;
2366- }
2367-
2368- fcplen = strlen(sr->simResponse);
2369- if ((fcplen == 0) || (fcplen & 1)) {
2370- err = -EINVAL;
2371- goto error;
2372- }
2373-
2374- err = fcp_to_ts_51011(sr->simResponse, fcplen, &resp);
2375- if (err < 0)
2376- goto error;
2377-
2378- cvt_buf = malloc(sizeof(resp) * 2 + 1);
2379- if (!cvt_buf) {
2380- err = -ENOMEM;
2381- goto error;
3140+ err = at_tok_nextstr(&line, &(sr.simResponse));
3141+ if (err < 0) goto error;
23823142 }
23833143
2384- err = binaryToString((unsigned char*)(&resp),
2385- sizeof(resp), cvt_buf);
2386- if (err < 0)
2387- goto error;
2388-
2389- /* cvt_buf ownership is moved to the caller */
2390- *cvt = cvt_buf;
2391- cvt_buf = NULL;
2392-
2393-finally:
2394- return err;
2395-
2396-error:
2397- free(cvt_buf);
2398- goto finally;
2399-}
3144+ /* Interpret and print results as a debugging aid */
3145+ print_simansw(sr.sw1,sr.sw2);
24003146
2401-/**
2402- * RIL_REQUEST_SIM_IO
2403- *
2404- * Request SIM I/O operation.
2405- * This is similar to the TS 27.007 "restricted SIM" operation
2406- * where it assumes all of the EF selection will be done by the
2407- * callee.
2408- */
2409-static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
2410-{
2411- (void) datalen;
2412- ATResponse *atResponse = NULL;
2413- RIL_SIM_IO_Response sr;
2414- int cvt_done = 0;
2415- int err;
2416- UICC_Type UiccType = getUICCType();
3147+ /* If dealing with a USIM card ... */
3148+ if (p_args->command == 0xC0 &&
3149+ sr.simResponse[0] == '6' &&
3150+ sr.simResponse[1] == '2' &&
3151+ sr.simResponse[6] == '0' &&
3152+ sr.simResponse[7] == '5' &&
3153+ strlen(sr.simResponse) <= 30 &&
3154+ getUICCType() != UICC_TYPE_SIM) {
24173155
2418- int pathReplaced = 0;
2419- RIL_SIM_IO_v6 ioargsDup;
3156+ /* Convert it to a format Android understands */
24203157
2421- /*
2422- * Android telephony framework does not support USIM cards properly,
2423- * send GSM filepath where as active cardtype is USIM.
2424- * Android RIL needs to change the file path of files listed under ADF-USIM
2425- * if current active cardtype is USIM
2426- */
2427- memcpy(&ioargsDup, data, sizeof(RIL_SIM_IO_v6));
2428- if (UICC_TYPE_USIM == UiccType) {
2429- unsigned int i;
2430- int err;
2431- unsigned int count = sizeof(ef_usim_files) / sizeof(int);
2432-
2433- for (i = 0; i < count; i++) {
2434- if (ef_usim_files[i] == ioargsDup.fileid) {
2435- err = asprintf(&ioargsDup.path, PATH_ADF_USIM_DIRECTORY);
2436- if (err < 0)
2437- goto error;
2438- pathReplaced = 1;
2439- ALOGD("%s() Path replaced for USIM: %d", __func__, ioargsDup.fileid);
2440- break;
2441- }
2442- }
2443- if(!pathReplaced){
2444- unsigned int count2 = sizeof(ef_telecom_files) / sizeof(int);
2445- for (i = 0; i < count2; i++) {
2446- if (ef_telecom_files[i] == ioargsDup.fileid) {
2447- err = asprintf(&ioargsDup.path, PATH_ADF_TELECOM_DIRECTORY);
2448- if (err < 0)
2449- goto error;
2450- pathReplaced = 1;
2451- ALOGD("%s() Path replaced for telecom: %d", __func__, ioargsDup.fileid);
2452- break;
2453- }
2454- }
2455- }
2456- }
3158+ unsigned char buf[15];
3159+ unsigned int val;
24573160
2458- memset(&sr, 0, sizeof(sr));
3161+ // Convert to bytes...
3162+ hexStringToBytes(buf,sr.simResponse);
24593163
2460- err = sendSimIOCmdICC(&ioargsDup, &atResponse, &sr);
3164+ // Reformat response...
3165+ sr.simResponse[0x00] = '0';
3166+ sr.simResponse[0x01] = '0';
3167+ sr.simResponse[0x02] = '0';
3168+ sr.simResponse[0x03] = '0';
24613169
2462- if (err < 0)
2463- goto error;
3170+ val = buf[8] * (buf[7] + (buf[6]<<8U));
3171+ sprintf(&sr.simResponse[0x04],"%04x",val & 0xFFFFU);
24643172
2465- /*
2466- * In case the command is GET_RESPONSE and cardtype is 3G SIM
2467- * convert to 2G FCP
2468- */
2469- if (ioargsDup.command == 0xC0 && UiccType != UICC_TYPE_SIM) {
2470- err = convertSimIoFcp(&sr, &sr.simResponse);
2471- if (err < 0)
2472- goto error;
2473- cvt_done = 1; /* sr.simResponse needs to be freed */
3173+ sr.simResponse[0x08] = sr.simResponse[0x16];
3174+ sr.simResponse[0x09] = sr.simResponse[0x17];
3175+ sr.simResponse[0x0A] = sr.simResponse[0x18];
3176+ sr.simResponse[0x0B] = sr.simResponse[0x19];
3177+ sr.simResponse[0x0D] = '4';
3178+ sr.simResponse[0x1A] = '0';
3179+ sr.simResponse[0x1B] = '1';
3180+ sr.simResponse[0x1C] = sr.simResponse[0x0E];
3181+ sr.simResponse[0x1D] = sr.simResponse[0x0F];
3182+ sr.simResponse[0x1E] = 0;
24743183 }
24753184
24763185 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
2477-
2478-finally:
24793186 at_response_free(atResponse);
2480- if (cvt_done)
2481- free(sr.simResponse);
2482-
2483- if (pathReplaced)
2484- free(ioargsDup.path);
24853187 return;
24863188
24873189 error:
24883190 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2489- goto finally;
3191+ at_response_free(atResponse);
24903192 }
24913193
2492-
24933194 /*
24943195 * The following list contains values for the structure "RIL_AppStatus" to be
24953196 * sent to Android on a given SIM state. It is indexed by the SIM_Status above.
@@ -2818,6 +3519,7 @@ static void requestQueryFacilityLock(void *data, size_t datalen, RIL_Token t)
28183519 char *facility_string = NULL;
28193520 char *facility_password = NULL;
28203521 char *facility_class = NULL;
3522+ const char *fmt;
28213523
28223524 (void) datalen;
28233525
@@ -2830,7 +3532,16 @@ static void requestQueryFacilityLock(void *data, size_t datalen, RIL_Token t)
28303532 facility_password = ((char **) data)[1];
28313533 facility_class = ((char **) data)[2];
28323534
2833- err = at_send_command_singleline("AT+CLCK=\"%s\",2,%s,%s", "+CLCK:", &atResponse,
3535+ if (facility_password != NULL && facility_password[0] != 0) {
3536+ if (facility_class != NULL && facility_class[0] != 0) {
3537+ fmt = "AT+CLCK=\"%s\",2,%s,%s";
3538+ } else {
3539+ fmt = "AT+CLCK=\"%s\",2,%s";
3540+ }
3541+ } else {
3542+ fmt = "AT+CLCK=\"%s\",2";
3543+ }
3544+ err = at_send_command_singleline(fmt, "+CLCK:", &atResponse,
28343545 facility_string, facility_password, facility_class);
28353546 if (err != AT_NOERROR)
28363547 goto error;
@@ -2896,48 +3607,48 @@ static void requestSetFacilityLock(void *data, size_t datalen, RIL_Token t)
28963607 * printing NULL with %s will give string "(null)".
28973608 */
28983609 err = at_send_command("AT+CLCK=\"%s\",%d,\"%s\",%s", facility_string,
2899- facility_mode, facility_password, facility_class);
3610+ facility_mode, facility_password ? facility_password : "", facility_class);
29003611
29013612 if (at_get_error_type(err) == AT_ERROR)
29023613 goto exit;
29033614 if (err != AT_NOERROR) {
29043615 switch (at_get_cme_error(err)) {
2905- /* CME ERROR 11: "SIM PIN required" happens when PIN is wrong */
2906- case CME_SIM_PIN_REQUIRED:
2907- ALOGI("Wrong PIN");
2908- errorril = RIL_E_PASSWORD_INCORRECT;
2909- break;
2910- /*
2911- * CME ERROR 12: "SIM PUK required" happens when wrong PIN is used
2912- * 3 times in a row
2913- */
2914- case CME_SIM_PUK_REQUIRED:
2915- ALOGI("PIN locked, change PIN with PUK");
2916- num_retries = 0;/* PUK required */
2917- errorril = RIL_E_PASSWORD_INCORRECT;
2918- break;
2919- /* CME ERROR 16: "Incorrect password" happens when PIN is wrong */
2920- case CME_INCORRECT_PASSWORD:
2921- ALOGI("Incorrect password, Facility: %s", facility_string);
2922- errorril = RIL_E_PASSWORD_INCORRECT;
2923- break;
2924- /* CME ERROR 17: "SIM PIN2 required" happens when PIN2 is wrong */
2925- case CME_SIM_PIN2_REQUIRED:
2926- ALOGI("Wrong PIN2");
2927- errorril = RIL_E_PASSWORD_INCORRECT;
2928- break;
2929- /*
2930- * CME ERROR 18: "SIM PUK2 required" happens when wrong PIN2 is used
2931- * 3 times in a row
2932- */
2933- case CME_SIM_PUK2_REQUIRED:
2934- ALOGI("PIN2 locked, change PIN2 with PUK2");
2935- num_retries = 0;/* PUK2 required */
2936- errorril = RIL_E_SIM_PUK2;
2937- break;
2938- default: /* some other error */
2939- num_retries = -1;
2940- break;
3616+ /* CME ERROR 11: "SIM PIN required" happens when PIN is wrong */
3617+ case CME_SIM_PIN_REQUIRED:
3618+ ALOGI("Wrong PIN");
3619+ errorril = RIL_E_PASSWORD_INCORRECT;
3620+ break;
3621+ /*
3622+ * CME ERROR 12: "SIM PUK required" happens when wrong PIN is used
3623+ * 3 times in a row
3624+ */
3625+ case CME_SIM_PUK_REQUIRED:
3626+ ALOGI("PIN locked, change PIN with PUK");
3627+ num_retries = 0;/* PUK required */
3628+ errorril = RIL_E_PASSWORD_INCORRECT;
3629+ break;
3630+ /* CME ERROR 16: "Incorrect password" happens when PIN is wrong */
3631+ case CME_INCORRECT_PASSWORD:
3632+ ALOGI("Incorrect password, Facility: %s", facility_string);
3633+ errorril = RIL_E_PASSWORD_INCORRECT;
3634+ break;
3635+ /* CME ERROR 17: "SIM PIN2 required" happens when PIN2 is wrong */
3636+ case CME_SIM_PIN2_REQUIRED:
3637+ ALOGI("Wrong PIN2");
3638+ errorril = RIL_E_PASSWORD_INCORRECT;
3639+ break;
3640+ /*
3641+ * CME ERROR 18: "SIM PUK2 required" happens when wrong PIN2 is used
3642+ * 3 times in a row
3643+ */
3644+ case CME_SIM_PUK2_REQUIRED:
3645+ ALOGI("PIN2 locked, change PIN2 with PUK2");
3646+ num_retries = 0;/* PUK2 required */
3647+ errorril = RIL_E_SIM_PUK2;
3648+ break;
3649+ default: /* some other error */
3650+ num_retries = -1;
3651+ break;
29413652 }
29423653 goto finally;
29433654 }
@@ -2981,7 +3692,7 @@ static void requestEnterSimPin(void *data, size_t datalen, RIL_Token t, int requ
29813692 err = at_send_command("AT+CPIN=\"%s\",\"%s\"", strings[0], strings[1]);
29823693 }
29833694 } else if (datalen == 3 * sizeof(char *)) {
2984- err = at_send_command("AT+CPIN=\"%s\",\"%s\"", strings[0], strings[1]);
3695+ err = at_send_command("AT+CPIN=\"%s\",\"%s\"", strings[0], strings[1]);
29853696 } else {
29863697 goto error;
29873698 }
@@ -2990,25 +3701,30 @@ static void requestEnterSimPin(void *data, size_t datalen, RIL_Token t, int requ
29903701
29913702 if (cme_err != CME_ERROR_NON_CME && err != AT_NOERROR) {
29923703 switch (cme_err) {
2993- case CME_SIM_PIN_REQUIRED:
2994- case CME_SIM_PUK_REQUIRED:
2995- case CME_INCORRECT_PASSWORD:
2996- case CME_SIM_PIN2_REQUIRED:
2997- case CME_SIM_PUK2_REQUIRED:
2998- num_retries = 1;
2999- RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &num_retries, sizeof(int *));
3000- break;
3001- default:
3002- goto error;
3704+ case CME_SIM_PIN_REQUIRED:
3705+ case CME_SIM_PUK_REQUIRED:
3706+ case CME_INCORRECT_PASSWORD:
3707+ case CME_SIM_PIN2_REQUIRED:
3708+ case CME_SIM_PUK2_REQUIRED:
3709+ num_retries = 1;
3710+ RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &num_retries, sizeof(int *));
3711+ break;
3712+ default:
3713+ goto error;
30033714 }
30043715 } else {
3005- /*
3006- * Got OK, return success and wait for *EPEV to trigger poll
3007- * of SIM state.
3008- */
3716+ /* Got OK, return success. */
30093717
30103718 num_retries = 1;
30113719 RIL_onRequestComplete(t, RIL_E_SUCCESS, &num_retries, sizeof(int *));
3720+
3721+ /* Make sure we get notifications for network registeration
3722+ of both voice and data now */
3723+ at_send_command("AT+CREG=2");
3724+ at_send_command("AT+CGREG=2");
3725+
3726+ /* Notify that SIM is ready */
3727+ setRadioState(RADIO_STATE_SIM_READY);
30123728 }
30133729 return;
30143730 error:
@@ -3124,15 +3840,15 @@ static void pollOperatorSelected(void *params)
31243840 Loop and try again. */
31253841 if (!at_tok_hasmore(&line)) {
31263842 switch (s_registrationDeniedReason) {
3127- case IMSI_UNKNOWN_IN_HLR: /* fall through */
3128- case ILLEGAL_ME:
3129- RIL_onRequestComplete(t, RIL_E_ILLEGAL_SIM_OR_ME, NULL, 0);
3130- free(poll_params);
3131- break;
3132- default:
3133- poll_params->loopcount++;
3134- enqueueRILEvent(pollOperatorSelected,
3135- poll_params, &TIMEVAL_OPERATOR_SELECT_POLL);
3843+ case IMSI_UNKNOWN_IN_HLR: /* fall through */
3844+ case ILLEGAL_ME:
3845+ RIL_onRequestComplete(t, RIL_E_ILLEGAL_SIM_OR_ME, NULL, 0);
3846+ free(poll_params);
3847+ break;
3848+ default:
3849+ poll_params->loopcount++;
3850+ enqueueRILEvent(pollOperatorSelected,
3851+ poll_params, &TIMEVAL_OPERATOR_SELECT_POLL);
31363852 }
31373853 } else {
31383854 /* We got operator, throw a success! */
@@ -3514,6 +4230,135 @@ error:
35144230 goto finally;
35154231 }
35164232
4233+/**
4234+ * RIL_REQUEST_SET_BAND_MODE
4235+ *
4236+ * Assign a specified band for RF configuration.
4237+ *
4238+ * "data" is int *
4239+ * ((int *)data)[0] is == 0 for "unspecified" (selected by baseband automatically)
4240+ * ((int *)data)[0] is == 1 for "EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000)
4241+ * ((int *)data)[0] is == 2 for "US band" (GSM-850 / PCS-1900 / WCDMA-850 / WCDMA-PCS-1900)
4242+ * ((int *)data)[0] is == 3 for "JPN band" (WCDMA-800 / WCDMA-IMT-2000)
4243+ * ((int *)data)[0] is == 4 for "AUS band" (GSM-900 / DCS-1800 / WCDMA-850 / WCDMA-IMT-2000)
4244+ * ((int *)data)[0] is == 5 for "AUS band 2" (GSM-900 / DCS-1800 / WCDMA-850)
4245+ *
4246+ * "response" is NULL
4247+ *
4248+ * Valid errors:
4249+ * SUCCESS
4250+ * RADIO_NOT_AVAILABLE
4251+ * GENERIC_FAILURE
4252+ */
4253+static void requestSetBandMode(void *data, size_t datalen, RIL_Token t)
4254+{
4255+ int band,err;
4256+ const char* strband;
4257+
4258+ assert (datalen >= sizeof(int *));
4259+ band = ((int *)data)[0];
4260+
4261+ switch (band) {
4262+ case 0:
4263+ default:
4264+ strband = "3FFFFFFF";
4265+ break;
4266+ case 1:
4267+ strband = "2000000400380";
4268+ break;
4269+ case 2:
4270+ strband = "4A80000";
4271+ break;
4272+ }
4273+
4274+ /* Set allowed bands */
4275+ err = at_send_command("AT^SYSCFG=16,3,%s,1,2", strband );
4276+ if (err != AT_NOERROR)
4277+ goto error;
4278+
4279+ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, sizeof(int));
4280+ return;
4281+
4282+error:
4283+ ALOGE("ERROR: requestSetBandMode() failed");
4284+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4285+
4286+}
4287+
4288+/**
4289+ * RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE
4290+ *
4291+ * Query the list of band mode supported by RF.
4292+ *
4293+ * "data" is NULL
4294+ *
4295+ * "response" is int *
4296+ * "response" points to an array of int's, the int[0] is the size of array, reset is one for
4297+ * each available band mode.
4298+ *
4299+ * 0 for "unspecified" (selected by baseband automatically)
4300+ * 1 for "EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000)
4301+ * 2 for "US band" (GSM-850 / PCS-1900 / WCDMA-850 / WCDMA-PCS-1900)
4302+ * 3 for "JPN band" (WCDMA-800 / WCDMA-IMT-2000)
4303+ * 4 for "AUS band" (GSM-900 / DCS-1800 / WCDMA-850 / WCDMA-IMT-2000)
4304+ * 5 for "AUS band 2" (GSM-900 / DCS-1800 / WCDMA-850)
4305+ *
4306+ * Valid errors:
4307+ * SUCCESS
4308+ * RADIO_NOT_AVAILABLE
4309+ * GENERIC_FAILURE
4310+ *
4311+ * See also: RIL_REQUEST_SET_BAND_MODE
4312+ */
4313+static void requestQueryAvailableBandMode(void *data, size_t datalen, RIL_Token t)
4314+{
4315+ int err = 0;
4316+ char *line;
4317+ ATResponse *atResponse = NULL;
4318+ char *strband;
4319+ int mode, acqorder, band;
4320+
4321+ err = at_send_command_singleline("AT^SYSCFG?", "^SYSCFG:", &atResponse);
4322+ if (err != AT_NOERROR)
4323+ goto error;
4324+
4325+ line = atResponse->p_intermediates->line;
4326+
4327+ err = at_tok_start(&line);
4328+ if (err < 0)
4329+ goto error;
4330+
4331+ err = at_tok_nextint(&line, &mode);
4332+ if (err < 0)
4333+ goto error;
4334+
4335+ err = at_tok_nextint(&line, &acqorder);
4336+ if (err < 0)
4337+ goto error;
4338+
4339+ err = at_tok_nextstr(&line, &strband);
4340+ if (err < 0)
4341+ goto error;
4342+
4343+ if (strcmp(strband, "2000000400380") == 0)
4344+ band = 1;
4345+ else if (strcmp(strband, "4A80000") == 0)
4346+ band = 2;
4347+ else
4348+ band = 0;
4349+
4350+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &band, sizeof(int));
4351+
4352+finally:
4353+ at_response_free(atResponse);
4354+ return;
4355+
4356+error:
4357+ ALOGE("%s() Failed to get current band mode", __func__);
4358+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4359+ goto finally;
4360+}
4361+
35174362
35184363 /**
35194364 * RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE
@@ -3529,28 +4374,19 @@ static void requestSetPreferredNetworkType(void *data, size_t datalen, RIL_Token
35294374 assert (datalen >= sizeof(int *));
35304375 rat = ((int *)data)[0];
35314376
3532- /* Huawei specific
3533- AT^SYSCFG=2,1,3FFFFFFF,2,4 for GPRS/EDGE Preferred
3534- AT^SYSCFG=2,2,3FFFFFFF,2,4 for 3G Preferred
3535- AT^SYSCFG=13,1,3FFFFFFF,2,4 for GPRS/EDGE Only
3536- AT^SYSCFG=14,2,3FFFFFFF,2,4 for 3G Only
3537-
3538- The third parameter, 0x3FFFFFFF tells the card to use all bands.
3539- A value of 0x400380 here means GSM900/1800/WCDMA2100 only and a
3540- value of 0x200000 here means GSM1900 only.
3541-
3542- */
3543-
35444377 switch (rat) {
3545- case PREF_NET_TYPE_GSM_ONLY: /* GSM only */
3546- cmd = "AT^SYSCFG=13,1,3FFFFFFF,2,4"; /* for GPRS/EDGE Only */
4378+ case PREF_NET_TYPE_GSM_ONLY: /* GSM only */
4379+ cmd = "AT^SYSCFG=13,1,40000000,2,4"; /* GSM only */
35474380 break;
3548- case PREF_NET_TYPE_GSM_WCDMA: /* WCDMA only */
3549- cmd = "AT^SYSCFG=14,2,3FFFFFFF,2,4"; /* for 3G Only */
4381+ case PREF_NET_TYPE_WCDMA: /* WCDMA only */
4382+ cmd = "AT^SYSCFG=14,2,40000000,2,4"; /* WCDMA only */
35504383 break;
3551- case PREF_NET_TYPE_GSM_WCDMA_AUTO:
4384+ case PREF_NET_TYPE_GSM_WCDMA: /* GSM/WCDMA (WCDMA preferred) */
4385+ cmd = "AT^SYSCFG=2,2,40000000,2,4"; /* Automatic, prefer WCDMA */
4386+ break;
4387+ case PREF_NET_TYPE_GSM_WCDMA_AUTO: /* GSM/WCDMA (auto mode, according to PRL) */
35524388 default: /* Dual Mode - WCDMA preferred*/
3553- cmd = "AT^SYSCFG=2,2,3FFFFFFF,2,4"; /* for 3G Preferred */
4389+ cmd = "AT^SYSCFG=2,0,40000000,2,4"; /* for 3G Preferred */
35544390 break;
35554391 }
35564392
@@ -3582,13 +4418,6 @@ error:
35824418 */
35834419 static void requestGetPreferredNetworkType(RIL_Token t)
35844420 {
3585- /*
3586- AT^SYSCFG=2,1,3FFFFFFF,1,2 for GPRS/EDGE Preferred
3587- AT^SYSCFG=2,2,3FFFFFFF,1,2 for 3G Preferred
3588- AT^SYSCFG=13,1,3FFFFFFF,1,2 for GPRS/EDGE Only
3589- AT^SYSCFG=14,2,3FFFFFFF,1,2 for 3G Only
3590- */
3591-
35924421 ATResponse *atResponse = NULL;
35934422 int err;
35944423 char *line;
@@ -3614,12 +4443,14 @@ static void requestGetPreferredNetworkType(RIL_Token t)
36144443 if (err < 0) goto error;
36154444
36164445 /* Based on reported syscfg */
3617- if (ret1 == 13) {
4446+ if (ret1 == 13 && ret2 == 1) {
36184447 response = PREF_NET_TYPE_GSM_ONLY; /* GSM only */
3619- } else if (ret1 == 14) {
3620- response = PREF_NET_TYPE_GSM_WCDMA; /* WCDMA only */
4448+ } else if (ret1 == 14 && ret2 == 2) {
4449+ response = PREF_NET_TYPE_WCDMA; /* WCDMA only */
4450+ } else if (ret1 == 2 && ret2 == 2) {
4451+ response = PREF_NET_TYPE_GSM_WCDMA; /* GSM or WCDMA */
36214452 } else {
3622- response = PREF_NET_TYPE_GSM_WCDMA_AUTO; /* for 3G Preferred */
4453+ response = PREF_NET_TYPE_GSM_WCDMA_AUTO; /* Auto */
36234454 }
36244455
36254456 D("requestGetPreferredNetworkType() mode:%d", response);
@@ -3660,25 +4491,33 @@ enum CREG_stat {
36604491 *
36614492 * Request current registration state.
36624493 */
3663-static void requestRegistrationState(RIL_Token t)
4494+static void requestRegistrationState(RIL_Token t, int data)
36644495 {
3665- int err = 0;
3666- const char resp_size = 15;
3667- int response[15];
3668- char *responseStr[15] = {0};
4496+ const int resp_size = 15;
4497+ int response[resp_size];
4498+ char *responseStr[resp_size];
36694499 ATResponse *cgreg_resp = NULL;
36704500 char *line;
36714501 int commas = 0;
36724502 int skip, cs_status = 0;
36734503 int i;
4504+ int err;
4505+ const char *cmd;
4506+ const char *prefix;
36744507
36754508 /* Setting default values in case values are not returned by AT command */
3676- for (i = 0; i < resp_size; i++)
3677- responseStr[i] = NULL;
3678-
4509+ memset(responseStr, 0, sizeof(responseStr));
36794510 memset(response, 0, sizeof(response));
36804511
3681- err = at_send_command_singleline("AT+CREG?", "+CREG:", &cgreg_resp);
4512+ if (data == 0) {
4513+ cmd = "AT+CREG?";
4514+ prefix = "+CREG:";
4515+ } else {
4516+ cmd = "AT+CGREG?";
4517+ prefix = "+CGREG:";
4518+ }
4519+
4520+ err = at_send_command_singleline(cmd, prefix, &cgreg_resp);
36824521 if (err != AT_NOERROR)
36834522 goto error;
36844523
@@ -3716,62 +4555,117 @@ static void requestRegistrationState(RIL_Token t)
37164555 goto error;
37174556
37184557 switch (commas) {
3719- case 0: /* +CREG: <stat> */
3720- err = at_tok_nextint(&line, &response[0]);
3721- if (err < 0)
3722- goto error;
4558+ case 0: /* +CREG: <stat> */
4559+ err = at_tok_nextint(&line, &response[0]);
4560+ if (err < 0)
4561+ goto error;
37234562
3724- response[1] = -1;
3725- response[2] = -1;
3726- break;
4563+ response[1] = -1;
4564+ response[2] = -1;
4565+ break;
37274566
3728- case 1: /* +CREG: <n>, <stat> */
3729- err = at_tok_nextint(&line, &skip);
3730- if (err < 0)
3731- goto error;
4567+ case 1: /* +CREG: <n>, <stat> */
4568+ err = at_tok_nextint(&line, &skip);
4569+ if (err < 0)
4570+ goto error;
37324571
3733- err = at_tok_nextint(&line, &response[0]);
3734- if (err < 0)
3735- goto error;
4572+ err = at_tok_nextint(&line, &response[0]);
4573+ if (err < 0)
4574+ goto error;
37364575
3737- response[1] = -1;
3738- response[2] = -1;
3739- if (err < 0)
3740- goto error;
3741- break;
3742- case 2: /* +CREG: <stat>, <lac>, <cid> */
3743- err = at_tok_nextint(&line, &response[0]);
3744- if (err < 0)
3745- goto error;
4576+ response[1] = -1;
4577+ response[2] = -1;
4578+ if (err < 0)
4579+ goto error;
4580+ break;
4581+ case 2: /* +CREG: <stat>, <lac>, <cid> */
4582+ err = at_tok_nextint(&line, &response[0]);
4583+ if (err < 0)
4584+ goto error;
37464585
3747- err = at_tok_nexthexint(&line, &response[1]);
3748- if (err < 0)
3749- goto error;
4586+ err = at_tok_nexthexint(&line, &response[1]);
4587+ if (err < 0)
4588+ goto error;
37504589
3751- err = at_tok_nexthexint(&line, &response[2]);
3752- if (err < 0)
3753- goto error;
3754- break;
3755- case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
3756- case 4: /* +CREG: <n>, <stat>, <lac>, <cid>, <?> */
3757- err = at_tok_nextint(&line, &skip);
3758- if (err < 0)
3759- goto error;
4590+ err = at_tok_nexthexint(&line, &response[2]);
4591+ if (err < 0)
4592+ goto error;
4593+ break;
4594+ case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
4595+ case 4: /* +CREG: <n>, <stat>, <lac>, <cid>, <?> */
4596+ err = at_tok_nextint(&line, &skip);
4597+ if (err < 0)
4598+ goto error;
37604599
3761- err = at_tok_nextint(&line, &response[0]);
3762- if (err < 0)
3763- goto error;
4600+ err = at_tok_nextint(&line, &response[0]);
4601+ if (err < 0)
4602+ goto error;
37644603
3765- err = at_tok_nexthexint(&line, &response[1]);
3766- if (err < 0)
3767- goto error;
4604+ err = at_tok_nexthexint(&line, &response[1]);
4605+ if (err < 0)
4606+ goto error;
37684607
3769- err = at_tok_nexthexint(&line, &response[2]);
3770- if (err < 0)
4608+ err = at_tok_nexthexint(&line, &response[2]);
4609+
4610+ /* Hack for broken +CGREG responses which don't return the network type */
4611+ ATResponse *p_response_op = NULL;
4612+ err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response_op);
4613+ /* We need to get the 4th return param */
4614+ int commas_op;
4615+ commas_op = 0;
4616+ char *p_op, *line_op;
4617+ line_op = p_response_op->p_intermediates->line;
4618+
4619+ for (p_op = line_op ; *p_op != '\0' ;p_op++) {
4620+ if (*p_op == ',') commas_op++;
4621+ }
4622+
4623+ if (commas_op == 3) {
4624+ err = at_tok_start(&line_op);
4625+ err = at_tok_nextint(&line_op, &skip);
4626+ if (err < 0) goto error;
4627+ err = at_tok_nextint(&line_op, &skip);
4628+ if (err < 0) goto error;
4629+ err = at_tok_nextint(&line_op, &skip);
4630+ if (err < 0) goto error;
4631+ err = at_tok_nextint(&line_op, &response[3]);
4632+ if (err < 0) goto error;
4633+ /* Now translate to 'Broken Android Speak' - can't follow the GSM spec */
4634+ switch (response[3]) {
4635+ /* GSM/GSM Compact - aka GRPS */
4636+ case 0:
4637+ case 1:
4638+ response[3] = 1;
4639+ break;
4640+
4641+ /* EGPRS - aka EDGE */
4642+ case 3:
4643+ response[3] = 2;
4644+ break;
4645+
4646+ /* UTRAN - UMTS aka 3G */
4647+ case 2:
4648+ case 7:
4649+ response[3] = 3;
4650+ break;
4651+
4652+ /* UTRAN with HSDPA and/or HSUPA aka Turbo-3G*/
4653+ case 4:
4654+ case 5:
4655+ case 6:
4656+ response[3] = 9;
4657+ break;
4658+ }
4659+ }
4660+
4661+ at_response_free(p_response_op);
4662+ /* End hack */
4663+
4664+ if (err < 0)
4665+ goto error;
4666+ break;
4667+ default:
37714668 goto error;
3772- break;
3773- default:
3774- goto error;
37754669 }
37764670
37774671
@@ -3781,10 +4675,11 @@ static void requestRegistrationState(RIL_Token t)
37814675 asprintf(&responseStr[1], "%04x", response[1]);
37824676 if (response[2] > 0)
37834677 asprintf(&responseStr[2], "%08x", response[2]);
4678+ if (response[3] > 0)
4679+ asprintf(&responseStr[3], "%d", response[3]);
37844680
3785- if (response[0] == CGREG_STAT_REG_HOME_NET ||
3786- response[0] == CGREG_STAT_ROAMING)
3787- responseStr[3] = (0);
4681+ if (data == 1)
4682+ responseStr[5] = (char*) "1";
37884683
37894684 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr,
37904685 resp_size * sizeof(char *));
@@ -3803,171 +4698,6 @@ error:
38034698 goto finally;
38044699 }
38054700
3806-
3807-/**
3808- * RIL_REQUEST_DATA_REGISTRATION_STATE
3809- *
3810- * Request current GPRS registration state.
3811- */
3812-static void requestGprsRegistrationState(RIL_Token t)
3813-{
3814- int err = 0;
3815- const char resp_size = 6;
3816- int response[resp_size];
3817- char *responseStr[resp_size];
3818- ATResponse *atResponse = NULL;
3819- char *line, *p;
3820- int commas = 0;
3821- int skip, tmp;
3822- int count = 3;
3823-
3824- memset(responseStr, 0, sizeof(responseStr));
3825- memset(response, 0, sizeof(response));
3826- response[1] = -1;
3827- response[2] = -1;
3828-
3829- err = at_send_command_singleline("AT+CGREG?", "+CGREG: ", &atResponse);
3830- if (err != AT_NOERROR)
3831- goto error;
3832-
3833- line = atResponse->p_intermediates->line;
3834- err = at_tok_start(&line);
3835- if (err < 0)
3836- goto error;
3837- /*
3838- * The solicited version of the +CGREG response is
3839- * +CGREG: n, stat, [lac, cid [,<AcT>]]
3840- * and the unsolicited version is
3841- * +CGREG: stat, [lac, cid [,<AcT>]]
3842- * The <n> parameter is basically "is unsolicited creg on?"
3843- * which it should always be.
3844- *
3845- * Now we should normally get the solicited version here,
3846- * but the unsolicited version could have snuck in
3847- * so we have to handle both.
3848- *
3849- * Also since the LAC, CID and AcT are only reported when registered,
3850- * we can have 1, 2, 3, 4 or 5 arguments here.
3851- */
3852- /* Count number of commas */
3853- p = line;
3854- err = at_tok_charcounter(line, ',', &commas);
3855- if (err < 0) {
3856- ALOGE("%s() at_tok_charcounter failed", __func__);
3857- goto error;
3858- }
3859-
3860- switch (commas) {
3861- case 0: /* +CGREG: <stat> */
3862- err = at_tok_nextint(&line, &response[0]);
3863- if (err < 0) goto error;
3864- break;
3865-
3866- case 1: /* +CGREG: <n>, <stat> */
3867- err = at_tok_nextint(&line, &skip);
3868- if (err < 0) goto error;
3869- err = at_tok_nextint(&line, &response[0]);
3870- if (err < 0) goto error;
3871- break;
3872-
3873- case 2: /* +CGREG: <stat>, <lac>, <cid> */
3874- err = at_tok_nextint(&line, &response[0]);
3875- if (err < 0) goto error;
3876- err = at_tok_nexthexint(&line, &response[1]);
3877- if (err < 0) goto error;
3878- err = at_tok_nexthexint(&line, &response[2]);
3879- if (err < 0) goto error;
3880- break;
3881-
3882- case 3: /* +CGREG: <n>, <stat>, <lac>, <cid> */
3883- /* +CGREG: <stat>, <lac>, <cid>, <AcT> */
3884- err = at_tok_nextint(&line, &tmp);
3885- if (err < 0) goto error;
3886-
3887- /* We need to check if the second parameter is <lac> */
3888- if (*(line) == '"') {
3889- response[0] = tmp; /* <stat> */
3890- err = at_tok_nexthexint(&line, &response[1]); /* <lac> */
3891- if (err < 0) goto error;
3892- err = at_tok_nexthexint(&line, &response[2]); /* <cid> */
3893- if (err < 0) goto error;
3894- err = at_tok_nextint(&line, &response[3]); /* <AcT> */
3895- if (err < 0) goto error;
3896- count = 4;
3897- } else {
3898- err = at_tok_nextint(&line, &response[0]); /* <stat> */
3899- if (err < 0) goto error;
3900- err = at_tok_nexthexint(&line, &response[1]); /* <lac> */
3901- if (err < 0) goto error;
3902- err = at_tok_nexthexint(&line, &response[2]); /* <cid> */
3903- if (err < 0) goto error;
3904- }
3905- break;
3906-
3907- case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <AcT> */
3908- err = at_tok_nextint(&line, &skip); /* <n> */
3909- if (err < 0) goto error;
3910- err = at_tok_nextint(&line, &response[0]); /* <stat> */
3911- if (err < 0) goto error;
3912- err = at_tok_nexthexint(&line, &response[1]); /* <lac> */
3913- if (err < 0) goto error;
3914- err = at_tok_nexthexint(&line, &response[2]); /* <cid> */
3915- if (err < 0) goto error;
3916- err = at_tok_nextint(&line, &response[3]); /* <AcT> */
3917- if (err < 0) goto error;
3918- count = 4;
3919- break;
3920-
3921- default:
3922- ALOGE("%s() Invalid input", __func__);
3923- goto error;
3924- }
3925-
3926- /* Converting to stringlist for Android */
3927-
3928- asprintf(&responseStr[0], "%d", response[0]); /* state */
3929-
3930- if (response[1] >= 0)
3931- asprintf(&responseStr[1], "%04x", response[1]); /* LAC */
3932- else
3933- responseStr[1] = NULL;
3934-
3935- if (response[2] >= 0)
3936- asprintf(&responseStr[2], "%08x", response[2]); /* CID */
3937- else
3938- responseStr[2] = NULL;
3939-
3940- if (response[0] == CGREG_STAT_REG_HOME_NET ||
3941- response[0] == CGREG_STAT_ROAMING)
3942- asprintf(&responseStr[3], "%d",response[3]);
3943- else
3944- responseStr[3] = NULL;
3945-
3946- responseStr[5] = (char*) "1";
3947-
3948- RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, resp_size * sizeof(char *));
3949-
3950-finally:
3951-
3952- if (responseStr[0])
3953- free(responseStr[0]);
3954- if (responseStr[1])
3955- free(responseStr[1]);
3956- if (responseStr[2])
3957- free(responseStr[2]);
3958- if (responseStr[3])
3959- free(responseStr[3]);
3960-
3961- at_response_free(atResponse);
3962- return;
3963-
3964-error:
3965- ALOGE("%s Must never return an error when radio is on", __func__);
3966- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3967- goto finally;
3968-}
3969-
3970-
39714701 /**
39724702 * RIL_REQUEST_OEM_HOOK_RAW
39734703 *
@@ -4049,17 +4779,40 @@ static void unsolicitedNitzTime(const char * s)
40494779 {
40504780 int err;
40514781 char * response = NULL;
4052- char * line = NULL;
4053- char * p = NULL;
4782+ char * dt = NULL;
4783+ char * tm = NULL;
40544784 char * tz = NULL; /* Timezone */
40554785 static char sNITZtime[64] = {0};
40564786
4057- line = strdup(s);
4787+ char * line = strdup(s);
40584788
40594789 /* Higher layers expect a NITZ string in this format:
40604790 * 08/10/28,19:08:37-20,1 (yy/mm/dd,hh:mm:ss(+/-)tz,dst)
40614791 */
4792+ if (strStartsWith(s,"^NWTIME:")) {
4793+ /* Network time, as reported by Huawei modems:
4794+ ^NWTIME: 12/09/22,08:33:59+8,01 */
4795+
4796+ /* We got the network time, now assemble the response and send to upper layers */
4797+ at_tok_start(&line);
4798+
4799+ err = at_tok_nextstr(&line, &dt);
4800+ if (err < 0) goto error;
4801+
4802+ err = at_tok_nextstr(&line, &tm);
4803+ if (err < 0) goto error;
4804+
4805+ err = at_tok_nextstr(&line, &tz);
4806+ if (err < 0) goto error;
4807+
4808+ asprintf(&response, "%s,%s,%s", dt ,tm ,tz);
4809+ RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response));
4810+ free(response);
4811+
4812+ free(line);
4813+ return;
40624814
4815+ } else
40634816 if (strStartsWith(s,"+CTZV:")){
40644817
40654818 /* Get Time and Timezone data and store in static variable.
@@ -4098,6 +4851,147 @@ static void unsolicitedNitzTime(const char * s)
40984851
40994852 error:
41004853 ALOGE("Invalid NITZ line %s", s);
4854+ free(line);
4855+}
4856+
4857+/* Unsolicited call start status */
4858+static void unsolicitedCONN(const char * s)
4859+{
4860+ int err;
4861+ int call_id;
4862+ int type;
4863+ char * line = strdup(s);
4864+
4865+ err = at_tok_start(&line);
4866+ if (err < 0) goto error;
4867+
4868+ err = at_tok_nextint(&line, &call_id);
4869+ if (err < 0) goto error;
4870+
4871+ err = at_tok_nextint(&line, &type);
4872+ if (err < 0) goto error;
4873+
4874+ ALOGD("Call started: ID:%d, type:%d", call_id, type);
4875+
4876+ /* Store last call index */
4877+ lastCallIdx = call_id;
4878+
4879+ free(line);
4880+ return;
4881+
4882+error:
4883+ ALOGI("Error getting Call Start status");
4884+ free(line);
4885+ return;
4886+}
4887+
4888+/* Unsolicited call start status */
4889+static void unsolicitedORIG(const char * s)
4890+{
4891+ int err;
4892+ int call_id;
4893+ int type;
4894+ char * line = strdup(s);
4895+
4896+ err = at_tok_start(&line);
4897+ if (err < 0) goto error;
4898+
4899+ err = at_tok_nextint(&line, &call_id);
4900+ if (err < 0) goto error;
4901+
4902+ err = at_tok_nextint(&line, &type);
4903+ if (err < 0) goto error;
4904+
4905+ ALOGD("Call originated: ID:%d, type:%d", call_id, type);
4906+
4907+ /* Store last call index */
4908+ lastCallIdx = call_id;
4909+
4910+ free(line);
4911+ return;
4912+
4913+error:
4914+ ALOGI("Error getting Call Originated status");
4915+ free(line);
4916+ return;
4917+}
4918+
4919+/* Unsolicited call conference status */
4920+static void unsolicitedCONF(const char * s)
4921+{
4922+ int err;
4923+ int call_id;
4924+ char * line = strdup(s);
4925+
4926+ err = at_tok_start(&line);
4927+ if (err < 0) goto error;
4928+
4929+ err = at_tok_nextint(&line, &call_id);
4930+ if (err < 0) goto error;
4931+
4932+ ALOGD("Call conference started: ID:%d", call_id);
4933+
4934+ /* Store last call index */
4935+ lastCallIdx = call_id;
4936+
4937+ free(line);
4938+ return;
4939+
4940+error:
4941+ ALOGI("Error getting Call Conference Start status");
4942+ free(line);
4943+ return;
4944+}
4945+
4946+/* Unsolicited call end status */
4947+static void unsolicitedCEND(const char * s)
4948+{
4949+ int err;
4950+ int call_id;
4951+ int duration;
4952+ int end_status;
4953+ int cc_cause = CALL_FAIL_NORMAL;
4954+ char * line = strdup(s);
4955+
4956+ err = at_tok_start(&line);
4957+ if (err < 0) goto error;
4958+
4959+ err = at_tok_nextint(&line, &call_id);
4960+ if (err < 0) goto error;
4961+
4962+ err = at_tok_nextint(&line, &duration);
4963+ if (err < 0) goto error;
4964+
4965+ err = at_tok_nextint(&line, &end_status);
4966+ if (err < 0) goto error;
4967+
4968+ if (at_tok_hasmore(&line)) { /* not present if error */
4969+ err = at_tok_nextint(&line, &cc_cause);
4970+ if (err < 0) goto error;
4971+ }
4972+
4973+ ALOGD("Call ended: ID:%d, duration:%ds status:%d, cccause:%d", call_id, duration, end_status, cc_cause);
4974+
4975+ /* Store last call error */
4976+ lastCallFailCause = cc_cause;
4977+
4978+ free(line);
4979+ return;
4980+
4981+error:
4982+ ALOGI("Error getting Call End status");
4983+ lastCallFailCause = CALL_FAIL_NORMAL;
4984+ free(line);
4985+ return;
4986+}
4987+
4988+
4989+static void unsolicitedDCONN(const char *s)
4990+{
4991+}
4992+
4993+static void unsolicitedDEND(const char *s)
4994+{
41014995 }
41024996
41034997 static void unsolicitedRSSI(const char * s)
@@ -4105,9 +4999,10 @@ static void unsolicitedRSSI(const char * s)
41054999 int err;
41065000 int rssi;
41075001 RIL_SignalStrength_v6 signalStrength;
4108- char * line = NULL;
41095002
4110- line = strdup(s);
5003+ char * line = strdup(s);
5004+
5005+ memset(&signalStrength, 0, sizeof(RIL_SignalStrength_v6));
41115006
41125007 err = at_tok_start(&line);
41135008 if (err < 0) goto error;
@@ -4115,22 +5010,14 @@ static void unsolicitedRSSI(const char * s)
41155010 err = at_tok_nextint(&line, &rssi);
41165011 if (err < 0) goto error;
41175012
5013+ if (rssi == 99) return;
5014+
41185015 signalStrength.GW_SignalStrength.signalStrength = rssi;
41195016 signalStrength.GW_SignalStrength.bitErrorRate = 99;
4120- signalStrength.CDMA_SignalStrength.dbm = 0;
4121- signalStrength.CDMA_SignalStrength.ecio = 0;
4122- signalStrength.EVDO_SignalStrength.dbm = 0;
4123- signalStrength.EVDO_SignalStrength.ecio = 0;
4124- signalStrength.EVDO_SignalStrength.signalNoiseRatio = 0;
4125- signalStrength.LTE_SignalStrength.signalStrength = 0;
4126- signalStrength.LTE_SignalStrength.rsrp = 0;
4127- signalStrength.LTE_SignalStrength.rsrq = 0;
4128- signalStrength.LTE_SignalStrength.rssnr = 0;
4129- signalStrength.LTE_SignalStrength.cqi = 0;
41305017
41315018 ALOGI("Signal Strength %d", rssi);
41325019
4133- RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, &signalStrength, sizeof(signalStrength));
5020+ RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, &signalStrength, sizeof(RIL_SignalStrength_v6));
41345021 free(line);
41355022 return;
41365023
@@ -4141,18 +5028,181 @@ error:
41415028 return;
41425029 }
41435030
5031+/* Get SIM status: 1=valid, all the others are invalid */
5032+static int getSimState(void)
5033+{
5034+ ATResponse *atResponse = NULL;
5035+ int err;
5036+ char *line;
5037+ int status;
5038+ int srv_status,srv_domain,roam_status,sys_mode,sim_state = -1;
5039+
5040+ // Check status.
5041+ err = at_send_command_singleline("AT^SYSINFO", "^SYSINFO:", &atResponse);
5042+ if (err != AT_NOERROR)
5043+ goto error;
5044+
5045+ line = atResponse->p_intermediates->line;
5046+ err = at_tok_start(&line);
5047+ if (err < 0) goto error;
5048+
5049+ err = at_tok_nextint(&line, &srv_status);
5050+ if (err < 0) goto error;
5051+
5052+ err = at_tok_nextint(&line, &srv_domain);
5053+ if (err < 0) goto error;
5054+
5055+ err = at_tok_nextint(&line, &roam_status);
5056+ if (err < 0) goto error;
5057+
5058+ err = at_tok_nextint(&line, &sys_mode);
5059+ if (err < 0) goto error;
5060+
5061+ err = at_tok_nextint(&line, &sim_state);
5062+ if (err < 0) goto error;
5063+
5064+
5065+ ALOGE("Sim State: %d",sim_state);
5066+ at_response_free(atResponse);
5067+ return sim_state;
5068+
5069+error:
5070+ ALOGE("Failed to get sim state");
5071+
5072+ at_response_free(atResponse);
5073+ return -1;
5074+}
5075+
5076+static int requestNetworkRegistration()
5077+{
5078+ ATResponse *atResponse = NULL;
5079+ int err;
5080+ char *line;
5081+ int srv_status,srv_domain,nr = 0;
5082+
5083+ // Check status.
5084+ err = at_send_command_singleline("AT^SYSINFO", "^SYSINFO:", &atResponse);
5085+ if (err != AT_NOERROR)
5086+ goto error;
5087+
5088+ line = atResponse->p_intermediates->line;
5089+ err = at_tok_start(&line);
5090+ if (err < 0) goto error;
5091+
5092+ err = at_tok_nextint(&line, &srv_status);
5093+ if (err < 0) goto error;
5094+
5095+ err = at_tok_nextint(&line, &srv_domain);
5096+ if (err < 0) goto error;
5097+
5098+ nr = (srv_status == 2 && (srv_domain == 2 || srv_domain == 3));
5099+
5100+ ALOGE("Network registration (PS) : %s", nr ? "Yes" : "No");
5101+ at_response_free(atResponse);
5102+ return nr;
5103+
5104+error:
5105+ ALOGE("Failed to get network registration");
5106+
5107+ at_response_free(atResponse);
5108+ return -1;
5109+}
5110+
5111+/* SIM status change */
5112+static void unsolicitedSimStatus(const char * s)
5113+{
5114+ int err;
5115+ int state;
5116+ char * line = NULL;
5117+
5118+ /*
5119+ ^SIMST:0 Invalid USIM card state
5120+ ^SIMST:1 Valid USIM card state
5121+ ^SIMST:2 Invalid USIM card in case of CS
5122+ ^SIMST:3 Invalid USIM card in case of PS
5123+ ^SIMST:4 Invalid USIM card in case of CS or PS
5124+ ^SIMST:255 Card not present
5125+ */
5126+
5127+ line = strdup(s);
5128+
5129+ err = at_tok_start(&line);
5130+ if (err < 0) goto error;
5131+
5132+ err = at_tok_nextint(&line, &state);
5133+ if (err < 0) goto error;
5134+
5135+ ALOGD("SIM state: %d",state);
5136+
5137+ free(line);
5138+ return;
5139+
5140+error:
5141+ ALOGI("Error getting state");
5142+ free(line);
5143+ return;
5144+}
5145+
5146+static void unsolicitedSrvStatus(const char * s)
5147+{
5148+ int err;
5149+ int mode;
5150+ char * line = NULL;
5151+
5152+ /*
5153+ ^SRVST:0 No service
5154+ ^SRVST:1 Restricted service
5155+ ^SRVST:2 Valid service
5156+ ^SRVST:3 Restricted Regional Service
5157+ ^SRVST:4 Power saving and deep sleep
5158+ */
5159+
5160+ line = strdup(s);
5161+
5162+ err = at_tok_start(&line);
5163+ if (err < 0) goto error;
5164+
5165+ err = at_tok_nextint(&line, &mode);
5166+ if (err < 0) goto error;
5167+
5168+ free(line);
5169+ return;
5170+
5171+error:
5172+ ALOGI("Error getting mode");
5173+ free(line);
5174+ return;
5175+}
5176+
5177+
41445178 static void unsolicitedMode(const char * s)
41455179 {
41465180 int err;
4147- int mode1;
4148- int mode2;
5181+ int android_mode;
5182+ int sys_mode;
5183+ int sys_submode;
41495184 char * line = NULL;
41505185
41515186 /*
4152- ^MODE:3,2 indicates GPRS
4153- ^MODE:3,3 indicates EDGE
4154- ^MODE:5,4 indicates 3G
4155- ^MODE:5,5 indicates HSDPA
5187+ ^MODE:<sys_mode>,<sys_submode>
5188+
5189+ <sys_mode>: System mode. The values are as follows:
5190+ 0 No service.
5191+ 1 AMPS mode (not in use currently)
5192+ 2 CDMA mode (not in use currently)
5193+ 3 GSM/GPRS mode
5194+ 4 HDR mode
5195+ 5 WCDMA mode
5196+ 6 GPS mode
5197+ <sys_submode>: System sub mode. The values are as follows:
5198+ 0 No service.
5199+ 1 GSM mode
5200+ 2 GPRS mode
5201+ 3 EDEG mode
5202+ 4 WCDMA mode
5203+ 5 HSDPA mode
5204+ 6 HSUPA mode
5205+ 7 HSDPA mode and HSUPA mode
41565206 */
41575207
41585208 line = strdup(s);
@@ -4160,13 +5210,43 @@ static void unsolicitedMode(const char * s)
41605210 err = at_tok_start(&line);
41615211 if (err < 0) goto error;
41625212
4163- err = at_tok_nextint(&line, &mode1);
5213+ err = at_tok_nextint(&line, &sys_mode);
41645214 if (err < 0) goto error;
41655215
4166- err = at_tok_nextint(&line, &mode2);
5216+ err = at_tok_nextint(&line, &sys_submode);
41675217 if (err < 0) goto error;
41685218
5219+ switch (sys_submode)
5220+ {
5221+ case 0:
5222+ android_mode = RADIO_TECH_UNKNOWN;
5223+ break;
5224+ case 1:
5225+ android_mode = RADIO_TECH_GSM;
5226+ break;
5227+ case 2:
5228+ android_mode = RADIO_TECH_GPRS;
5229+ break;
5230+ case 3:
5231+ android_mode = RADIO_TECH_EDGE;
5232+ break;
5233+ case 4:
5234+ android_mode = RADIO_TECH_UMTS;
5235+ break;
5236+ case 5:
5237+ android_mode = RADIO_TECH_HSDPA;
5238+ break;
5239+ case 6:
5240+ android_mode = RADIO_TECH_HSUPA;
5241+ break;
5242+ case 7:
5243+ android_mode = RADIO_TECH_HSPA;
5244+ break;
5245+ }
5246+
41695247 free(line);
5248+
5249+ RIL_onUnsolicitedResponse(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, &android_mode, sizeof(int *));
41705250 return;
41715251
41725252 error:
@@ -4194,12 +5274,6 @@ static void requestSignalStrength(RIL_Token t)
41945274
41955275 memset(&signalStrength, 0, sizeof(RIL_SignalStrength_v6));
41965276
4197- signalStrength.LTE_SignalStrength.signalStrength = 0x7FFFFFFF;
4198- signalStrength.LTE_SignalStrength.rsrp = 0x7FFFFFFF;
4199- signalStrength.LTE_SignalStrength.rsrq = 0x7FFFFFFF;
4200- signalStrength.LTE_SignalStrength.rssnr = 0x7FFFFFFF;
4201- signalStrength.LTE_SignalStrength.cqi = 0x7FFFFFFF;
4202-
42035277 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &atResponse);
42045278 if (err != AT_NOERROR)
42055279 goto error;
@@ -4209,32 +5283,18 @@ static void requestSignalStrength(RIL_Token t)
42095283 err = at_tok_start(&line);
42105284 if (err < 0) goto error;
42115285
4212- err = at_tok_nextint(&line,&rssi);
5286+ err = at_tok_nextint(&line, &rssi);
42135287 if (err < 0) goto error;
42145288
4215- signalStrength.GW_SignalStrength.signalStrength = rssi;
4216-
42175289 err = at_tok_nextint(&line, &ber);
4218- if (err < 0)
4219- goto error;
5290+ if (err < 0) goto error;
42205291
5292+ signalStrength.GW_SignalStrength.signalStrength = rssi;
42215293 signalStrength.GW_SignalStrength.bitErrorRate = ber;
42225294
4223- signalStrength.CDMA_SignalStrength.dbm = 0;
4224- signalStrength.CDMA_SignalStrength.ecio = 0;
4225- signalStrength.EVDO_SignalStrength.dbm = 0;
4226- signalStrength.EVDO_SignalStrength.ecio = 0;
4227- signalStrength.EVDO_SignalStrength.signalNoiseRatio = 0;
4228- signalStrength.LTE_SignalStrength.signalStrength = 0;
4229- signalStrength.LTE_SignalStrength.rsrp = 0;
4230- signalStrength.LTE_SignalStrength.rsrq = 0;
4231- signalStrength.LTE_SignalStrength.rssnr = 0;
4232- signalStrength.LTE_SignalStrength.cqi = 0;
4233-
42345295 ALOGI("SignalStrength %d BER: %d", rssi, ber);
42355296
4236- RIL_onRequestComplete(t, RIL_E_SUCCESS, &signalStrength,
4237- sizeof(RIL_SignalStrength_v6));
5297+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &signalStrength, sizeof(RIL_SignalStrength_v6));
42385298
42395299 at_response_free(atResponse);
42405300 atResponse = NULL;
@@ -4266,9 +5326,9 @@ static void requestOperator(RIL_Token t)
42665326
42675327 memset(response, 0, sizeof(response));
42685328
4269- err = at_send_command_multiline
4270- ("AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", "+COPS:",
4271- &atResponse);
5329+ err = at_send_command_multiline(
5330+ "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", "+COPS:",
5331+ &atResponse);
42725332
42735333 if (err != AT_NOERROR)
42745334 goto error;
@@ -4279,8 +5339,8 @@ static void requestOperator(RIL_Token t)
42795339 * +COPS: 0,2,"310170"
42805340 */
42815341 for (i = 0, cursor = atResponse->p_intermediates;
4282- cursor != NULL && i < num_resp_lines;
4283- cursor = cursor->p_next, i++) {
5342+ cursor != NULL && i < num_resp_lines;
5343+ cursor = cursor->p_next, i++) {
42845344 char *line = cursor->line;
42855345
42865346 err = at_tok_start(&line);
@@ -4367,8 +5427,7 @@ static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
43675427 if (onOff == 0 && getRadioState() != RADIO_STATE_OFF) {
43685428 char value[PROPERTY_VALUE_MAX];
43695429
4370- /* Switch RF OFF */
4371- err = at_send_command("AT^RFSWITCH=0");
5430+ err = at_send_command("AT+CFUN=0");
43725431 if (err != AT_NOERROR)
43735432 goto error;
43745433
@@ -4379,12 +5438,9 @@ static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
43795438
43805439 } else if (onOff > 0 && getRadioState() == RADIO_STATE_OFF) {
43815440
4382- /* Switch RF ON */
4383- err = at_send_command("AT^RFSWITCH=1");
4384- if (err != AT_NOERROR)
4385- goto error;
4386-
5441+ err = at_send_command("AT+CFUN=1");
43875442 if (err != AT_NOERROR) {
5443+
43885444 // Some stacks return an error when there is no SIM,
43895445 // but they really turn the RF portion on
43905446 // So, if we get an error, let's check to see if it
@@ -4401,7 +5457,7 @@ static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
44015457
44025458 restricted = RIL_RESTRICTED_STATE_NONE;
44035459 RIL_onUnsolicitedResponse(RIL_UNSOL_RESTRICTED_STATE_CHANGED,
4404- &restricted, sizeof(int *));
5460+ &restricted, sizeof(int *));
44055461
44065462 return;
44075463
@@ -4430,7 +5486,31 @@ static void requestGetIMSI(RIL_Token t)
44305486 at_response_free(atResponse);
44315487 }
44325488
5489+/**
5490+ * RIL_REQUEST_GET_IMEI
5491+ *
5492+ * Get the device IMEI, which should be 15 decimal digits.
5493+ */
5494+static void requestGetIMEI(RIL_Token t)
5495+{
5496+ ATResponse *atResponse = NULL;
5497+ int err;
44335498
5499+ /* IMEI */
5500+ err = at_send_command_numeric("AT+CGSN", &atResponse);
5501+
5502+ if (err != AT_NOERROR)
5503+ goto error;
5504+
5505+ RIL_onRequestComplete(t, RIL_E_SUCCESS, atResponse->p_intermediates->line, sizeof(char *));
5506+
5507+ at_response_free(atResponse);
5508+ return;
5509+
5510+error:
5511+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
5512+ at_response_free(atResponse);
5513+}
44345514
44355515 /**
44365516 * RIL_REQUEST_GET_IMEISV
@@ -4442,9 +5522,8 @@ static void requestGetIMEISV(RIL_Token t)
44425522 RIL_onRequestComplete(t, RIL_E_SUCCESS, (void*)"01", sizeof(char *));
44435523 }
44445524
4445-
4446-
4447-/* RIL_REQUEST_DEVICE_IDENTITY
5525+/**
5526+ * RIL_REQUEST_DEVICE_IDENTITY
44485527 *
44495528 * Request the device ESN / MEID / IMEI / IMEISV.
44505529 *
@@ -4509,6 +5588,31 @@ static void requestBasebandVersion(RIL_Token t)
45095588 at_response_free(atResponse);
45105589 }
45115590
5591+/**
5592+ * RIL_REQUEST_STK_SETUP_CALL
5593+ *
5594+ */
5595+static void requestStkSetupCall(void * data, size_t datalen, RIL_Token t)
5596+{
5597+ int onOff;
5598+ int err;
5599+
5600+ if (datalen < sizeof(int *)) {
5601+ ALOGE("%s() bad data length!", __func__);
5602+ goto error;
5603+ }
5604+
5605+ onOff = ((int *)data)[0];
5606+ err = at_send_command("AT^CSTC=%d", (onOff)?1:0 );
5607+ if (err != AT_NOERROR)
5608+ goto error;
5609+
5610+ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5611+ return;
5612+
5613+error:
5614+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
5615+}
45125616
45135617 /**
45145618 * RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE
@@ -4518,9 +5622,21 @@ static void requestBasebandVersion(RIL_Token t)
45185622 */
45195623 static void requestStkSendTerminalResponse(void * data, size_t datalen, RIL_Token t)
45205624 {
5625+ int err;
5626+ const char *ec = (const char *) data;
45215627 (void)datalen;
4522- const char *stkResponse = (const char *) data;
4523- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5628+
5629+ err = at_send_command("AT^CSTR=%d,\"%s\"",strlen(ec),ec);
5630+
5631+ if (err != AT_NOERROR)
5632+ goto error;
5633+
5634+ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL,0 );
5635+ return;
5636+
5637+error:
5638+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
5639+
45245640 }
45255641
45265642
@@ -4532,9 +5648,20 @@ static void requestStkSendTerminalResponse(void * data, size_t datalen, RIL_Toke
45325648 */
45335649 static void requestStkSendEnvelopeCommand(void * data, size_t datalen, RIL_Token t)
45345650 {
5651+ int err;
45355652 const char *ec = (const char *) data;
45365653 (void)datalen;
4537- RIL_onRequestComplete(t, RIL_E_SUCCESS, (void*)"ok", sizeof(char *));
5654+
5655+ err = at_send_command("AT^CSEN=%d,\"%s\"",strlen(ec),ec);
5656+
5657+ if (err != AT_NOERROR)
5658+ goto error;
5659+
5660+ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0 );
5661+ return;
5662+
5663+error:
5664+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
45385665 }
45395666
45405667
@@ -4551,6 +5678,11 @@ static void requestStkGetProfile(RIL_Token t)
45515678 }
45525679
45535680
5681+static void initStackUnsolv()
5682+{
5683+ at_send_command("AT^CSMN");
5684+}
5685+
45545686 /**
45555687 * RIL_REQUEST_STK_SET_PROFILE
45565688 *
@@ -4581,7 +5713,9 @@ void requestReportStkServiceIsRunning(RIL_Token t)
45815713 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
45825714 }
45835715
4584-
5716+/**
5717+ * RIL_REQUEST_DIAL
5718+ */
45855719 static void requestDial(void *data, size_t datalen, RIL_Token t)
45865720 {
45875721 RIL_Dial *p_dial;
@@ -4600,6 +5734,9 @@ static void requestDial(void *data, size_t datalen, RIL_Token t)
46005734 /* Originate call */
46015735 ret = at_send_command("ATD%s%s;", p_dial->address, clir);
46025736
5737+ /* Switch to audio from USB1 */
5738+ at_send_command("AT^DDSETEX=2");
5739+
46035740 /* success or failure is ignored by the upper layer here.
46045741 it will call GET_CURRENT_CALLS and determine success that way */
46055742 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
@@ -4614,6 +5751,11 @@ static void requestHangup(void *data, size_t datalen, RIL_Token t)
46145751
46155752 p_line = (int *)data;
46165753
5754+ /* Just in case, stop the audio tunnel now. We need to stop if before the modem
5755+ stops streaming audio. If another call is being held, it will be restarted a
5756+ little bit later by the ccurrent call list callback */
5757+ stopAudioTunnel(NULL);
5758+
46175759 // 3GPP 22.030 6.5.5
46185760 // "Releases a specific active call X"
46195761 ret = at_send_command("AT+CHLD=1%d", p_line[0]);
@@ -4625,6 +5767,11 @@ static void requestHangup(void *data, size_t datalen, RIL_Token t)
46255767
46265768 static void requestHangupWaitingOrBackground(RIL_Token t)
46275769 {
5770+ /* Just in case, stop the audio tunnel now. We need to stop if before the modem
5771+ stops streaming audio. If another call is being hold, it will be restarted a
5772+ little bit later by the ccurrent call list callback */
5773+ stopAudioTunnel(NULL);
5774+
46285775 // 3GPP 22.030 6.5.5
46295776 // "Releases all held calls or sets User Determined User Busy
46305777 // (UDUB) for a waiting call."
@@ -4638,6 +5785,11 @@ static void requestHangupWaitingOrBackground(RIL_Token t)
46385785
46395786 static void requestHangupForegroundResumeBackground(RIL_Token t)
46405787 {
5788+ /* Just in case, stop the audio tunnel now. We need to stop if before the modem
5789+ stops streaming audio. If another call is being hold, it will be restarted a
5790+ little bit later */
5791+ stopAudioTunnel(NULL);
5792+
46415793 // 3GPP 22.030 6.5.5
46425794 // "Releases all active calls (if any exist) and accepts
46435795 // the other (held or waiting) call."
@@ -4651,6 +5803,11 @@ static void requestHangupForegroundResumeBackground(RIL_Token t)
46515803
46525804 static void requestSwitchWaitingOrHoldingAndActive(RIL_Token t)
46535805 {
5806+ /* Just in case, stop the audio tunnel now. We need to stop if before the modem
5807+ stops streaming audio. If another call is being hold, it will be restarted a
5808+ little bit later */
5809+ stopAudioTunnel(NULL);
5810+
46545811 // 3GPP 22.030 6.5.5
46555812 // "Places all active calls (if any exist) on hold and accepts
46565813 // the other (held or waiting) call."
@@ -4664,8 +5821,12 @@ static void requestSwitchWaitingOrHoldingAndActive(RIL_Token t)
46645821
46655822 static void requestAnswer(RIL_Token t)
46665823 {
5824+ /* Answer call */
46675825 at_send_command("ATA");
46685826
5827+ /* Switch to audio from USB1 */
5828+ at_send_command("AT^DDSETEX=2");
5829+
46695830 /* success or failure is ignored by the upper layer here.
46705831 it will call GET_CURRENT_CALLS and determine success that way */
46715832 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
@@ -4712,24 +5873,24 @@ static void requestSeparateConnection(void * data, size_t datalen, RIL_Token t)
47125873 }
47135874 }
47145875
4715-
5876+static int wasMuted = 0;
47165877 static void requestSetMute(void *data, size_t datalen, RIL_Token t)
47175878 {
47185879 int err;
47195880 assert (datalen >= sizeof(int *));
5881+ int mute = ((int*)data)[0];
47205882
4721- /* mute */
4722- err = at_send_command("AT+CMUT=%d", ((int*)data)[0]);
4723- if (err != AT_NOERROR)
4724- goto error;
5883+ /* Store mute status */
5884+ wasMuted = mute;
47255885
4726- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4727- return;
5886+ /* mute - Don't consider it an error if it fails, as we are using a Software loopback for audio data */
5887+ err = at_send_command("AT+CMUT=%d", mute);
47285888
4729-error:
4730- ALOGE("ERROR: requestSetMute failed");
4731- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
5889+ /* Update the audio tunnel mute status */
5890+ muteAudioTunnel(wasMuted);
47325891
5892+ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5893+ return;
47335894 }
47345895
47355896
@@ -4740,8 +5901,8 @@ static void requestGetMute(RIL_Token t)
47405901 int response[1];
47415902 char *line;
47425903
5904+ /* If we fail, return a cached version of it */
47435905 err = at_send_command_singleline("AT+CMUT?", "+CMUT:", &atResponse);
4744-
47455906 if (err != AT_NOERROR)
47465907 goto error;
47475908
@@ -4759,8 +5920,10 @@ static void requestGetMute(RIL_Token t)
47595920 return;
47605921
47615922 error:
4762- ALOGE("ERROR: requestGetMute failed");
4763- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
5923+ ALOGE("ERROR: requestGetMute failed - Returned cached result");
5924+
5925+ response[0] = wasMuted;
5926+ RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char*));
47645927 at_response_free(atResponse);
47655928 }
47665929
@@ -4770,7 +5933,14 @@ static void requestDTMF(void * data, size_t datalen, RIL_Token t)
47705933 int err = 0;
47715934 char c = ((char *)data)[0];
47725935
4773- err = at_send_command("AT+VTS=%c", (int)c);
5936+ /* Start DTMF generation for 250ms */
5937+ err = at_send_command("AT^DTMF=%d,%c", lastCallIdx, (int)c); /* 1=call idx */
5938+
5939+ /* If failed, try the older method */
5940+ if (err != AT_NOERROR) {
5941+ err = at_send_command("AT+VTS=%c", (int)c);
5942+ }
5943+
47745944 if (err != AT_NOERROR) {
47755945 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
47765946 } else {
@@ -4798,7 +5968,6 @@ error:
47985968
47995969 }
48005970
4801-
48025971 static void requestDtmfStart(void *data, size_t datalen, RIL_Token t)
48035972 {
48045973 int err;
@@ -4808,8 +5977,14 @@ static void requestDtmfStart(void *data, size_t datalen, RIL_Token t)
48085977
48095978 c = ((char *)data)[0];
48105979
4811- /* Start DTMF generation fro 250ms */
4812- err = at_send_command("AT^DTMF=0,%c", (int)c);
5980+ /* Start DTMF generation for 250ms */
5981+ err = at_send_command("AT^DTMF=%d,%c", lastCallIdx, (int)c); /* 1=call idx */
5982+
5983+ /* If failed, try the older method */
5984+ if (err != AT_NOERROR) {
5985+ err = at_send_command("AT+VTS=%c", (int)c);
5986+ }
5987+
48135988 if (err != AT_NOERROR)
48145989 goto error;
48155990
@@ -4822,46 +5997,99 @@ error:
48225997
48235998 }
48245999
6000+/* decodes USSDs. Sometimes, they arrive as GSM8, sometimes they arrive as HEX encoded GSM7... */
6001+static bytes_t decodeUSSD(const char* message)
6002+{
6003+ bytes_t utf8 = NULL;
6004+
6005+ /* Could be in Hex or in GSM8 ... - Check it - Some modems return HEX
6006+ encoded GSM7, others return GSM8... */
6007+ int pos = 0;
6008+ int ishex = 1;
6009+ while (1) {
6010+ unsigned char c = message[pos];
6011+ if (!c) break;
6012+ if (!((c >= '0' && c <= '9') || ( c >= 'A' && c <= 'F' ))) {
6013+ ishex = 0;
6014+ break;
6015+ }
6016+ pos++;
6017+ };
6018+
6019+ /* Not hex encoded. Just convert to UTF-8 from GSM8 */
6020+ if (!ishex) {
6021+
6022+ /* Convert GSM8 to UTF8 */
6023+ int gsmbytes = strlen(message);
6024+ int utf8bytes = utf8_from_gsm8((cbytes_t)message,gsmbytes,NULL);
6025+ utf8 = malloc( utf8bytes + 1);
6026+ utf8_from_gsm8((cbytes_t)message,gsmbytes,utf8);
6027+ utf8[utf8bytes]= '\0';
6028+
6029+ } else {
6030+
6031+ int gsmseptets;
6032+ int utf8bytes;
6033+
6034+ /* Convert HEX to GSM7 */
6035+ int hexlen = strlen(message);
6036+ int binlen = (hexlen + 1) >> 1;
6037+ bytes_t bytes = malloc(binlen + 1);
6038+ gsm_hex_to_bytes((cbytes_t)message,hexlen,bytes);
6039+ bytes[binlen] = 0;
6040+
6041+ /* And then, GSM7 to UTF8 */
6042+ gsmseptets = (binlen * 8) / 7; // Round DOWN
6043+ utf8bytes = utf8_from_gsm7(bytes, 0, gsmseptets, NULL);
6044+ utf8 = malloc(utf8bytes + 1);
6045+ utf8_from_gsm7(bytes, 0, gsmseptets, utf8);
6046+ utf8[utf8bytes] = 0;
6047+ free(bytes);
6048+ }
6049+
6050+ return utf8;
6051+}
6052+
48256053 static void unsolicitedUSSD(const char *s)
48266054 {
48276055 char *line, *linestart;
4828- int typeCode, count, err, len;
6056+ int typeCode, count, err;
48296057 char *message;
4830- char *outputmessage;
48316058 char *responseStr[2] = {0,0};
48326059
48336060 D("unsolicitedUSSD %s", s);
48346061
4835- linestart=line=strdup(s);
6062+ linestart = line = strdup(s);
6063+
48366064 err = at_tok_start(&line);
48376065 if (err < 0) goto error;
48386066
48396067 err = at_tok_nextint(&line, &typeCode);
48406068 if (err < 0) goto error;
48416069
6070+ if (typeCode < 0 || typeCode > 5) goto error;
6071+
48426072 if (at_tok_hasmore(&line)) {
6073+
48436074 err = at_tok_nextstr(&line, &message);
48446075 if(err < 0) goto error;
48456076
4846- outputmessage = (char*) malloc(strlen(message)*2+1);
4847- gsm_hex_to_bytes((cbytes_t)message,strlen(message),(bytes_t)outputmessage);
4848-
4849- responseStr[1] = (char*) malloc(strlen(outputmessage)*2+1);
4850-
4851- len = utf8_from_gsm8((cbytes_t)outputmessage,strlen(outputmessage),(bytes_t)responseStr[1]);
4852-
4853- responseStr[1][strlen(message)/2]='\0';
4854- free(outputmessage);
6077+ /* Decode message */
6078+ responseStr[1] = (char*) decodeUSSD(message);
48556079
48566080 count = 2;
6081+
48576082 } else {
4858- responseStr[1]=NULL;
6083+
6084+ responseStr[1] = NULL;
48596085 count = 1;
48606086 }
4861- free(linestart);
6087+
48626088 asprintf(&responseStr[0], "%d", typeCode);
48636089
4864- RIL_onUnsolicitedResponse (RIL_UNSOL_ON_USSD, responseStr, count*sizeof(char*));
6090+ RIL_onUnsolicitedResponse(RIL_UNSOL_ON_USSD, responseStr, count*sizeof(char*));
6091+
6092+ free(linestart);
48656093 if (responseStr[0])
48666094 free(responseStr[0]);
48676095 if (responseStr[1])
@@ -5103,23 +6331,84 @@ static void requestSetCLIR(void *data, size_t datalen, RIL_Token t)
51036331 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
51046332 {
51056333 int err = 0;
5106- int len;
5107- cbytes_t ussdRequest;
5108- bytes_t temp;
5109- char *newUSSDRequest;
5110- ussdRequest = (cbytes_t)(data);
5111-
5112- temp = (bytes_t) malloc(strlen((char *)ussdRequest)*sizeof(char)+1);
5113- len = utf8_to_gsm8(ussdRequest,strlen((char *)ussdRequest),temp);
5114- newUSSDRequest = (char*) malloc(2*len*sizeof(char)+1);
5115- gsm_hex_from_bytes(newUSSDRequest,temp, len);
5116- newUSSDRequest[2*len]='\0';
5117- free(temp);
5118-
5119- err = at_send_command("AT+CUSD=1,\"%s\",15", newUSSDRequest);
5120- free(newUSSDRequest);
5121- if (err != AT_NOERROR)
5122- goto error;
6334+ cbytes_t ussdRequest = (cbytes_t)(data);
6335+
6336+ /*
6337+ * ussdRequest should be checked for invalid characters that can be used to
6338+ * send invalid AT commands. However Android have complete check of
6339+ * ussd strings before they are sent to the RIL.
6340+ *
6341+ * AT+CUSD=[<n>[,<str>[,<dcs>]]]
6342+ * <n> = 0,1,2 Dissable, Enable, Cancel
6343+ * <str> = CUSD string in UTF8
6344+ * <dcs> = Cell Brodcast Data Coding Scheme:
6345+ * 0000 German
6346+ * 0001 English
6347+ * 0010 Italian
6348+ * 0011 French
6349+ * 0100 Spanish
6350+ * 0101 Dutch
6351+ * 0110 Swedish
6352+ * 0111 Danish
6353+ * 1000 Portuguese
6354+ * 1001 Finnish
6355+ * 1010 Norwegian
6356+ * 1011 Greek
6357+ * 1100 Turkish
6358+ * 1101..1110 Reserved for European languages
6359+ * 1111 Language unspecified
6360+ *
6361+ * According to Android ril.h , CUSD messages are always sent as utf8,
6362+ * but the dcs field does not have an entry for this.
6363+ * The nearest "most correct" would be 15 = unspecified,
6364+ * not adding the dcs would result in the default "0" meaning German,
6365+ * and some networks are not happy with this.
6366+ *
6367+ * Huawei modems, depending on firmware version, seem to accept GSM8 or
6368+ * a HEX encoded GSM7 request. Try GSM8; if it fails, try GSM7 encoded in HEX
6369+ */
6370+
6371+ /* Convert to GSM8 from UTF8 */
6372+ int utf8len = strlen((const char*)ussdRequest);
6373+ int gsmbytes = utf8_to_gsm8(ussdRequest, utf8len, NULL);
6374+ bytes_t gsm8 = malloc(gsmbytes + 1);
6375+ utf8_to_gsm8(ussdRequest, utf8len, gsm8);
6376+ gsm8[gsmbytes] = 0;
6377+
6378+ /* Try to send it as GSM8 */
6379+ err = at_send_command("AT+CUSD=1,%s,15", gsm8);
6380+
6381+ /* Some modems like the string to be between quotes ... Retry if error */
6382+ if (err != AT_NOERROR) {
6383+ err = at_send_command("AT+CUSD=1,\"%s\",15", gsm8);
6384+ }
6385+ free(gsm8);
6386+
6387+ /* If modem did not accept the USSD, retry it but using HEX encoded GSM7 */
6388+ if (err != AT_NOERROR) {
6389+ char* hex = NULL;
6390+
6391+ /* Convert to GSM7 */
6392+ int gsmseptets = utf8_to_gsm7(ussdRequest, utf8len, NULL, 0);
6393+ int gsmbytes = ((gsmseptets * 7) + 7) / 8; // Round UP, to be able to transmit incomplete septets
6394+ bytes_t gsm7 = malloc(gsmbytes + 1);
6395+ utf8_to_gsm7(ussdRequest, utf8len, gsm7, 0);
6396+ gsm7[gsmbytes] = 0;
6397+
6398+ /* And then encode to HEX */
6399+ hex = malloc(2*gsmbytes+1);
6400+ gsm_hex_from_bytes(hex, gsm7, gsmbytes);
6401+ hex[2*gsmbytes]='\0';
6402+
6403+ /* Retry to send the command */
6404+ ALOGD("utf8len: %d, gsmseptets: %d, gsmbytes:%d", utf8len, gsmseptets, gsmbytes);
6405+ err = at_send_command("AT+CUSD=1,\"%s\",15", hex);
6406+ free(gsm7);
6407+ free(hex);
6408+
6409+ if (err != AT_NOERROR)
6410+ goto error;
6411+ }
51236412
51246413 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
51256414 return;
@@ -5191,11 +6480,9 @@ static void requestResetRadio(RIL_Token t)
51916480
51926481 /* Reset MS */
51936482 err = at_send_command("AT+CFUN=6");
5194- if (err != AT_NOERROR)
5195- goto error;
51966483
51976484 /* Go online */
5198- err = at_send_command("AT^RFSWITCH=1");
6485+ err = at_send_command("AT^RFSWITCH=1"); /* ignore error. If unsupported, the next line will enable RF */
51996486 err = at_send_command("AT+CFUN=1");
52006487 if (err != AT_NOERROR)
52016488 goto error;
@@ -5237,22 +6524,17 @@ static void requestSetLocationUpdates(void *data, size_t datalen, RIL_Token t)
52376524 {
52386525 int err = 0;
52396526 int updates = 0;
5240- ATResponse *atResponse = NULL;
52416527
52426528 updates = ((int *)data)[0] == 1? 2 : 1;
52436529
5244- err = at_send_command_singleline("AT+CREG=%d","+CLIP:",&atResponse, updates);
6530+ err = at_send_command("AT+CREG=%d", updates);
52456531 if (err != AT_NOERROR)
52466532 goto error;
52476533
5248- at_response_free(atResponse);
5249-
5250- //Always return success for CDMA (for now)
52516534 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
52526535 return;
52536536
52546537 error:
5255- at_response_free(atResponse);
52566538 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
52576539 }
52586540
@@ -5268,6 +6550,16 @@ static void requestLastFailCause(RIL_Token t)
52686550 if(err != AT_NOERROR)
52696551 goto error;
52706552
6553+ /*
6554+ CALL_FAIL_NORMAL = 16,
6555+ CALL_FAIL_BUSY = 17,
6556+ CALL_FAIL_CONGESTION = 34,
6557+ CALL_FAIL_ACM_LIMIT_EXCEEDED = 68,
6558+ CALL_FAIL_CALL_BARRED = 240,
6559+ CALL_FAIL_FDN_BLOCKED = 241,
6560+ CALL_FAIL_ERROR_UNSPECIFIED = 0xffff
6561+ */
6562+
52716563 line = atResponse->p_intermediates->line;
52726564 err = at_tok_start(&line);
52736565 if(err < 0) goto error;
@@ -5275,17 +6567,19 @@ static void requestLastFailCause(RIL_Token t)
52756567 err = at_tok_nextstr(&line, &tmp);
52766568 if(err < 0) goto error;
52776569
5278- err = at_tok_nextint(&line, &response);
5279- if(err < 0) goto error;
6570+ if (at_tok_hasmore(&line)) {
6571+ err = at_tok_nextint(&line, &response);
6572+ if(err < 0) goto error;
6573+ }
52806574
5281- RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
5282- at_response_free(atResponse);
5283- return;
6575+ ALOGD("Textual last call fail cause: %s [%d]", tmp, response);
52846576
52856577 error:
5286- at_response_free(atResponse);
5287- RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
52886578
6579+ /* Send the last call fail cause */
6580+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &lastCallFailCause, sizeof(int));
6581+ at_response_free(atResponse);
6582+ return;
52896583 }
52906584
52916585 /*
@@ -5448,30 +6742,6 @@ static void onSIMReady(void *p)
54486742 /* Check if ME is ready to set preferred message storage */
54496743 checkMessageStorageReady(NULL);
54506744
5451- /* Select message service */
5452- at_send_command("AT+CSMS=0");
5453-
5454- /*
5455- * Always send SMS messages directly to the TE
5456- *
5457- * mode = 1 // discard when link is reserved (link should never be
5458- * reserved)
5459- * mt = 2 // most messages routed to TE
5460- * bm = 2 // new cell BM's routed to TE
5461- * ds = 1 // Status reports routed to TE
5462- * bfr = 1 // flush buffer
5463- */
5464- at_send_command("AT+CNMI=1,2,2,1,1");
5465-
5466- /* Select cell broadcast messages: Do not accept messages */
5467- at_send_command("AT+CSCB=1");
5468-
5469- /* Enable automatic timezone update */
5470- at_send_command("AT+CTZU=1");
5471-
5472- /* Enable timezone change reporting */
5473- at_send_command("AT+CTZR=1");
5474-
54756745 /* Subscribe to network registration events.
54766746 * n = 2 - Enable network registration and location information
54776747 * unsolicited result code +CREG: <stat>[,<lac>,<ci>]
@@ -5482,23 +6752,58 @@ static void onSIMReady(void *p)
54826752 at_send_command("AT+CREG=1");
54836753 }
54846754
6755+ /* Enable proactive network registration notifications */
6756+ at_send_command("AT+CGREG=2");
6757+
6758+ /* Extended Cellular result codes enabled */
6759+ at_send_command("AT+CRC=1");
6760+
6761+ /* Calling line identification enabled */
6762+ at_send_command("AT+CLIP=1");
6763+
6764+ /* Call waiting enabled */
6765+ at_send_command("AT+CCWA=1");
6766+
6767+ /* Alternating voice/data off */
6768+ at_send_command("AT+CMOD=0");
6769+
6770+ /* +CSSU unsolicited supp service notifications */
6771+ at_send_command("AT+CSSN=0,1");
6772+
6773+ /* Connected line identification On*/
6774+ at_send_command("AT+COLP=1");
6775+
6776+ /*
6777+ * Ensure that the modem is using GSM character set and not IRA,
6778+ * otherwise weirdness with umlauts and other non-ASCII characters
6779+ * can result
6780+ */
6781+ at_send_command("AT+CSCS=\"GSM\"");
6782+
6783+ /* USSD unsolicited */
6784+ at_send_command("AT+CUSD=1");
6785+
54856786 /* Configure Short Message (SMS) Format
54866787 * mode = 0 - PDU mode.
54876788 */
54886789 at_send_command("AT+CMGF=0");
54896790
5490- /* Enable unsolicited RSSI reporting */
5491- at_send_command("AT^CURC=1");
5492-
5493- /* Enable GPRS reporting */
5494- at_send_command("AT+CGEREP=1,0");
6791+ /* Disable boot messages */
6792+ at_send_command("AT^BOOT=0,0");
54956793
6794+ /* And flow messages */
6795+ at_send_command("AT^DSFLOWRPT=0");
54966796
54976797 /* Select SMS type */
5498- at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
5499-}
6798+ at_send_command_singleline("AT+CSMS=0", "+CSMS:", NULL);
6799+
6800+ /* Always send SMS messages directly to the TE */
6801+ at_send_command("AT+CNMI=2,1,2,2,0");
55006802
6803+ /* Enable unsolicited RSSI reporting */
6804+ at_send_command("AT^CURC=1");
55016805
6806+}
55026807
55036808 static void requestNotSupported(RIL_Token t, int request)
55046809 {
@@ -5519,7 +6824,6 @@ static void processRequest (int request, void *data, size_t datalen, RIL_Token t
55196824 * GENERIC_FAILURE if we're not in SIM_STATE_READY.
55206825 */
55216826 RIL_RadioState radio_state = getRadioState();
5522-D("%s() %s", __func__, radioStateToString(radio_state));
55236827
55246828 if (radio_state != RADIO_STATE_SIM_READY &&
55256829 (request == RIL_REQUEST_WRITE_SMS_TO_SIM ||
@@ -5585,11 +6889,11 @@ D("%s() %s", __func__, radioStateToString(radio_state));
55856889 /* Trigger a rehash of network values, just to be sure. */
55866890 if (((int *)data)[0] == 1)
55876891 RIL_onUnsolicitedResponse(
5588- RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
5589- NULL, 0);
6892+ RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
6893+ NULL, 0);
55906894 break;
55916895
5592- /* Data Call Requests */
6896+ /* Data Call Requests */
55936897 case RIL_REQUEST_SETUP_DATA_CALL:
55946898 requestSetupDefaultPDP(data, datalen, t);
55956899 break;
@@ -5603,7 +6907,7 @@ D("%s() %s", __func__, radioStateToString(radio_state));
56036907 requestPDPContextList(t);
56046908 break;
56056909
5606- /* SMS Requests */
6910+ /* SMS Requests */
56076911 case RIL_REQUEST_SEND_SMS:
56086912 requestSendSMS(data, datalen, t);
56096913 break;
@@ -5638,7 +6942,7 @@ D("%s() %s", __func__, radioStateToString(radio_state));
56386942 requestGSMSMSBroadcastActivation(data, datalen, t);
56396943 break;
56406944
5641- /* SIM Handling Requests */
6945+ /* SIM Handling Requests */
56426946 case RIL_REQUEST_SIM_IO:
56436947 requestSIM_IO(data, datalen, t);
56446948 break;
@@ -5664,7 +6968,7 @@ D("%s() %s", __func__, radioStateToString(radio_state));
56646968 requestSetFacilityLock(data, datalen, t);
56656969 break;
56666970
5667- /* Network Requests */
6971+ /* Network Requests */
56686972 case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION:
56696973 requestEnterSimPin(data, datalen, t, request);
56706974 break;
@@ -5686,14 +6990,14 @@ D("%s() %s", __func__, radioStateToString(radio_state));
56866990 case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
56876991 requestGetPreferredNetworkType(t);
56886992 break;
5689- case RIL_REQUEST_VOICE_REGISTRATION_STATE:
5690- requestRegistrationState(t);
5691- break;
56926993 case RIL_REQUEST_DATA_REGISTRATION_STATE:
5693- requestGprsRegistrationState(t);
6994+ requestRegistrationState(t, 1);
6995+ break;
6996+ case RIL_REQUEST_VOICE_REGISTRATION_STATE:
6997+ requestRegistrationState(t, 0);
56946998 break;
56956999
5696- /* OEM */
7000+ /* OEM */
56977001 case RIL_REQUEST_OEM_HOOK_RAW:
56987002 // echo back data
56997003 requestOEMHookRaw(data, datalen, t);
@@ -5702,7 +7006,7 @@ D("%s() %s", __func__, radioStateToString(radio_state));
57027006 requestOEMHookStrings(data, datalen, t);
57037007 break;
57047008
5705- /* Misc */
7009+ /* Misc */
57067010 case RIL_REQUEST_SIGNAL_STRENGTH:
57077011 requestSignalStrength(t);
57087012 break;
@@ -5716,7 +7020,7 @@ D("%s() %s", __func__, radioStateToString(radio_state));
57167020 requestGetIMSI(t);
57177021 break;
57187022 case RIL_REQUEST_GET_IMEI:
5719- requestGetIMEISV(t);
7023+ requestGetIMEI(t);
57207024 break;
57217025 case RIL_REQUEST_GET_IMEISV:
57227026 requestGetIMEISV(t);
@@ -5728,7 +7032,15 @@ D("%s() %s", __func__, radioStateToString(radio_state));
57287032 requestBasebandVersion(t);
57297033 break;
57307034
5731- /* SIM Application Toolkit */
7035+ /* Band control */
7036+ case RIL_REQUEST_SET_BAND_MODE:
7037+ requestSetBandMode(data, datalen, t);
7038+ break;
7039+ case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE:
7040+ requestQueryAvailableBandMode(data, datalen, t);
7041+ break;
7042+
7043+ /* SIM Application Toolkit */
57327044 case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
57337045 requestStkSendTerminalResponse(data, datalen, t);
57347046 break;
@@ -5745,7 +7057,7 @@ D("%s() %s", __func__, radioStateToString(radio_state));
57457057 requestReportStkServiceIsRunning(t);
57467058 break;
57477059
5748- /* Misc ops */
7060+ /* Misc ops */
57497061 case RIL_REQUEST_DIAL:
57507062 requestDial(data, datalen, t);
57517063 break;
@@ -5862,7 +7174,7 @@ D("%s() %s", __func__, radioStateToString(radio_state));
58627174
58637175 default:
58647176 ALOGW("FIXME: Unsupported request logged: %s",
5865- requestToString(request));
7177+ requestToString(request));
58667178 requestNotSupported(t, request);
58677179 break;
58687180 }
@@ -5892,8 +7204,7 @@ static void onRequest(int request, void *data, size_t datalen, RIL_Token t)
58927204 RequestQueue *q = &s_requestQueue;
58937205 int err;
58947206
5895- r = (RILRequest *) malloc(sizeof(RILRequest));
5896- memset(r, 0, sizeof(RILRequest));
7207+ r = (RILRequest *) calloc(1, sizeof(RILRequest));
58977208
58987209 /* Formulate a RILRequest and put it in the queue. */
58997210 r->request = request;
@@ -5986,90 +7297,40 @@ static void sendTime(void *p)
59867297 at_send_command("AT+CCLK=\"%s%c%02d\"", str, tz[0], tzi);
59877298 }
59887299
5989-
7300+/**
7301+ * Initialize everything
7302+ */
59907303 static char initializeCommon(void)
59917304 {
59927305 int err = 0;
59937306 unsigned int i;
59947307 static const char* const initcmd[] = {
59957308
5996- /* Reset the MS*/
5997- "AT+CFUN=6",
5998-
5999- /* atchannel is tolerant of echo but it must */
6000- /* reset and have verbose result codes */
6001- "ATZV1",
6002-
60037309 /* echo off */
60047310 "ATE0",
60057311
6006- /* No auto-answer */
6007- "ATS0=0",
7312+ /* Send verbose results */
7313+ "ATQ0V1",
60087314
60097315 /* No auto-answer */
6010- "AT%AUTOANSWER=0",
6011-
6012- /* send results */
6013- "ATQ0",
6014-
6015- /* check for busy, don't check for dialone */
6016- "ATX3",
6017-
6018- /* set DCD depending on service */
6019- "AT&C1",
6020-
6021- /* set DTR according to service */
6022- "AT&D1",
7316+ "ATS0=0",
60237317
60247318 /* Extended errors without textual decriptions */
60257319 "AT+CMEE=1",
60267320
6027- /* detailed rings, unknown */
6028- "AT+CRC=1;+CR=1",
6029-
6030- /* caller id = yes */
6031- "AT+CLIP=1",
6032-
6033- /* don't hide outgoing callerID */
6034- "AT+CLIR=0",
6035-
6036- /* Call Waiting notifications */
6037- "AT+CCWA=1",
6038-
6039- /* No connected line identification */
6040- "AT+COLP=0",
6041-
6042- /* USSD unsolicited */
6043- "AT+CUSD=1",
6044-
6045- /* SMS PDU mode */
6046- "AT+CMGF=0",
6047-
6048- //"AT+GTKC=2",
6049-
6050- /* +CSSU unsolicited supp service notifications */
6051- "AT+CSSN=0,1",
6052-
6053- /* HEX character set */
6054- //"AT+CSCS=\"HEX\"",
6055- "AT+CSCS=\"IRA\"",
6056-
6057- /* Modem mode */
6058- "AT+FCLASS=0",
6059-
6060- "AT+CNMI=1,2,2,2,0",
6061- //"AT+CPPP=1",
7321+ /* Enable RF */
7322+ "AT^RFSWITCH=1"
7323+ };
60627324
7325+ D("%s()", __func__);
60637326
6064- "AT"
6065- };
7327+ setRadioState(RADIO_STATE_OFF);
60667328
60677329 if (at_handshake() < 0) {
60687330 LOG_FATAL("Handshake failed!");
60697331 return 1;
60707332 }
60717333
6072-
60737334 for (i=0; i < sizeof(initcmd) / sizeof(initcmd[0]); i++) {
60747335 err = at_send_command(initcmd[i]);
60757336 if (err != AT_NOERROR) {
@@ -6077,63 +7338,9 @@ static char initializeCommon(void)
60777338 }
60787339 }
60797340
6080- /* Send the current time of the OS to the module */
6081- sendTime(NULL);
6082-
6083- return 0;
6084-}
6085-
6086-/**
6087- * Initialize everything
6088- */
6089-static char initializeChannel(void)
6090-{
6091- int err = 0;
6092- unsigned int i;
6093- static const char* const initcmd[] = {
6094-
6095- /* Configure Packet Domain Network Registration Status events
6096- * 2 = Enable network registration and location information
6097- * unsolicited result code
6098- */
6099-
6100- /* Alternating voice/data off */
6101- "AT+CMOD=0",
7341+ /* TE-MS handshake function */
7342+ //"AT^HS=0,0",
61027343
6103- /* Not muted */
6104- "AT+CMUT=0",
6105-
6106- /* Network registration events */
6107- "AT+CREG=2",
6108-
6109- /* GPRS registration events */
6110- "AT+CGREG=2",
6111-
6112- "AT+CGEQREQ=1,4,0,0,0,0,2,0,\"0E0\",\"0E0\",3,0,0",
6113-
6114- /* Enable unsolicited reports */
6115- "AT^CURC=1",
6116-
6117- /* Enable GPRS reporting */
6118- "AT+CGEREP=1,0",
6119-
6120- /* for 3G Preferred */
6121- "AT^SYSCFG=2,2,3FFFFFFF,1,2",
6122-
6123- /* Disable RF */
6124- "AT^RFSWITCH=0"
6125- };
6126-
6127- D("%s()", __func__);
6128-
6129- setRadioState(RADIO_STATE_OFF);
6130-
6131- for (i=0; i < sizeof(initcmd) / sizeof(initcmd[0]); i++) {
6132- err = at_send_command(initcmd[i]);
6133- if (err != AT_NOERROR) {
6134- ALOGE("Failed sending command '%s'",initcmd[i]);
6135- }
6136- }
61377344
61387345 /* Assume radio is off on error. */
61397346 if (isRadioOn() > 0)
@@ -6154,28 +7361,75 @@ static void onUnsolicited (const char *s, const char *sms_pdu)
61547361 if (getRadioState() == RADIO_STATE_UNAVAILABLE)
61557362 return;
61567363
7364+ /* Timezone */
61577365 if (strStartsWith(s, "%CTZV:")
61587366 || strStartsWith(s,"+CTZV:")
61597367 || strStartsWith(s,"+CTZDST:")
6160- || strStartsWith(s,"+HTCCTZV:")) {
7368+ || strStartsWith(s,"+HTCCTZV:")
7369+ || strStartsWith(s,"^NWTIME:")
7370+ ) {
61617371 unsolicitedNitzTime(s);
7372+
7373+ /* Call status/start/end indicator */
61627374 } else if (strStartsWith(s,"+CRING:")
61637375 || strStartsWith(s,"RING")
7376+ || strStartsWith(s,"+CLIP")
61647377 || strStartsWith(s,"NO CARRIER")
61657378 || strStartsWith(s,"+CCWA")
7379+ || strStartsWith(s,"^ORIG:")
7380+ || strStartsWith(s,"^CONF:")
7381+ || strStartsWith(s,"^CONN:")
7382+ || strStartsWith(s,"^CEND:")
61667383 ) {
6167- RIL_onUnsolicitedResponse (
7384+
7385+ /* Start/stop audio tunnel if needed when a successful connection is done */
7386+ if ( strStartsWith(s,"^ORIG:")) {
7387+ enqueueRILEvent(startAudioTunnel, NULL, NULL);
7388+ unsolicitedORIG(s);
7389+ } else
7390+ if ( strStartsWith(s,"^CONF:")) {
7391+ enqueueRILEvent(startAudioTunnel, NULL, NULL);
7392+ unsolicitedCONF(s);
7393+ } else
7394+ if ( strStartsWith(s,"^CONN:")) {
7395+ enqueueRILEvent(startAudioTunnel, NULL, NULL);
7396+ unsolicitedCONN(s);
7397+ } else
7398+ if (strStartsWith(s,"^CEND:")) {
7399+ /* This is the only fast way to detect when call was hang by the callee */
7400+ enqueueRILEvent(stopAudioTunnel, NULL, NULL);
7401+ unsolicitedCEND(s);
7402+ }
7403+
7404+ RIL_onUnsolicitedResponse(
7405+ RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
7406+ NULL, 0);
7407+ enqueueRILEvent(onDataCallListChanged, NULL, NULL);
7408+
7409+ /* Data call status/start/end */
7410+ } else if (strStartsWith(s,"^DCONN:")
7411+ || strStartsWith(s,"^DEND:")) {
7412+
7413+ RIL_onUnsolicitedResponse(
61687414 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
61697415 NULL, 0);
61707416 enqueueRILEvent(onDataCallListChanged, NULL, NULL);
6171- } else if (strStartsWith(s,"^RSSI:") ||
6172- strStartsWith(s,"%RSSI:")) {
7417+
7418+ } else if (strStartsWith(s,"^COMM:")) {
7419+
7420+
7421+ } else if (strStartsWith(s,"^RSSI:")
7422+ || strStartsWith(s,"%RSSI:")) {
61737423 unsolicitedRSSI(s);
61747424 } else if (strStartsWith(s,"^MODE:")) {
61757425 unsolicitedMode(s);
7426+ } else if (strStartsWith(s,"^SRVST:")) {
7427+ unsolicitedSrvStatus(s);
7428+ } else if (strStartsWith(s,"^SIMST:")) {
7429+ unsolicitedSimStatus(s);
61767430 } else if (strStartsWith(s,"+CREG:")
61777431 || strStartsWith(s,"+CGREG:")) {
6178- RIL_onUnsolicitedResponse (
7432+ RIL_onUnsolicitedResponse(
61797433 RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
61807434 NULL, 0);
61817435 enqueueRILEvent(onDataCallListChanged, NULL, NULL);
@@ -6183,7 +7437,8 @@ static void onUnsolicited (const char *s, const char *sms_pdu)
61837437 onNewSms(sms_pdu);
61847438 } else if (strStartsWith(s, "+CBM:")) {
61857439 onNewBroadcastSms(sms_pdu);
6186- } else if (strStartsWith(s, "+CMTI:")) {
7440+ } else if (strStartsWith(s, "+CMTI:")
7441+ || strStartsWith(s, "+CDSI:")) {
61877442 onNewSmsOnSIM(s);
61887443 } else if (strStartsWith(s, "+CDS:")) {
61897444 onNewStatusReport(sms_pdu);
@@ -6196,8 +7451,9 @@ static void onUnsolicited (const char *s, const char *sms_pdu)
61967451 enqueueRILEvent(onDataCallListChanged, NULL, NULL);
61977452 } else if (strStartsWith(s, "+CUSD:")) {
61987453 unsolicitedUSSD(s);
6199- } else if (strStartsWith(s, "+CIEV: 7") ||
6200- strStartsWith(s, "Received SMS:")) {
7454+ } else if (strStartsWith(s, "+CIEV: 7")
7455+ || strStartsWith(s, "Received SMS:")
7456+ || strStartsWith(s, "^SMMEMFULL") ) {
62017457 onNewSmsIndication();
62027458 }
62037459 }
@@ -6210,16 +7466,16 @@ static void signalCloseQueues(void)
62107466 RequestQueue *q = s_requestQueues[i];
62117467 if ((err = pthread_mutex_lock(&q->queueMutex)) != 0)
62127468 ALOGE("%s() failed to take queue mutex: %s",
6213- __func__, strerror(err));
7469+ __func__, strerror(err));
62147470
62157471 q->closed = 1;
62167472 if ((err = pthread_cond_signal(&q->cond)) != 0)
62177473 ALOGE("%s() failed to broadcast queue update: %s",
6218- __func__, strerror(err));
7474+ __func__, strerror(err));
62197475
62207476 if ((err = pthread_mutex_unlock(&q->queueMutex)) != 0)
62217477 ALOGE("%s() failed to take queue mutex: %s", __func__,
6222- strerror(err));
7478+ strerror(err));
62237479 }
62247480 }
62257481
@@ -6251,7 +7507,7 @@ static void onATTimeout()
62517507 static void usage(char *s)
62527508 {
62537509 #ifdef RIL_SHLIB
6254- fprintf(stderr, "htcgeneric-ril requires: -p <tcp port> or -d /dev/tty_device\n");
7510+ fprintf(stderr, "generic-ril requires: -p <tcp port> or -d /dev/tty_device\n");
62557511 #else
62567512 fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device] [-v /dev/tty_device]\n", s);
62577513 exit(-1);
@@ -6318,8 +7574,8 @@ static void *queueRunner(void *param)
63187574
63197575 if (fd < 0) {
63207576 ALOGE("%s() Failed to open AT channel %s (%s), retrying in %d.",
6321- __func__, queueArgs->device_path,
6322- strerror(errno), TIMEOUT_SEARCH_FOR_TTY);
7577+ __func__, queueArgs->device_path,
7578+ strerror(errno), TIMEOUT_SEARCH_FOR_TTY);
63237579 sleep(TIMEOUT_SEARCH_FOR_TTY);
63247580 /* Never returns. */
63257581 }
@@ -6339,18 +7595,12 @@ static void *queueRunner(void *param)
63397595 q = &s_requestQueue;
63407596
63417597 if (initializeCommon()) {
6342- ALOGE("%s() Failed to initialize channel!", __func__);
7598+ ALOGE("%s() Failed to initialize common", __func__);
63437599 at_close();
63447600 continue;
63457601 }
63467602
63477603 q->closed = 0;
6348- if (initializeChannel()) {
6349- ALOGE("%s() Failed to initialize channel!", __func__);
6350- at_close();
6351- continue;
6352- }
6353-
63547604 at_make_default_channel();
63557605
63567606 ALOGE("%s() Looping the requestQueue!", __func__);
@@ -6362,9 +7612,9 @@ static void *queueRunner(void *param)
63627612
63637613 memset(&ts, 0, sizeof(ts));
63647614
6365- if ((err = pthread_mutex_lock(&q->queueMutex)) != 0)
6366- ALOGE("%s() failed to take queue mutex: %s!",
6367- __func__, strerror(err));
7615+ if ((err = pthread_mutex_lock(&q->queueMutex)) != 0)
7616+ ALOGE("%s() failed to take queue mutex: %s!",
7617+ __func__, strerror(err));
63687618
63697619 if (q->closed != 0) {
63707620 ALOGW("%s() AT Channel error, attempting to recover..", __func__);
@@ -6374,10 +7624,10 @@ static void *queueRunner(void *param)
63747624 }
63757625
63767626 while (q->closed == 0 && q->requestList == NULL &&
6377- q->eventList == NULL) {
7627+ q->eventList == NULL) {
63787628 if ((err = pthread_cond_wait(&q->cond, &q->queueMutex)) != 0)
63797629 ALOGE("%s() failed broadcast queue cond: %s!",
6380- __func__, strerror(err));
7630+ __func__, strerror(err));
63817631 }
63827632
63837633 /* eventList is prioritized, smallest abstime first. */
@@ -6386,13 +7636,13 @@ static void *queueRunner(void *param)
63867636 err = pthread_cond_timedwait(&q->cond, &q->queueMutex, &q->eventList->abstime);
63877637 if (err && err != ETIMEDOUT)
63887638 ALOGE("%s() timedwait returned unexpected error: %s",
6389- __func__, strerror(err));
7639+ __func__, strerror(err));
63907640 }
63917641
63927642 if (q->closed != 0) {
63937643 if ((err = pthread_mutex_unlock(&q->queueMutex)) != 0)
63947644 ALOGE("%s(): Failed to release queue mutex: %s!",
6395- __func__, strerror(err));
7645+ __func__, strerror(err));
63967646 continue; /* Catch the closed bit at the top of the loop. */
63977647 }
63987648
@@ -6402,7 +7652,7 @@ static void *queueRunner(void *param)
64027652 clock_gettime(CLOCK_MONOTONIC, &ts);
64037653
64047654 if (q->eventList != NULL &&
6405- timespec_cmp(q->eventList->abstime, ts, < )) {
7655+ timespec_cmp(q->eventList->abstime, ts, < )) {
64067656 e = q->eventList;
64077657 q->eventList = e->next;
64087658 }
@@ -6414,7 +7664,7 @@ static void *queueRunner(void *param)
64147664
64157665 if ((err = pthread_mutex_unlock(&q->queueMutex)) != 0)
64167666 ALOGE("%s(): Failed to release queue mutex: %s!",
6417- __func__, strerror(err));
7667+ __func__, strerror(err));
64187668
64197669 if (e) {
64207670 e->eventCallback(e->param);
@@ -6441,10 +7691,31 @@ const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
64417691 int opt;
64427692 int port = -1;
64437693 char *loophost = NULL;
6444- const char *device_path = NULL;
7694+ const char *ctrl_path = NULL;
64457695 struct queueArgs *queueArgs;
64467696 pthread_attr_t attr;
64477697
7698+#if 0
7699+ /* Logcat test */
7700+ char local_ip[64];
7701+ char dns1[64];
7702+ char dns2[64];
7703+ char gw[64];
7704+ struct timeval from;
7705+ int rr;
7706+ gettimeofday(&from,NULL);
7707+ rr = get_pppd_info(&from,local_ip, dns1, dns2, gw);
7708+ ALOGD("result: %d",rr);
7709+#endif
7710+
7711+#if 0
7712+ char * m = decodeUSSD("D9775D0E6286E7749050FEBECFD3EE33685A9ECFD36F37283D07BDCD201868297449CBED70DA9D769F414679B90C2287E96190FDCDAEB7CBA0F41C849BCD60B41C68297401");
7713+ ALOGD("Decoded msg: '%s'",m);
7714+ free(m);
7715+#endif
7716+
7717+ memset(&sAudioChannel, 0, sizeof(sAudioChannel));
7718+
64487719 s_rilenv = env;
64497720
64507721 /* By default, use USB1 as audio channel */
@@ -6452,7 +7723,7 @@ const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
64527723
64537724 D("%s() entering...", __func__);
64547725
6455- while (-1 != (opt = getopt(argc, argv, "z:p:d:v:"))) {
7726+ while (-1 != (opt = getopt(argc, argv, "z:n:i:p:d:v:"))) {
64567727 switch (opt) {
64577728 case 'z':
64587729 loophost = optarg;
@@ -6469,8 +7740,8 @@ const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
64697740 break;
64707741
64717742 case 'd':
6472- device_path = optarg;
6473- D("%s() Opening tty device %s", __func__, device_path);
7743+ ctrl_path = optarg;
7744+ D("%s() Opening tty device %s", __func__, ctrl_path);
64747745 break;
64757746
64767747 case 'v':
@@ -6478,21 +7749,30 @@ const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
64787749 D("%s() Opening voice tty device %s", __func__, sAudioDevice);
64797750 break;
64807751
7752+ case 'n':
7753+ rndis_iface_dev = optarg;
7754+ D("%s() Using network interface %s as primary data channel.", __func__, rndis_iface_dev);
7755+ break;
7756+
7757+ case 'i':
7758+ ppp_iface_dev = optarg;
7759+ D("%s() Using ppp interface %s as primary data channel.", __func__, ppp_iface_dev);
7760+ break;
7761+
64817762 default:
64827763 usage(argv[0]);
64837764 return NULL;
64847765 }
64857766 }
64867767
6487- if (port < 0 && device_path == NULL) {
7768+ if (port < 0 && ctrl_path == NULL) {
64887769 usage(argv[0]);
64897770 return NULL;
64907771 }
64917772
6492- queueArgs = (struct queueArgs*) malloc(sizeof(struct queueArgs));
6493- memset(queueArgs, 0, sizeof(struct queueArgs));
7773+ queueArgs = (struct queueArgs*) calloc(1, sizeof(struct queueArgs));
64947774
6495- queueArgs->device_path = device_path;
7775+ queueArgs->device_path = ctrl_path;
64967776 queueArgs->port = port;
64977777 queueArgs->loophost = loophost;
64987778
@@ -6510,15 +7790,17 @@ int main (int argc, char **argv)
65107790 int opt;
65117791 int port = -1;
65127792 char *loophost = NULL;
6513- const char *device_path = NULL;
7793+ const char *ctrl_path = NULL;
65147794 struct queueArgs *queueArgs;
65157795
7796+ memset(&sAudioChannel, 0, sizeof(sAudioChannel));
7797+
65167798 /* By default, use USB1 as audio channel */
65177799 strcpy(sAudioDevice,"/dev/ttyUSB1");
65187800
65197801 D("%s() entering...", __func__);
65207802
6521- while (-1 != (opt = getopt(argc, argv, "z:p:d:v:"))) {
7803+ while (-1 != (opt = getopt(argc, argv, "z:n:i:p:d:v:"))) {
65227804 switch (opt) {
65237805 case 'z':
65247806 loophost = optarg;
@@ -6535,8 +7817,8 @@ int main (int argc, char **argv)
65357817 break;
65367818
65377819 case 'd':
6538- device_path = optarg;
6539- D("%s() Opening tty device %s", __func__, device_path);
7820+ ctrl_path = optarg;
7821+ D("%s() Opening tty device %s", __func__, ctrl_path);
65407822 break;
65417823
65427824 case 'v':
@@ -6544,21 +7826,30 @@ int main (int argc, char **argv)
65447826 D("%s() Opening voice tty device %s", __func__, sAudioDevice);
65457827 break;
65467828
7829+ case 'n':
7830+ rndis_iface_dev = optarg;
7831+ D("%s() Using network interface %s as primary data channel.", __func__, rndis_iface_dev);
7832+ break;
7833+
7834+ case 'i':
7835+ ppp_iface_dev = optarg;
7836+ D("%s() Using ppp interface %s as primary data channel.", __func__, ppp_iface_dev);
7837+ break;
7838+
65477839 default:
65487840 usage(argv[0]);
65497841 return 0;
65507842 }
65517843 }
65527844
6553- if (port < 0 && device_path == NULL) {
7845+ if (port < 0 && ctrl_path == NULL) {
65547846 usage(argv[0]);
65557847 return 0;
65567848 }
65577849
6558- queueArgs = (struct queueArgs*) malloc(sizeof(struct queueArgs));
6559- memset(queueArgs, 0, sizeof(struct queueArgs));
7850+ queueArgs = (struct queueArgs*) calloc(1, sizeof(struct queueArgs));
65607851
6561- queueArgs->device_path = device_path;
7852+ queueArgs->device_path = ctrl_path;
65627853 queueArgs->port = port;
65637854 queueArgs->loophost = loophost;
65647855
--- a/huaweigeneric-ril/misc.c
+++ b/huaweigeneric-ril/misc.c
@@ -78,9 +78,9 @@ char *getFirstElementValue(const char* document,
7878 to be used when document contains many tags with same name. */
7979 if (remainingDocument != NULL)
8080 *remainingDocument = end + strlen(elementEndTag);
81+ }
8182 }
8283 }
83- }
8484 return value;
8585 }
8686
--- /dev/null
+++ b/huaweigeneric-ril/net-utils.c
@@ -0,0 +1,188 @@
1+/*
2+ * Copyright 2008, The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#include <stdio.h>
18+#include <stdlib.h>
19+#include <unistd.h>
20+#include <string.h>
21+#include <errno.h>
22+
23+#include <sys/socket.h>
24+#include <sys/select.h>
25+#include <sys/types.h>
26+#include <netinet/in.h>
27+#include <arpa/inet.h>
28+
29+#include <linux/if.h>
30+#include <linux/sockios.h>
31+#include <linux/route.h>
32+#include <linux/wireless.h>
33+
34+#define LOG_TAG "mbm-netutils"
35+#include <cutils/log.h>
36+#include <cutils/properties.h>
37+
38+static int ifc_ctl_sock = -1;
39+
40+static const char *ipaddr_to_string(in_addr_t addr)
41+{
42+ struct in_addr in_addr;
43+
44+ in_addr.s_addr = addr;
45+ return inet_ntoa(in_addr);
46+}
47+
48+int ifc_init(void)
49+{
50+ if (ifc_ctl_sock == -1) {
51+ ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
52+ if (ifc_ctl_sock < 0)
53+ ALOGE("%s() socket() failed: %s", __func__, strerror(errno));
54+ }
55+ return ifc_ctl_sock < 0 ? -1 : 0;
56+}
57+
58+void ifc_close(void)
59+{
60+ if (ifc_ctl_sock != -1) {
61+ (void) close(ifc_ctl_sock);
62+ ifc_ctl_sock = -1;
63+ }
64+}
65+
66+static void ifc_init_ifr(const char *name, struct ifreq *ifr)
67+{
68+ memset(ifr, 0, sizeof(struct ifreq));
69+ strncpy(ifr->ifr_name, name, IFNAMSIZ);
70+ ifr->ifr_name[IFNAMSIZ - 1] = 0;
71+}
72+
73+static int ifc_set_flags(const char *name, unsigned set, unsigned clr)
74+{
75+ struct ifreq ifr;
76+ ifc_init_ifr(name, &ifr);
77+
78+ if (ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0)
79+ return -1;
80+ ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set;
81+ return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr);
82+}
83+
84+int ifc_up(const char *name)
85+{
86+ return ifc_set_flags(name, IFF_UP | IFF_NOARP, 0);
87+}
88+
89+int ifc_down(const char *name)
90+{
91+ return ifc_set_flags(name, 0, IFF_UP);
92+}
93+
94+static void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr)
95+{
96+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
97+ sin->sin_family = AF_INET;
98+ sin->sin_port = 0;
99+ sin->sin_addr.s_addr = addr;
100+}
101+
102+int ifc_set_addr(const char *name, in_addr_t addr)
103+{
104+ struct ifreq ifr;
105+
106+ ifc_init_ifr(name, &ifr);
107+ init_sockaddr_in(&ifr.ifr_addr, addr);
108+
109+ return ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
110+}
111+
112+int ifc_set_mask(const char *name, in_addr_t mask)
113+{
114+ struct ifreq ifr;
115+
116+ ifc_init_ifr(name, &ifr);
117+ init_sockaddr_in(&ifr.ifr_addr, mask);
118+
119