1 /* //device/system/reference-ril/reference-ril.c
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include <telephony/ril_cdma_sms.h>
19 #include <telephony/librilutils.h>
20 #include <stdio.h>
21 #include <assert.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <sys/cdefs.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <inttypes.h>
29 #include <fcntl.h>
30 #include <pthread.h>
31 #include <alloca.h>
32 #include "atchannel.h"
33 #include "at_tok.h"
34 #include "base64util.h"
35 #include "misc.h"
36 #include <getopt.h>
37 #include <sys/socket.h>
38 #include <cutils/properties.h>
39 #include <cutils/sockets.h>
40 #include <termios.h>
41 #include <sys/wait.h>
42 #include <stdbool.h>
43 #include <net/if.h>
44 #include <netinet/in.h>
45 #include <linux/vm_sockets.h>
46 #include <arpa/inet.h>
47
48 #include "guest/hals/ril/reference-libril/ril.h"
49 #define LOG_TAG "RIL"
50 #include <utils/Log.h>
51
noopRemoveWarning(void * a)52 static void *noopRemoveWarning( void *a ) { return a; }
53 #define RIL_UNUSED_PARM(a) noopRemoveWarning((void *)&(a));
54
55 #define MAX_AT_RESPONSE 0x1000
56
57 #define MAX_PDP 11 // max LTE bearers
58
59 /* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */
60 // This is used if Wifi is not supported, plain old eth0
61 #ifdef CUTTLEFISH_ENABLE
62 #define PPP_TTY_PATH_ETH0 "buried_eth0"
63 #else
64 #define PPP_TTY_PATH_ETH0 "eth0"
65 #endif
66 // This is used for emulator
67 #define EMULATOR_RADIO_INTERFACE "eth0"
68
69 // for sim
70 #define AUTH_CONTEXT_EAP_SIM 128
71 #define AUTH_CONTEXT_EAP_AKA 129
72 #define SIM_AUTH_RESPONSE_SUCCESS 0
73 #define SIM_AUTH_RESPONSE_SYNC_FAILURE 3
74
75 // Default MTU value
76 #define DEFAULT_MTU 1500
77
78 #ifdef USE_TI_COMMANDS
79
80 // Enable a workaround
81 // 1) Make incoming call, do not answer
82 // 2) Hangup remote end
83 // Expected: call should disappear from CLCC line
84 // Actual: Call shows as "ACTIVE" before disappearing
85 #define WORKAROUND_ERRONEOUS_ANSWER 1
86
87 // Some variants of the TI stack do not support the +CGEV unsolicited
88 // response. However, they seem to send an unsolicited +CME ERROR: 150
89 #define WORKAROUND_FAKE_CGEV 1
90 #endif
91
92 /* Modem Technology bits */
93 #define MDM_GSM 0x01
94 #define MDM_WCDMA 0x02
95 #define MDM_CDMA 0x04
96 #define MDM_EVDO 0x08
97 #define MDM_TDSCDMA 0x10
98 #define MDM_LTE 0x20
99 #define MDM_NR 0x40
100
101 typedef struct {
102 int supportedTechs; // Bitmask of supported Modem Technology bits
103 int currentTech; // Technology the modem is currently using (in the format used by modem)
104 int isMultimode;
105
106 // Preferred mode bitmask. This is actually 4 byte-sized bitmasks with different priority values,
107 // in which the byte number from LSB to MSB give the priority.
108 //
109 // |MSB| | |LSB
110 // value: |00 |00 |00 |00
111 // byte #: |3 |2 |1 |0
112 //
113 // Higher byte order give higher priority. Thus, a value of 0x0000000f represents
114 // a preferred mode of GSM, WCDMA, CDMA, and EvDo in which all are equally preferable, whereas
115 // 0x00000201 represents a mode with GSM and WCDMA, in which WCDMA is preferred over GSM
116 int32_t preferredNetworkMode;
117 int subscription_source;
118
119 } ModemInfo;
120
121 static ModemInfo *sMdmInfo;
122 // TECH returns the current technology in the format used by the modem.
123 // It can be used as an l-value
124 #define TECH(mdminfo) ((mdminfo)->currentTech)
125 // TECH_BIT returns the bitmask equivalent of the current tech
126 #define TECH_BIT(mdminfo) (1 << ((mdminfo)->currentTech))
127 #define IS_MULTIMODE(mdminfo) ((mdminfo)->isMultimode)
128 #define TECH_SUPPORTED(mdminfo, tech) ((mdminfo)->supportedTechs & (tech))
129 #define PREFERRED_NETWORK(mdminfo) ((mdminfo)->preferredNetworkMode)
130 // CDMA Subscription Source
131 #define SSOURCE(mdminfo) ((mdminfo)->subscription_source)
132
133 static int net2modem[] = {
134 MDM_GSM | MDM_WCDMA, // 0 - GSM / WCDMA Pref
135 MDM_GSM, // 1 - GSM only
136 MDM_WCDMA, // 2 - WCDMA only
137 MDM_GSM | MDM_WCDMA, // 3 - GSM / WCDMA Auto
138 MDM_CDMA | MDM_EVDO, // 4 - CDMA / EvDo Auto
139 MDM_CDMA, // 5 - CDMA only
140 MDM_EVDO, // 6 - EvDo only
141 MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO, // 7 - GSM/WCDMA, CDMA, EvDo
142 MDM_LTE | MDM_CDMA | MDM_EVDO, // 8 - LTE, CDMA and EvDo
143 MDM_LTE | MDM_GSM | MDM_WCDMA, // 9 - LTE, GSM/WCDMA
144 MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
145 MDM_LTE, // 11 - LTE only
146 MDM_LTE | MDM_WCDMA, // 12 - LTE and WCDMA
147 MDM_TDSCDMA, // 13 - TD-SCDMA only
148 MDM_WCDMA | MDM_TDSCDMA, // 14 - TD-SCDMA and WCDMA
149 MDM_LTE | MDM_TDSCDMA, // 15 - LTE and TD-SCDMA
150 MDM_TDSCDMA | MDM_GSM, // 16 - TD-SCDMA and GSM
151 MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 17 - TD-SCDMA, GSM and LTE
152 MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 18 - TD-SCDMA, GSM and WCDMA
153 MDM_LTE | MDM_WCDMA | MDM_TDSCDMA, // 19 - LTE, TD-SCDMA and WCDMA
154 MDM_LTE | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 20 - LTE, TD-SCDMA, GSM, and WCDMA
155 MDM_EVDO | MDM_CDMA | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 21 - TD-SCDMA, CDMA, EVDO, GSM and WCDMA
156 MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 22 - LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA
157 MDM_NR, // 23 - NR 5G only mode
158 MDM_NR | MDM_LTE, // 24 - NR 5G, LTE
159 MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO, // 25 - NR 5G, LTE, CDMA and EvDo
160 MDM_NR | MDM_LTE | MDM_WCDMA | MDM_GSM, // 26 - NR 5G, LTE, GSM and WCDMA
161 MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 27 - NR 5G, LTE, CDMA, EvDo, GSM and WCDMA
162 MDM_NR | MDM_LTE | MDM_WCDMA, // 28 - NR 5G, LTE and WCDMA
163 MDM_NR | MDM_LTE | MDM_TDSCDMA, // 29 - NR 5G, LTE and TDSCDMA
164 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 30 - NR 5G, LTE, TD-SCDMA and GSM
165 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA, // 31 - NR 5G, LTE, TD-SCDMA, WCDMA
166 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA | MDM_GSM, // 32 - NR 5G, LTE, TD-SCDMA, GSM and WCDMA
167 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 33 - NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA
168 };
169
170 static int32_t net2pmask[] = {
171 MDM_GSM | (MDM_WCDMA << 8), // 0 - GSM / WCDMA Pref
172 MDM_GSM, // 1 - GSM only
173 MDM_WCDMA, // 2 - WCDMA only
174 MDM_GSM | MDM_WCDMA, // 3 - GSM / WCDMA Auto
175 MDM_CDMA | MDM_EVDO, // 4 - CDMA / EvDo Auto
176 MDM_CDMA, // 5 - CDMA only
177 MDM_EVDO, // 6 - EvDo only
178 MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO, // 7 - GSM/WCDMA, CDMA, EvDo
179 MDM_LTE | MDM_CDMA | MDM_EVDO, // 8 - LTE, CDMA and EvDo
180 MDM_LTE | MDM_GSM | MDM_WCDMA, // 9 - LTE, GSM/WCDMA
181 MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
182 MDM_LTE, // 11 - LTE only
183 MDM_LTE | MDM_WCDMA, // 12 - LTE and WCDMA
184 MDM_TDSCDMA, // 13 - TD-SCDMA only
185 MDM_WCDMA | MDM_TDSCDMA, // 14 - TD-SCDMA and WCDMA
186 MDM_LTE | MDM_TDSCDMA, // 15 - LTE and TD-SCDMA
187 MDM_TDSCDMA | MDM_GSM, // 16 - TD-SCDMA and GSM
188 MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 17 - TD-SCDMA, GSM and LTE
189 MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 18 - TD-SCDMA, GSM and WCDMA
190 MDM_LTE | MDM_WCDMA | MDM_TDSCDMA, // 19 - LTE, TD-SCDMA and WCDMA
191 MDM_LTE | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 20 - LTE, TD-SCDMA, GSM, and WCDMA
192 MDM_EVDO | MDM_CDMA | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM, // 21 - TD-SCDMA, CDMA, EVDO, GSM and WCDMA
193 MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 22 - LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA
194 MDM_NR, // 23 - NR 5G only mode
195 MDM_NR | MDM_LTE, // 24 - NR 5G, LTE
196 MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO, // 25 - NR 5G, LTE, CDMA and EvDo
197 MDM_NR | MDM_LTE | MDM_WCDMA | MDM_GSM, // 26 - NR 5G, LTE, GSM and WCDMA
198 MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 27 - NR 5G, LTE, CDMA, EvDo, GSM and WCDMA
199 MDM_NR | MDM_LTE | MDM_WCDMA, // 28 - NR 5G, LTE and WCDMA
200 MDM_NR | MDM_LTE | MDM_TDSCDMA, // 29 - NR 5G, LTE and TDSCDMA
201 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_GSM, // 30 - NR 5G, LTE, TD-SCDMA and GSM
202 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA, // 31 - NR 5G, LTE, TD-SCDMA, WCDMA
203 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA | MDM_GSM, // 32 - NR 5G, LTE, TD-SCDMA, GSM and WCDMA
204 MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM, // 33 - NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA
205 };
206
207 #define GSM (RAF_GSM | RAF_GPRS | RAF_EDGE)
208 #define CDMA (RAF_IS95A | RAF_IS95B | RAF_1xRTT)
209 #define EVDO (RAF_EVDO_0 | RAF_EVDO_A | RAF_EVDO_B | RAF_EHRPD)
210 #define WCDMA (RAF_HSUPA | RAF_HSDPA | RAF_HSPA | RAF_HSPAP | RAF_UMTS)
211 #define LTE (RAF_LTE)
212 #define NR (RAF_NR)
213
214 typedef struct {
215 int bitmap;
216 int type;
217 } NetworkTypeBitmap;
218
219 static NetworkTypeBitmap s_networkMask[] = {
220 {WCDMA | GSM, MDM_GSM | (MDM_WCDMA << 8)}, // 0 - GSM / WCDMA Pref
221 {GSM, MDM_GSM}, // 1 - GSM only
222 {WCDMA, MDM_WCDMA}, // 2 - WCDMA only
223 {WCDMA | GSM, MDM_GSM | MDM_WCDMA}, // 3 - GSM / WCDMA Auto
224 {CDMA | EVDO, MDM_CDMA | MDM_EVDO}, // 4 - CDMA / EvDo Auto
225 {CDMA, MDM_CDMA}, // 5 - CDMA only
226 {EVDO, MDM_EVDO}, // 6 - EvDo only
227 {GSM | WCDMA | CDMA | EVDO, MDM_GSM | MDM_WCDMA | MDM_CDMA | MDM_EVDO}, // 7 - GSM/WCDMA, CDMA, EvDo
228 {LTE | CDMA | EVDO, MDM_LTE | MDM_CDMA | MDM_EVDO}, // 8 - LTE, CDMA and EvDo
229 {LTE | GSM | WCDMA, MDM_LTE | MDM_GSM | MDM_WCDMA}, // 9 - LTE, GSM/WCDMA
230 {LTE | CDMA | EVDO | GSM | WCDMA, MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_GSM | MDM_WCDMA}, // 10 - LTE, CDMA, EvDo, GSM/WCDMA
231 {LTE, MDM_LTE}, // 11 - LTE only
232 {LTE | WCDMA, MDM_LTE | MDM_WCDMA}, // 12 - LTE and WCDMA
233 {RAF_TD_SCDMA, MDM_TDSCDMA}, // 13 - TD-SCDMA only
234 {RAF_TD_SCDMA | WCDMA, MDM_WCDMA | MDM_TDSCDMA}, // 14 - TD-SCDMA and WCDMA
235 {LTE | RAF_TD_SCDMA, MDM_LTE | MDM_TDSCDMA}, // 15 - LTE and TD-SCDMA
236 {RAF_TD_SCDMA | GSM, MDM_TDSCDMA | MDM_GSM}, // 16 - TD-SCDMA and GSM
237 {LTE | RAF_TD_SCDMA | GSM, MDM_LTE | MDM_TDSCDMA | MDM_GSM}, // 17 - TD-SCDMA, GSM and LTE
238 {RAF_TD_SCDMA | GSM | WCDMA, MDM_WCDMA | MDM_TDSCDMA | MDM_GSM}, // 18 - TD-SCDMA, GSM and WCDMA
239 {LTE | RAF_TD_SCDMA | WCDMA, MDM_LTE | MDM_WCDMA | MDM_TDSCDMA}, // 19 - LTE, TD-SCDMA and WCDMA
240 {LTE | RAF_TD_SCDMA | GSM | WCDMA,MDM_LTE | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM}, // 20 - LTE, TD-SCDMA, GSM, and WCDMA
241 {RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA, MDM_EVDO | MDM_CDMA | MDM_WCDMA | MDM_TDSCDMA | MDM_GSM}, // 21 - TD-SCDMA, CDMA, EVDO, GSM and WCDMA
242 {LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA, MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM}, // 22 - LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA
243 {NR, MDM_NR}, // 23 - NR 5G only mode
244 {NR | LTE, MDM_NR | MDM_LTE}, // 24 - NR 5G, LTE
245 {NR | LTE | CDMA | EVDO, MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO}, // 25 - NR 5G, LTE, CDMA and EvDo
246 {NR | LTE | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_WCDMA | MDM_GSM}, // 26 - NR 5G, LTE, GSM and WCDMA
247 {NR | LTE | CDMA | EVDO | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM}, // 27 - NR 5G, LTE, CDMA, EvDo, GSM and WCDMA
248 {NR | LTE | WCDMA, MDM_NR | MDM_LTE | MDM_WCDMA}, // 28 - NR 5G, LTE and WCDMA
249 {NR | LTE | RAF_TD_SCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA}, // 29 - NR 5G, LTE and TDSCDMA
250 {NR | LTE | RAF_TD_SCDMA | GSM, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_GSM}, // 30 - NR 5G, LTE, TD-SCDMA and GSM
251 {NR | LTE | RAF_TD_SCDMA | WCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA}, // 31 - NR 5G, LTE, TD-SCDMA, WCDMA
252 {NR | LTE | RAF_TD_SCDMA | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_WCDMA | MDM_GSM}, // 32 - NR 5G, LTE, TD-SCDMA, GSM and WCDMA
253 {NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA, MDM_NR | MDM_LTE | MDM_TDSCDMA | MDM_CDMA | MDM_EVDO | MDM_WCDMA | MDM_GSM}, // 33 - NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA
254 };
255
is3gpp2(int radioTech)256 static int is3gpp2(int radioTech) {
257 switch (radioTech) {
258 case RADIO_TECH_IS95A:
259 case RADIO_TECH_IS95B:
260 case RADIO_TECH_1xRTT:
261 case RADIO_TECH_EVDO_0:
262 case RADIO_TECH_EVDO_A:
263 case RADIO_TECH_EVDO_B:
264 case RADIO_TECH_EHRPD:
265 return 1;
266 default:
267 return 0;
268 }
269 }
270
271 typedef enum {
272 SIM_ABSENT = 0,
273 SIM_NOT_READY = 1,
274 SIM_READY = 2,
275 SIM_PIN = 3,
276 SIM_PUK = 4,
277 SIM_NETWORK_PERSONALIZATION = 5,
278 RUIM_ABSENT = 6,
279 RUIM_NOT_READY = 7,
280 RUIM_READY = 8,
281 RUIM_PIN = 9,
282 RUIM_PUK = 10,
283 RUIM_NETWORK_PERSONALIZATION = 11,
284 ISIM_ABSENT = 12,
285 ISIM_NOT_READY = 13,
286 ISIM_READY = 14,
287 ISIM_PIN = 15,
288 ISIM_PUK = 16,
289 ISIM_NETWORK_PERSONALIZATION = 17,
290 } SIM_Status;
291
292 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
293 static RIL_RadioState currentState();
294 static int onSupports (int requestCode);
295 static void onCancel (RIL_Token t);
296 static const char *getVersion();
297 static int isRadioOn();
298 static SIM_Status getSIMStatus();
299 static int getCardStatus(RIL_CardStatus_v1_5 **pp_card_status);
300 static void freeCardStatus(RIL_CardStatus_v1_5 *p_card_status);
301 static void onDataCallListChanged(void *param);
302 bool areUiccApplicationsEnabled = true;
303
304 extern const char * requestToString(int request);
305 extern uint8_t hexCharToInt(uint8_t c);
306 extern uint8_t * convertHexStringToBytes(void *response, size_t responseLen);
307
308 /*** Static Variables ***/
309 static const RIL_RadioFunctions s_callbacks = {
310 RIL_VERSION,
311 onRequest,
312 currentState,
313 onSupports,
314 onCancel,
315 getVersion
316 };
317
318 #ifdef RIL_SHLIB
319 static const struct RIL_Env *s_rilenv;
320
321 #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
322 #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
323 #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
324 #endif
325
326 static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
327 static bool isNrDualConnectivityEnabled = true;
328
329 static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
330 static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
331
332 static int s_port = -1;
333 static const char * s_device_path = NULL;
334 static int s_device_socket = 0;
335 static uint32_t s_modem_simulator_port = -1;
336
337 /* trigger change to this with s_state_cond */
338 static int s_closed = 0;
339
340 static int sFD; /* file desc of AT channel */
341 static char sATBuffer[MAX_AT_RESPONSE+1];
342 static char *sATBufferCur = NULL;
343
344 static const struct timeval TIMEVAL_SIMPOLL = {1,0};
345 static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
346 static const struct timeval TIMEVAL_0 = {0,0};
347
348 static int s_ims_registered = 0; // 0==unregistered
349 static int s_ims_services = 1; // & 0x1 == sms over ims supported
350 static int s_ims_format = 1; // FORMAT_3GPP(1) vs FORMAT_3GPP2(2);
351 static int s_ims_cause_retry = 0; // 1==causes sms over ims to temp fail
352 static int s_ims_cause_perm_failure = 0; // 1==causes sms over ims to permanent fail
353 static int s_ims_gsm_retry = 0; // 1==causes sms over gsm to temp fail
354 static int s_ims_gsm_fail = 0; // 1==causes sms over gsm to permanent fail
355
356 #ifdef WORKAROUND_ERRONEOUS_ANSWER
357 // Max number of times we'll try to repoll when we think
358 // we have a AT+CLCC race condition
359 #define REPOLL_CALLS_COUNT_MAX 4
360
361 // Line index that was incoming or waiting at last poll, or -1 for none
362 static int s_incomingOrWaitingLine = -1;
363 // Number of times we've asked for a repoll of AT+CLCC
364 static int s_repollCallsCount = 0;
365 // Should we expect a call to be answered in the next CLCC?
366 static int s_expectAnswer = 0;
367 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
368
369
370 static int s_cell_info_rate_ms = INT_MAX;
371 static int s_mcc = 0;
372 static int s_mnc = 0;
373 static int s_mncLength = 2;
374 static int s_lac = 0;
375 static int s_cid = 0;
376
377 // STK
378 static bool s_stkServiceRunning = false;
379 static char *s_stkUnsolResponse = NULL;
380
381 // Next available handle for keep alive session
382 static int32_t s_session_handle = 1;
383
384 typedef enum {
385 STK_UNSOL_EVENT_UNKNOWN,
386 STK_UNSOL_EVENT_NOTIFY,
387 STK_UNSOL_PROACTIVE_CMD,
388 } StkUnsolEvent;
389
390 typedef enum {
391 STK_RUN_AT = 0x34,
392 STK_SEND_DTMF = 0x14,
393 STK_SEND_SMS = 0x13,
394 STK_SEND_SS = 0x11,
395 STK_SEND_USSD = 0x12,
396 STK_PLAY_TONE = 0x20,
397 STK_OPEN_CHANNEL = 0x40,
398 STK_CLOSE_CHANNEL = 0x41,
399 STK_RECEIVE_DATA = 0x42,
400 STK_SEND_DATA = 0x43,
401 STK_GET_CHANNEL_STATUS = 0x44,
402 STK_REFRESH = 0x01,
403 } StkCmdType;
404
405 enum PDPState {
406 PDP_IDLE,
407 PDP_BUSY,
408 };
409
410 struct PDPInfo {
411 int cid;
412 enum PDPState state;
413 };
414
415 struct PDPInfo s_PDP[] = {
416 {1, PDP_IDLE}, {2, PDP_IDLE}, {3, PDP_IDLE}, {4, PDP_IDLE}, {5, PDP_IDLE}, {6, PDP_IDLE},
417 {7, PDP_IDLE}, {8, PDP_IDLE}, {9, PDP_IDLE}, {10, PDP_IDLE}, {11, PDP_IDLE},
418 };
419
420 static void pollSIMState (void *param);
421 static void setRadioState(RIL_RadioState newState);
422 static void setRadioTechnology(ModemInfo *mdm, int newtech);
423 static int query_ctec(ModemInfo *mdm, int *current, int32_t *preferred);
424 static int parse_technology_response(const char *response, int *current, int32_t *preferred);
425 static int techFromModemType(int mdmtype);
426 static void getIccId(char *iccid, int size);
427
clccStateToRILState(int state,RIL_CallState * p_state)428 static int clccStateToRILState(int state, RIL_CallState *p_state)
429 {
430 switch(state) {
431 case 0: *p_state = RIL_CALL_ACTIVE; return 0;
432 case 1: *p_state = RIL_CALL_HOLDING; return 0;
433 case 2: *p_state = RIL_CALL_DIALING; return 0;
434 case 3: *p_state = RIL_CALL_ALERTING; return 0;
435 case 4: *p_state = RIL_CALL_INCOMING; return 0;
436 case 5: *p_state = RIL_CALL_WAITING; return 0;
437 default: return -1;
438 }
439 }
440
convertBytesToHexString(char * bin_ptr,int length,unsigned char * hex_ptr)441 void convertBytesToHexString(char *bin_ptr, int length, unsigned char *hex_ptr) {
442 int i;
443 unsigned char tmp;
444
445 if (bin_ptr == NULL || hex_ptr == NULL) {
446 return;
447 }
448 for (i = 0; i < length; i++) {
449 tmp = (unsigned char)((bin_ptr[i] & 0xf0) >> 4);
450 if (tmp <= 9) {
451 *hex_ptr = (unsigned char)(tmp + '0');
452 } else {
453 *hex_ptr = (unsigned char)(tmp + 'A' - 10);
454 }
455 hex_ptr++;
456 tmp = (unsigned char)(bin_ptr[i] & 0x0f);
457 if (tmp <= 9) {
458 *hex_ptr = (unsigned char)(tmp + '0');
459 } else {
460 *hex_ptr = (unsigned char)(tmp + 'A' - 10);
461 }
462 hex_ptr++;
463 }
464 }
465
466 /**
467 * Note: directly modified line and has *p_call point directly into
468 * modified line
469 */
callFromCLCCLine(char * line,RIL_Call * p_call)470 static int callFromCLCCLine(char *line, RIL_Call *p_call)
471 {
472 //+CLCC: 1,0,2,0,0,\"+18005551212\",145
473 // index,isMT,state,mode,isMpty(,number,TOA)?
474
475 int err;
476 int state;
477 int mode;
478
479 err = at_tok_start(&line);
480 if (err < 0) goto error;
481
482 err = at_tok_nextint(&line, &(p_call->index));
483 if (err < 0) goto error;
484
485 err = at_tok_nextbool(&line, &(p_call->isMT));
486 if (err < 0) goto error;
487
488 err = at_tok_nextint(&line, &state);
489 if (err < 0) goto error;
490
491 err = clccStateToRILState(state, &(p_call->state));
492 if (err < 0) goto error;
493
494 err = at_tok_nextint(&line, &mode);
495 if (err < 0) goto error;
496
497 p_call->isVoice = (mode == 0);
498
499 err = at_tok_nextbool(&line, &(p_call->isMpty));
500 if (err < 0) goto error;
501
502 if (at_tok_hasmore(&line)) {
503 err = at_tok_nextstr(&line, &(p_call->number));
504
505 /* tolerate null here */
506 if (err < 0) return 0;
507
508 // Some lame implementations return strings
509 // like "NOT AVAILABLE" in the CLCC line
510 if (p_call->number != NULL
511 && 0 == strspn(p_call->number, "+0123456789")
512 ) {
513 p_call->number = NULL;
514 }
515
516 err = at_tok_nextint(&line, &p_call->toa);
517 if (err < 0) goto error;
518 }
519
520 p_call->uusInfo = NULL;
521
522 return 0;
523
524 error:
525 RLOGE("invalid CLCC line\n");
526 return -1;
527 }
528
parseSimResponseLine(char * line,RIL_SIM_IO_Response * response)529 static int parseSimResponseLine(char* line, RIL_SIM_IO_Response* response) {
530 int err;
531
532 err = at_tok_start(&line);
533 if (err < 0) return err;
534 err = at_tok_nextint(&line, &response->sw1);
535 if (err < 0) return err;
536 err = at_tok_nextint(&line, &response->sw2);
537 if (err < 0) return err;
538
539 if (at_tok_hasmore(&line)) {
540 err = at_tok_nextstr(&line, &response->simResponse);
541 if (err < 0) return err;
542 }
543 return 0;
544 }
545
546 #ifdef CUTTLEFISH_ENABLE
set_Ip_Addr(const char * addr,const char * radioInterfaceName)547 static void set_Ip_Addr(const char *addr, const char* radioInterfaceName) {
548 RLOGD("%s %d setting ip addr %s on interface %s", __func__, __LINE__, addr,
549 radioInterfaceName);
550 struct ifreq request;
551 int status = 0;
552 int family = strchr(addr, ':') ? AF_INET6 : AF_INET;
553 int sock = socket(family, SOCK_DGRAM, 0);
554 if (sock == -1) {
555 RLOGE("Failed to open interface socket: %s (%d)", strerror(errno), errno);
556 return;
557 }
558
559 memset(&request, 0, sizeof(request));
560 strncpy(request.ifr_name, radioInterfaceName, sizeof(request.ifr_name));
561 request.ifr_name[sizeof(request.ifr_name) - 1] = '\0';
562
563 int pfxlen = 0;
564 char *myaddr = strdup(addr);
565 char *pch = NULL;
566 pch = strchr(myaddr, '/');
567 if (pch) {
568 *pch = '\0';
569 pfxlen = atoi(++pch);
570 }
571
572 if (family == AF_INET) {
573 struct sockaddr_in *sin = (struct sockaddr_in *)&request.ifr_addr;
574 sin->sin_family = AF_INET;
575 sin->sin_addr.s_addr = inet_addr(myaddr);
576 if (ioctl(sock, SIOCSIFADDR, &request) < 0) {
577 RLOGE("%s: SIOCSIFADDR IPv4 failed.", __func__);
578 }
579 sin->sin_addr.s_addr = htonl(0xFFFFFFFFu << (32 - (pfxlen ?: 32)));
580 if (ioctl(sock, SIOCSIFNETMASK, &request) < 0) {
581 RLOGE("%s: SIOCSIFNETMASK failed.", __func__);
582 }
583 } else {
584 if (ioctl(sock, SIOGIFINDEX, &request) < 0) {
585 RLOGE("%s: SIOCGIFINDEX failed.", __func__);
586 }
587
588 struct in6_ifreq req6 = {
589 // struct in6_addr ifr6_addr;
590 .ifr6_prefixlen = pfxlen ?: 128, // __u32
591 .ifr6_ifindex = request.ifr_ifindex, // int
592 };
593 if (inet_pton(AF_INET6, myaddr, &req6.ifr6_addr) != 1) {
594 RLOGE("%s: inet_pton(AF_INET6, '%s') failed.", __func__, myaddr);
595 }
596
597 if (ioctl(sock, SIOCSIFADDR, &req6) < 0) {
598 RLOGE("%s: SIOCSIFADDR IPv6 failed.", __func__);
599 }
600 }
601
602 close(sock);
603 free(myaddr);
604 RLOGD("%s %d done.", __func__, __LINE__);
605 }
606 #endif
607
608 enum InterfaceState {
609 kInterfaceUp,
610 kInterfaceDown,
611 };
612
setInterfaceState(const char * interfaceName,enum InterfaceState state)613 static RIL_Errno setInterfaceState(const char* interfaceName,
614 enum InterfaceState state) {
615 struct ifreq request;
616 int status = 0;
617 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
618 if (sock == -1) {
619 RLOGE("Failed to open interface socket: %s (%d)",
620 strerror(errno), errno);
621 return RIL_E_GENERIC_FAILURE;
622 }
623
624 memset(&request, 0, sizeof(request));
625 strncpy(request.ifr_name, interfaceName, sizeof(request.ifr_name));
626 request.ifr_name[sizeof(request.ifr_name) - 1] = '\0';
627 status = ioctl(sock, SIOCGIFFLAGS, &request);
628 if (status != 0) {
629 RLOGE("Failed to get interface flags for %s: %s (%d)",
630 interfaceName, strerror(errno), errno);
631 close(sock);
632 return RIL_E_RADIO_NOT_AVAILABLE;
633 }
634
635 bool isUp = (request.ifr_flags & IFF_UP);
636 if ((state == kInterfaceUp && isUp) || (state == kInterfaceDown && !isUp)) {
637 // Interface already in desired state
638 close(sock);
639 return RIL_E_SUCCESS;
640 }
641
642 // Simply toggle the flag since we know it's the opposite of what we want
643 request.ifr_flags ^= IFF_UP;
644
645 status = ioctl(sock, SIOCSIFFLAGS, &request);
646 if (status != 0) {
647 RLOGE("Failed to set interface flags for %s: %s (%d)",
648 interfaceName, strerror(errno), errno);
649 close(sock);
650 return RIL_E_GENERIC_FAILURE;
651 }
652
653 close(sock);
654 return RIL_E_SUCCESS;
655 }
656
657 /** do post-AT+CFUN=1 initialization */
onRadioPowerOn()658 static void onRadioPowerOn()
659 {
660 #ifdef USE_TI_COMMANDS
661 /* Must be after CFUN=1 */
662 /* TI specific -- notifications for CPHS things such */
663 /* as CPHS message waiting indicator */
664
665 at_send_command("AT%CPHS=1", NULL);
666
667 /* TI specific -- enable NITZ unsol notifs */
668 at_send_command("AT%CTZV=1", NULL);
669 #endif
670
671 pollSIMState(NULL);
672 }
673
674 /** do post- SIM ready initialization */
onSIMReady()675 static void onSIMReady()
676 {
677 at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
678 /*
679 * Always send SMS messages directly to the TE
680 *
681 * mode = 1 // discard when link is reserved (link should never be
682 * reserved)
683 * mt = 2 // most messages routed to TE
684 * bm = 2 // new cell BM's routed to TE
685 * ds = 1 // Status reports routed to TE
686 * bfr = 1 // flush buffer
687 */
688 at_send_command("AT+CNMI=1,2,2,1,1", NULL);
689 }
690
requestRadioPower(void * data,size_t datalen __unused,RIL_Token t)691 static void requestRadioPower(void *data, size_t datalen __unused, RIL_Token t)
692 {
693 int onOff;
694
695 int err;
696 ATResponse *p_response = NULL;
697
698 assert (datalen >= sizeof(int *));
699 onOff = ((int *)data)[0];
700
701 if (onOff == 0 && sState != RADIO_STATE_OFF) {
702 err = at_send_command("AT+CFUN=0", &p_response);
703 if (err < 0 || p_response->success == 0) goto error;
704 setRadioState(RADIO_STATE_OFF);
705 } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
706 err = at_send_command("AT+CFUN=1", &p_response);
707 if (err < 0|| p_response->success == 0) {
708 // Some stacks return an error when there is no SIM,
709 // but they really turn the RF portion on
710 // So, if we get an error, let's check to see if it
711 // turned on anyway
712
713 if (isRadioOn() != 1) {
714 goto error;
715 }
716 }
717 setRadioState(RADIO_STATE_ON);
718 }
719
720 at_response_free(p_response);
721 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
722 return;
723 error:
724 at_response_free(p_response);
725 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
726 }
727
requestShutdown(RIL_Token t)728 static void requestShutdown(RIL_Token t)
729 {
730 int onOff;
731
732 ATResponse *p_response = NULL;
733
734 if (sState != RADIO_STATE_OFF) {
735 at_send_command("AT+CFUN=0", &p_response);
736 setRadioState(RADIO_STATE_UNAVAILABLE);
737 }
738
739 at_response_free(p_response);
740 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
741 return;
742 }
743
requestNvResetConfig(void * data,size_t datalen __unused,RIL_Token t)744 static void requestNvResetConfig(void* data, size_t datalen __unused, RIL_Token t) {
745 assert(datalen >= sizeof(int*));
746 int nvConfig = ((int*)data)[0];
747 if (nvConfig == 1 /* ResetNvType::RELOAD */) {
748 setRadioState(RADIO_STATE_OFF);
749 // Wait for FW to process radio off before sending radio on for reboot
750 sleep(5);
751 setRadioState(RADIO_STATE_ON);
752 }
753 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
754 }
755
756 static void requestOrSendDataCallList(int cid, RIL_Token *t);
757
onDataCallListChanged(void * param __unused)758 static void onDataCallListChanged(void *param __unused)
759 {
760 requestOrSendDataCallList(-1, NULL);
761 }
762
requestDataCallList(void * data __unused,size_t datalen __unused,RIL_Token t)763 static void requestDataCallList(void *data __unused, size_t datalen __unused, RIL_Token t)
764 {
765 requestOrSendDataCallList(-1, &t);
766 }
767
768 // Hang up, reject, conference, call waiting
requestCallSelection(void * data __unused,size_t datalen __unused,RIL_Token t,int request)769 static void requestCallSelection(
770 void *data __unused, size_t datalen __unused, RIL_Token t, int request)
771 {
772 // 3GPP 22.030 6.5.5
773 static char hangupWaiting[] = "AT+CHLD=0";
774 static char hangupForeground[] = "AT+CHLD=1";
775 static char switchWaiting[] = "AT+CHLD=2";
776 static char conference[] = "AT+CHLD=3";
777 static char reject[] = "ATH";
778
779 char* atCommand;
780
781 if (getSIMStatus() == SIM_ABSENT) {
782 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
783 return;
784 }
785
786 switch(request) {
787 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
788 // "Releases all held calls or sets User Determined User Busy
789 // (UDUB) for a waiting call."
790 atCommand = hangupWaiting;
791 break;
792 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
793 // "Releases all active calls (if any exist) and accepts
794 // the other (held or waiting) call."
795 atCommand = hangupForeground;
796 break;
797 case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
798 // "Places all active calls (if any exist) on hold and accepts
799 // the other (held or waiting) call."
800 atCommand = switchWaiting;
801 #ifdef WORKAROUND_ERRONEOUS_ANSWER
802 s_expectAnswer = 1;
803 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
804 break;
805 case RIL_REQUEST_CONFERENCE:
806 // "Adds a held call to the conversation"
807 atCommand = conference;
808 break;
809 case RIL_REQUEST_UDUB:
810 // User determined user busy (reject)
811 atCommand = reject;
812 break;
813 default:
814 assert(0);
815 }
816 at_send_command(atCommand, NULL);
817 // Success or failure is ignored by the upper layer here.
818 // It will call GET_CURRENT_CALLS and determine success that way.
819 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
820 }
821
getRadioInterfaceName()822 static const char* getRadioInterfaceName()
823 {
824 if (isInEmulator()) {
825 return EMULATOR_RADIO_INTERFACE;
826 }
827 return PPP_TTY_PATH_ETH0;
828 }
829
requestOrSendDataCallList(int cid,RIL_Token * t)830 static void requestOrSendDataCallList(int cid, RIL_Token *t)
831 {
832 ATResponse *p_response = NULL;
833 ATLine *p_cur = NULL;
834 int err = -1;
835 int n = 0;
836 char *out = NULL;
837 char propValue[PROP_VALUE_MAX] = {0};
838 const char* radioInterfaceName = getRadioInterfaceName();
839
840 err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
841 if (err != 0 || p_response->success == 0) {
842 if (t != NULL)
843 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
844 else
845 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
846 NULL, 0);
847 return;
848 }
849
850 for (p_cur = p_response->p_intermediates; p_cur != NULL;
851 p_cur = p_cur->p_next)
852 n++;
853
854 RIL_Data_Call_Response_v11 *responses = (n == 0) ? NULL :
855 alloca(n * sizeof(RIL_Data_Call_Response_v11));
856
857 int i;
858 for (i = 0; i < n; i++) {
859 responses[i].status = -1;
860 responses[i].suggestedRetryTime = -1;
861 responses[i].cid = -1;
862 responses[i].active = -1;
863 responses[i].type = "";
864 responses[i].ifname = "";
865 responses[i].addresses = "";
866 responses[i].dnses = "";
867 responses[i].gateways = "";
868 responses[i].pcscf = "";
869 responses[i].mtu = 0;
870 }
871
872 RIL_Data_Call_Response_v11 *response = responses;
873 for (p_cur = p_response->p_intermediates; p_cur != NULL;
874 p_cur = p_cur->p_next) {
875 char *line = p_cur->line;
876
877 err = at_tok_start(&line);
878 if (err < 0)
879 goto error;
880
881 err = at_tok_nextint(&line, &response->cid);
882 if (err < 0)
883 goto error;
884
885 err = at_tok_nextint(&line, &response->active);
886 if (err < 0)
887 goto error;
888
889 response++;
890 }
891
892 at_response_free(p_response);
893
894 err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
895 if (err != 0 || p_response->success == 0) {
896 if (t != NULL)
897 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
898 else
899 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
900 NULL, 0);
901 return;
902 }
903
904 for (p_cur = p_response->p_intermediates; p_cur != NULL;
905 p_cur = p_cur->p_next) {
906 char *line = p_cur->line;
907 int ncid;
908
909 err = at_tok_start(&line);
910 if (err < 0)
911 goto error;
912
913 err = at_tok_nextint(&line, &ncid);
914 if (err < 0)
915 goto error;
916
917 if (cid != ncid)
918 continue;
919
920 i = ncid - 1;
921
922 if (i >= n || i < 0)
923 goto error;
924
925 // Assume no error
926 responses[i].status = 0;
927
928 // type
929 err = at_tok_nextstr(&line, &out);
930 if (err < 0)
931 goto error;
932
933 int type_size = strlen(out) + 1;
934 responses[i].type = alloca(type_size);
935 strlcpy(responses[i].type, out, type_size);
936
937 // APN ignored for v5
938 err = at_tok_nextstr(&line, &out);
939 if (err < 0)
940 goto error;
941
942 int ifname_size = strlen(radioInterfaceName) + 1;
943 responses[i].ifname = alloca(ifname_size);
944 strlcpy(responses[i].ifname, radioInterfaceName, ifname_size);
945
946 err = at_tok_nextstr(&line, &out);
947 if (err < 0)
948 goto error;
949
950 int addresses_size = strlen(out) + 1;
951 responses[i].addresses = alloca(addresses_size);
952 strlcpy(responses[i].addresses, out, addresses_size);
953 #ifdef CUTTLEFISH_ENABLE
954 set_Ip_Addr(responses[i].addresses, radioInterfaceName);
955 #endif
956
957 if (isInEmulator()) {
958 /* We are in the emulator - the dns servers are listed
959 * by the following system properties, setup in
960 * /system/etc/init.goldfish.sh:
961 * - vendor.net.eth0.dns1
962 * - vendor.net.eth0.dns2
963 * - vendor.net.eth0.dns3
964 * - vendor.net.eth0.dns4
965 */
966 const int dnslist_sz = 128;
967 char* dnslist = alloca(dnslist_sz);
968 const char* separator = "";
969 int nn;
970
971 dnslist[0] = 0;
972 for (nn = 1; nn <= 4; nn++) {
973 /* Probe vendor.net.eth0.dns<n> */
974 char propName[PROP_NAME_MAX];
975 char propValue[PROP_VALUE_MAX];
976
977 snprintf(propName, sizeof propName, "vendor.net.eth0.dns%d", nn);
978
979 /* Ignore if undefined */
980 if (property_get(propName, propValue, "") <= 0) {
981 continue;
982 }
983
984 /* Append the DNS IP address */
985 strlcat(dnslist, separator, dnslist_sz);
986 strlcat(dnslist, propValue, dnslist_sz);
987 separator = " ";
988 }
989 responses[i].dnses = dnslist;
990
991 if (property_get("vendor.net.eth0.gw", propValue, "") > 0) {
992 responses[i].gateways = propValue;
993 } else {
994 responses[i].gateways = "";
995 }
996 responses[i].mtu = DEFAULT_MTU;
997 } else {
998 /* I don't know where we are, so use the public Google DNS
999 * servers by default and no gateway.
1000 */
1001 responses[i].dnses = "8.8.8.8 8.8.4.4";
1002 responses[i].gateways = "";
1003 }
1004 }
1005
1006 // If cid = -1, return the data call list without processing CGCONTRDP (setupDataCall)
1007 if (cid == -1) {
1008 if (t != NULL)
1009 RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
1010 sizeof(RIL_Data_Call_Response_v11));
1011 else
1012 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, responses,
1013 n * sizeof(RIL_Data_Call_Response_v11));
1014 at_response_free(p_response);
1015 p_response = NULL;
1016 return;
1017 }
1018
1019 at_response_free(p_response);
1020 p_response = NULL;
1021
1022 char cmd[64] = {0};
1023 snprintf(cmd, sizeof(cmd), "AT+CGCONTRDP=%d", cid);
1024 err = at_send_command_singleline(cmd, "+CGCONTRDP:", &p_response);
1025 if (err < 0 || p_response->success == 0) {
1026 goto error;
1027 }
1028
1029 int skip = 0;
1030 char *sskip = NULL;
1031 char *input = p_response->p_intermediates->line;
1032
1033 int ncid = -1;
1034 err = at_tok_start(&input);
1035 if (err < 0) goto error;
1036
1037 err = at_tok_nextint(&input, &ncid); // cid
1038 if (err < 0) goto error;
1039
1040 if (cid != ncid) goto error;
1041
1042 i = ncid - 1;
1043
1044 err = at_tok_nextint(&input, &skip); // bearer_id
1045 if (err < 0) goto error;
1046
1047 err = at_tok_nextstr(&input, &sskip); // apn
1048 if (err < 0) goto error;
1049
1050 err = at_tok_nextstr(&input, &sskip); // local_addr_and_subnet_mask
1051 if (err < 0) goto error;
1052
1053 err = at_tok_nextstr(
1054 &input, (responses) ? &responses[i].gateways : &sskip); // gw_addr
1055 if (err < 0) goto error;
1056
1057 err = at_tok_nextstr(
1058 &input, (responses) ? &responses[i].dnses : &sskip); // dns_prim_addr
1059 if (err < 0) goto error;
1060
1061 size_t response_size = 0;
1062 RIL_Data_Call_Response_v11 *presponse = NULL;
1063 if (responses) {
1064 if (i >= n || i < 0)
1065 goto error;
1066 presponse = &responses[i];
1067 response_size = sizeof(*presponse);
1068 }
1069
1070 if (t != NULL)
1071 RIL_onRequestComplete(*t, RIL_E_SUCCESS,
1072 presponse, response_size);
1073 else
1074 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
1075 responses, n * response_size);
1076
1077 at_response_free(p_response);
1078 return;
1079
1080 error:
1081 if (t != NULL)
1082 RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
1083 else
1084 RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
1085 NULL, 0);
1086 at_response_free(p_response);
1087 }
1088
requestQueryNetworkSelectionMode(void * data __unused,size_t datalen __unused,RIL_Token t)1089 static void requestQueryNetworkSelectionMode(
1090 void *data __unused, size_t datalen __unused, RIL_Token t)
1091 {
1092 int err;
1093 ATResponse *p_response = NULL;
1094 int response = 0;
1095 char *line;
1096
1097 err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
1098
1099 if (err < 0 || p_response->success == 0) {
1100 goto error;
1101 }
1102
1103 line = p_response->p_intermediates->line;
1104
1105 err = at_tok_start(&line);
1106
1107 if (err < 0) {
1108 goto error;
1109 }
1110
1111 err = at_tok_nextint(&line, &response);
1112
1113 if (err < 0) {
1114 goto error;
1115 }
1116
1117 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
1118 at_response_free(p_response);
1119 return;
1120 error:
1121 at_response_free(p_response);
1122 RLOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
1123 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1124 }
1125
sendCallStateChanged(void * param __unused)1126 static void sendCallStateChanged(void *param __unused)
1127 {
1128 RIL_onUnsolicitedResponse (
1129 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
1130 NULL, 0);
1131 }
1132
requestGetCurrentCalls(void * data __unused,size_t datalen __unused,RIL_Token t)1133 static void requestGetCurrentCalls(void *data __unused, size_t datalen __unused, RIL_Token t)
1134 {
1135 int err;
1136 ATResponse *p_response;
1137 ATLine *p_cur;
1138 int countCalls;
1139 int countValidCalls;
1140 RIL_Call *p_calls;
1141 RIL_Call **pp_calls;
1142 int i;
1143 int needRepoll = 0;
1144
1145 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1146 int prevIncomingOrWaitingLine;
1147
1148 prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
1149 s_incomingOrWaitingLine = -1;
1150 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
1151
1152 err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
1153
1154 if (err != 0 || p_response->success == 0) {
1155 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1156 return;
1157 }
1158
1159 /* count the calls */
1160 for (countCalls = 0, p_cur = p_response->p_intermediates
1161 ; p_cur != NULL
1162 ; p_cur = p_cur->p_next
1163 ) {
1164 countCalls++;
1165 }
1166
1167 /* yes, there's an array of pointers and then an array of structures */
1168
1169 pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
1170 p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
1171 memset (p_calls, 0, countCalls * sizeof(RIL_Call));
1172
1173 /* init the pointer array */
1174 for(i = 0; i < countCalls ; i++) {
1175 pp_calls[i] = &(p_calls[i]);
1176 }
1177
1178 for (countValidCalls = 0, p_cur = p_response->p_intermediates
1179 ; p_cur != NULL
1180 ; p_cur = p_cur->p_next
1181 ) {
1182 err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
1183
1184 if (err != 0) {
1185 continue;
1186 }
1187
1188 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1189 if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
1190 || p_calls[countValidCalls].state == RIL_CALL_WAITING
1191 ) {
1192 s_incomingOrWaitingLine = p_calls[countValidCalls].index;
1193 }
1194 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
1195
1196 if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
1197 && p_calls[countValidCalls].state != RIL_CALL_HOLDING
1198 ) {
1199 needRepoll = 1;
1200 }
1201
1202 countValidCalls++;
1203 }
1204
1205 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1206 // Basically:
1207 // A call was incoming or waiting
1208 // Now it's marked as active
1209 // But we never answered it
1210 //
1211 // This is probably a bug, and the call will probably
1212 // disappear from the call list in the next poll
1213 if (prevIncomingOrWaitingLine >= 0
1214 && s_incomingOrWaitingLine < 0
1215 && s_expectAnswer == 0
1216 ) {
1217 for (i = 0; i < countValidCalls ; i++) {
1218
1219 if (p_calls[i].index == prevIncomingOrWaitingLine
1220 && p_calls[i].state == RIL_CALL_ACTIVE
1221 && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
1222 ) {
1223 RLOGI(
1224 "Hit WORKAROUND_ERRONOUS_ANSWER case."
1225 " Repoll count: %d\n", s_repollCallsCount);
1226 s_repollCallsCount++;
1227 goto error;
1228 }
1229 }
1230 }
1231
1232 s_expectAnswer = 0;
1233 s_repollCallsCount = 0;
1234 #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
1235
1236 RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
1237 countValidCalls * sizeof (RIL_Call *));
1238
1239 at_response_free(p_response);
1240
1241 #ifdef POLL_CALL_STATE
1242 if (countValidCalls) { // We don't seem to get a "NO CARRIER" message from
1243 // smd, so we're forced to poll until the call ends.
1244 #else
1245 if (needRepoll) {
1246 #endif
1247 RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
1248 }
1249
1250 return;
1251 #ifdef WORKAROUND_ERRONEOUS_ANSWER
1252 error:
1253 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1254 at_response_free(p_response);
1255 #endif
1256 }
1257
1258 static void requestDial(void *data, size_t datalen __unused, RIL_Token t)
1259 {
1260 RIL_Dial *p_dial;
1261 char *cmd;
1262 const char *clir;
1263
1264 p_dial = (RIL_Dial *)data;
1265
1266 switch (p_dial->clir) {
1267 case 1: clir = "I"; break; /*invocation*/
1268 case 2: clir = "i"; break; /*suppression*/
1269 default:
1270 case 0: clir = ""; break; /*subscription default*/
1271 }
1272
1273 asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
1274
1275 at_send_command(cmd, NULL);
1276
1277 free(cmd);
1278
1279 /* success or failure is ignored by the upper layer here.
1280 it will call GET_CURRENT_CALLS and determine success that way */
1281 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1282 }
1283
1284 static void requestWriteSmsToSim(void *data, size_t datalen __unused, RIL_Token t)
1285 {
1286 RIL_SMS_WriteArgs *p_args;
1287 char *cmd;
1288 int length;
1289 int err;
1290 ATResponse *p_response = NULL;
1291
1292 if (getSIMStatus() == SIM_ABSENT) {
1293 RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
1294 return;
1295 }
1296
1297 p_args = (RIL_SMS_WriteArgs *)data;
1298
1299 length = strlen(p_args->pdu)/2;
1300 asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
1301
1302 err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
1303
1304 if (err != 0 || p_response->success == 0) goto error;
1305
1306 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1307 at_response_free(p_response);
1308
1309 return;
1310 error:
1311 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1312 at_response_free(p_response);
1313 }
1314
1315 static void requestHangup(void *data, size_t datalen __unused, RIL_Token t)
1316 {
1317 int *p_line;
1318
1319 char *cmd;
1320
1321 if (getSIMStatus() == SIM_ABSENT) {
1322 RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
1323 return;
1324 }
1325 p_line = (int *)data;
1326
1327 // 3GPP 22.030 6.5.5
1328 // "Releases a specific active call X"
1329 asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
1330
1331 at_send_command(cmd, NULL);
1332
1333 free(cmd);
1334
1335 /* success or failure is ignored by the upper layer here.
1336 it will call GET_CURRENT_CALLS and determine success that way */
1337 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1338 }
1339
1340 static void requestSignalStrength(void *data __unused, size_t datalen __unused, RIL_Token t)
1341 {
1342 ATResponse *p_response = NULL;
1343 int err;
1344 char *line;
1345 int count = 0;
1346 // Accept a response that is at least v6, and up to v12
1347 int minNumOfElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
1348 int maxNumOfElements=sizeof(RIL_SignalStrength_v12)/sizeof(int);
1349 int response[maxNumOfElements];
1350
1351 memset(response, 0, sizeof(response));
1352
1353 // TODO(b/206814247): Rename AT+CSQ command.
1354 err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
1355
1356 if (err < 0 || p_response->success == 0) {
1357 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1358 goto error;
1359 }
1360
1361 line = p_response->p_intermediates->line;
1362
1363 err = at_tok_start(&line);
1364 if (err < 0) goto error;
1365
1366 for (count = 0; count < maxNumOfElements; count++) {
1367 err = at_tok_nextint(&line, &(response[count]));
1368 if (err < 0 && count < minNumOfElements) goto error;
1369 }
1370
1371 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
1372
1373 at_response_free(p_response);
1374 return;
1375
1376 error:
1377 RLOGE("requestSignalStrength must never return an error when radio is on");
1378 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1379 at_response_free(p_response);
1380 }
1381
1382 /**
1383 * networkModePossible. Decides whether the network mode is appropriate for the
1384 * specified modem
1385 */
1386 static int networkModePossible(ModemInfo *mdm, int nm)
1387 {
1388 const int asize = sizeof(net2modem) / sizeof(net2modem[0]);
1389 if (nm >= asize || nm < 0) {
1390 RLOGW("%s %d: invalid net2modem index: %d", __func__, __LINE__, nm);
1391 return 0;
1392 }
1393 if ((net2modem[nm] & mdm->supportedTechs) == net2modem[nm]) {
1394 return 1;
1395 }
1396 return 0;
1397 }
1398
1399 int getPreferredFromBitmap(int value, int *index) {
1400 for (unsigned int i = 0; i < sizeof(s_networkMask) / sizeof(NetworkTypeBitmap); i++) {
1401 if (s_networkMask[i].bitmap == value) {
1402 if (index) *index = i;
1403 return s_networkMask[i].type;
1404 }
1405 }
1406 // set default value here, since there is no match found
1407 // ref.
1408 //{LTE | GSM | WCDMA, MDM_LTE | MDM_GSM | MDM_WCDMA}, // 9 - LTE, GSM/WCDMA
1409 //
1410 const int DEFAULT_PREFERRED_INDEX = 9;
1411 const int DEFAULT_PREFERRED_BITMAP = MDM_LTE | MDM_GSM | MDM_WCDMA;
1412 assert(s_networkMask[DEFAULT_PREFERRED_INDEX] == DEFAULT_PREFERRED_BITMAP);
1413 if (index) {
1414 *index = DEFAULT_PREFERRED_INDEX;
1415 }
1416 RLOGD("getPreferredFromBitmap %d not match", value);
1417 return DEFAULT_PREFERRED_BITMAP;
1418 }
1419
1420 unsigned getBitmapFromPreferred(int value) {
1421 for (unsigned int i = 0; i < sizeof(s_networkMask) / sizeof(NetworkTypeBitmap); i++) {
1422 if (s_networkMask[i].type == value) {
1423 return s_networkMask[i].bitmap;
1424 }
1425 }
1426 RLOGD("getBitmapFromPreferred %d not match", value);
1427 return LTE | GSM | WCDMA;
1428 }
1429
1430 static void requestSetPreferredNetworkType(int request, void *data,
1431 size_t datalen __unused, RIL_Token t )
1432 {
1433 ATResponse *p_response = NULL;
1434 char *cmd = NULL;
1435 int value = *(int *)data;
1436 int index = value;
1437 int current, old;
1438 int err;
1439 int32_t preferred;
1440
1441 if (request == RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE) {
1442 preferred = net2pmask[value];
1443 } else {
1444 preferred = getPreferredFromBitmap(value, &index);
1445 }
1446 RLOGD("requestSetPreferredNetworkType: current: %x. New: %x", PREFERRED_NETWORK(sMdmInfo), preferred);
1447
1448 if (!networkModePossible(sMdmInfo, index)) {
1449 RIL_onRequestComplete(t, RIL_E_MODE_NOT_SUPPORTED, NULL, 0);
1450 return;
1451 }
1452
1453 if (query_ctec(sMdmInfo, ¤t, NULL) < 0) {
1454 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1455 return;
1456 }
1457 old = PREFERRED_NETWORK(sMdmInfo);
1458 RLOGD("old != preferred: %d", old != preferred);
1459 if (old != preferred) {
1460 asprintf(&cmd, "AT+CTEC=%d,\"%x\"", current, preferred);
1461 RLOGD("Sending command: <%s>", cmd);
1462 err = at_send_command_singleline(cmd, "+CTEC:", &p_response);
1463 free(cmd);
1464 if (err || !p_response->success) {
1465 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1466 return;
1467 }
1468 PREFERRED_NETWORK(sMdmInfo) = value;
1469 if (!strstr( p_response->p_intermediates->line, "DONE") ) {
1470 int current;
1471 int res = parse_technology_response(p_response->p_intermediates->line, ¤t, NULL);
1472 switch (res) {
1473 case -1: // Error or unable to parse
1474 break;
1475 case 1: // Only able to parse current
1476 case 0: // Both current and preferred were parsed
1477 setRadioTechnology(sMdmInfo, current);
1478 break;
1479 }
1480 }
1481 }
1482 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1483 }
1484
1485 static void requestGetPreferredNetworkType(int request __unused, void *data __unused,
1486 size_t datalen __unused, RIL_Token t)
1487 {
1488 int preferred;
1489 unsigned i;
1490
1491 switch ( query_ctec(sMdmInfo, NULL, &preferred) ) {
1492 case -1: // Error or unable to parse
1493 case 1: // Only able to parse current
1494 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1495 break;
1496 case 0: // Both current and preferred were parsed
1497 for ( i = 0 ; i < sizeof(net2pmask) / sizeof(int32_t) ; i++ ) {
1498 if (preferred == net2pmask[i]) {
1499 goto done;
1500 }
1501 }
1502 RLOGE("Unknown preferred mode received from modem: %d", preferred);
1503 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1504 return;
1505 }
1506 done:
1507 if (request == RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP ||
1508 request == RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP) {
1509 i = getBitmapFromPreferred(preferred);
1510 }
1511 RIL_onRequestComplete(t, RIL_E_SUCCESS, &i, sizeof(i));
1512 }
1513
1514 static void requestGetCarrierRestrictions(void* data, size_t datalen, RIL_Token t) {
1515 RIL_UNUSED_PARM(datalen);
1516 RIL_UNUSED_PARM(data);
1517
1518 // Fixed values. TODO: query modem
1519 RIL_Carrier allowed_carriers = {
1520 "123", // mcc
1521 "456", // mnc
1522 RIL_MATCH_ALL, // match_type
1523 "", // match_data
1524 };
1525
1526 RIL_Carrier excluded_carriers;
1527
1528 RIL_CarrierRestrictionsWithPriority restrictions = {
1529 1, // len_allowed_carriers
1530 0, // len_excluded_carriers
1531 &allowed_carriers, // allowed_carriers
1532 &excluded_carriers, // excluded_carriers
1533 1, // allowedCarriersPrioritized
1534 NO_MULTISIM_POLICY // multiSimPolicy
1535 };
1536
1537 RIL_onRequestComplete(t, RIL_E_SUCCESS, &restrictions, sizeof(restrictions));
1538 }
1539
1540 static void requestCdmaPrlVersion(int request __unused, void *data __unused,
1541 size_t datalen __unused, RIL_Token t)
1542 {
1543 int err;
1544 char * responseStr;
1545 ATResponse *p_response = NULL;
1546 const char *cmd;
1547 char *line;
1548
1549 err = at_send_command_singleline("AT+WPRL?", "+WPRL:", &p_response);
1550 if (err < 0 || !p_response->success) goto error;
1551 line = p_response->p_intermediates->line;
1552 err = at_tok_start(&line);
1553 if (err < 0) goto error;
1554 err = at_tok_nextstr(&line, &responseStr);
1555 if (err < 0 || !responseStr) goto error;
1556 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, strlen(responseStr));
1557 at_response_free(p_response);
1558 return;
1559 error:
1560 at_response_free(p_response);
1561 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1562 }
1563
1564 static void requestCdmaBaseBandVersion(int request __unused, void *data __unused,
1565 size_t datalen __unused, RIL_Token t)
1566 {
1567 int err;
1568 char * responseStr;
1569 ATResponse *p_response = NULL;
1570 const char *cmd;
1571 const char *prefix;
1572 char *line, *p;
1573 int commas;
1574 int skip;
1575 int count = 4;
1576
1577 // Fixed values. TODO: query modem
1578 responseStr = strdup("1.0.0.0");
1579 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, sizeof(responseStr));
1580 free(responseStr);
1581 }
1582
1583 static void requestDeviceIdentity(int request __unused, void *data __unused,
1584 size_t datalen __unused, RIL_Token t)
1585 {
1586 int err;
1587 int response[4];
1588 char * responseStr[4];
1589 ATResponse *p_response = NULL;
1590 const char *cmd;
1591 const char *prefix;
1592 char *line, *p;
1593 int commas;
1594 int skip;
1595 int count = 4;
1596 char meid[14] = {0};
1597
1598 err = at_send_command_numeric("AT+CGSN", &p_response);
1599 if (err < 0 || p_response->success == 0) {
1600 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1601 return;
1602 }
1603
1604 responseStr[0] = p_response->p_intermediates->line;
1605 responseStr[1] = "";
1606 responseStr[2] = "77777777";
1607 responseStr[3] = ""; // default empty for non-CDMA
1608
1609 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
1610 strncpy(meid, responseStr[0], sizeof(meid));
1611 responseStr[3] = meid;
1612 }
1613
1614 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
1615 at_response_free(p_response);
1616 }
1617
1618 static void requestCdmaGetSubscriptionSource(int request __unused, void *data,
1619 size_t datalen __unused, RIL_Token t)
1620 {
1621 int err;
1622 int *ss = (int *)data;
1623 ATResponse *p_response = NULL;
1624 char *cmd = NULL;
1625 char *line = NULL;
1626 int response;
1627
1628 asprintf(&cmd, "AT+CCSS?");
1629 if (!cmd) goto error;
1630
1631 err = at_send_command_singleline(cmd, "+CCSS:", &p_response);
1632 if (err < 0 || !p_response->success)
1633 goto error;
1634
1635 line = p_response->p_intermediates->line;
1636 err = at_tok_start(&line);
1637 if (err < 0) goto error;
1638
1639 err = at_tok_nextint(&line, &response);
1640 free(cmd);
1641 cmd = NULL;
1642
1643 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
1644
1645 return;
1646 error:
1647 free(cmd);
1648 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1649 }
1650
1651 static void requestCdmaSetSubscriptionSource(int request __unused, void *data,
1652 size_t datalen, RIL_Token t)
1653 {
1654 int err;
1655 int *ss = (int *)data;
1656 ATResponse *p_response = NULL;
1657 char *cmd = NULL;
1658
1659 if (!ss || !datalen) {
1660 RLOGE("RIL_REQUEST_CDMA_SET_SUBSCRIPTION without data!");
1661 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1662 return;
1663 }
1664 asprintf(&cmd, "AT+CCSS=%d", ss[0]);
1665 if (!cmd) goto error;
1666
1667 err = at_send_command(cmd, &p_response);
1668 if (err < 0 || !p_response->success)
1669 goto error;
1670 free(cmd);
1671 cmd = NULL;
1672
1673 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1674
1675 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, ss, sizeof(ss[0]));
1676
1677 return;
1678 error:
1679 free(cmd);
1680 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1681 }
1682
1683 static void requestCdmaSubscription(int request __unused, void *data __unused,
1684 size_t datalen __unused, RIL_Token t)
1685 {
1686 int err;
1687 int response[5];
1688 char * responseStr[5];
1689 ATResponse *p_response = NULL;
1690 const char *cmd;
1691 const char *prefix;
1692 char *line, *p;
1693 int commas;
1694 int skip;
1695 int count = 5;
1696
1697 // Fixed values. TODO: Query modem
1698 responseStr[0] = "8587777777"; // MDN
1699 responseStr[1] = "1"; // SID
1700 responseStr[2] = "1"; // NID
1701 responseStr[3] = "8587777777"; // MIN
1702 responseStr[4] = "1"; // PRL Version
1703 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
1704 }
1705
1706 static void requestCdmaGetRoamingPreference(int request __unused, void *data __unused,
1707 size_t datalen __unused, RIL_Token t)
1708 {
1709 int roaming_pref = -1;
1710 ATResponse *p_response = NULL;
1711 char *line;
1712 int res;
1713
1714 res = at_send_command_singleline("AT+WRMP?", "+WRMP:", &p_response);
1715 if (res < 0 || !p_response->success) {
1716 goto error;
1717 }
1718 line = p_response->p_intermediates->line;
1719
1720 res = at_tok_start(&line);
1721 if (res < 0) goto error;
1722
1723 res = at_tok_nextint(&line, &roaming_pref);
1724 if (res < 0) goto error;
1725
1726 RIL_onRequestComplete(t, RIL_E_SUCCESS, &roaming_pref, sizeof(roaming_pref));
1727 return;
1728 error:
1729 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1730 }
1731
1732 static void requestCdmaSetRoamingPreference(int request __unused, void *data,
1733 size_t datalen __unused, RIL_Token t)
1734 {
1735 int *pref = (int *)data;
1736 ATResponse *p_response = NULL;
1737 char *line;
1738 int res;
1739 char *cmd = NULL;
1740
1741 asprintf(&cmd, "AT+WRMP=%d", *pref);
1742 if (cmd == NULL) goto error;
1743
1744 res = at_send_command(cmd, &p_response);
1745 if (res < 0 || !p_response->success)
1746 goto error;
1747
1748 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
1749 free(cmd);
1750 return;
1751 error:
1752 free(cmd);
1753 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
1754 }
1755
1756 static int parseRegistrationState(char *str, int *type, int *items, int **response)
1757 {
1758 int err;
1759 char *line = str, *p;
1760 int *resp = NULL;
1761 int skip;
1762 int commas;
1763
1764 s_lac = -1;
1765 s_cid = -1;
1766
1767 RLOGD("parseRegistrationState. Parsing: %s",str);
1768 err = at_tok_start(&line);
1769 if (err < 0) goto error;
1770
1771 /* Ok you have to be careful here
1772 * The solicited version of the CREG response is
1773 * +CREG: n, stat, [lac, cid]
1774 * and the unsolicited version is
1775 * +CREG: stat, [lac, cid]
1776 * The <n> parameter is basically "is unsolicited creg on?"
1777 * which it should always be
1778 *
1779 * Now we should normally get the solicited version here,
1780 * but the unsolicited version could have snuck in
1781 * so we have to handle both
1782 *
1783 * Also since the LAC and CID are only reported when registered,
1784 * we can have 1, 2, 3, or 4 arguments here
1785 *
1786 * finally, a +CGREG: answer may have a fifth value that corresponds
1787 * to the network type, as in;
1788 *
1789 * +CGREG: n, stat [,lac, cid [,networkType]]
1790 */
1791
1792 /* count number of commas */
1793 commas = 0;
1794 for (p = line ; *p != '\0' ;p++) {
1795 if (*p == ',') commas++;
1796 }
1797
1798 resp = (int *)calloc(commas + 1, sizeof(int));
1799 if (!resp) goto error;
1800 switch (commas) {
1801 case 0: /* +CREG: <stat> */
1802 err = at_tok_nextint(&line, &resp[0]);
1803 if (err < 0) goto error;
1804 break;
1805
1806 case 1: /* +CREG: <n>, <stat> */
1807 err = at_tok_nextint(&line, &skip);
1808 if (err < 0) goto error;
1809 err = at_tok_nextint(&line, &resp[0]);
1810 if (err < 0) goto error;
1811 break;
1812
1813 case 2: /* +CREG: <stat>, <lac>, <cid> */
1814 err = at_tok_nextint(&line, &resp[0]);
1815 if (err < 0) goto error;
1816 err = at_tok_nexthexint(&line, &resp[1]);
1817 if (err < 0) goto error;
1818 err = at_tok_nexthexint(&line, &resp[2]);
1819 if (err < 0) goto error;
1820 break;
1821 case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
1822 err = at_tok_nextint(&line, &skip);
1823 if (err < 0) goto error;
1824 err = at_tok_nextint(&line, &resp[0]);
1825 if (err < 0) goto error;
1826 err = at_tok_nexthexint(&line, &resp[1]);
1827 if (err < 0) goto error;
1828 err = at_tok_nexthexint(&line, &resp[2]);
1829 if (err < 0) goto error;
1830 break;
1831 /* special case for CGREG, there is a fourth parameter
1832 * that is the network type (unknown/gprs/edge/umts)
1833 */
1834 case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
1835 err = at_tok_nextint(&line, &skip);
1836 if (err < 0) goto error;
1837 err = at_tok_nextint(&line, &resp[0]);
1838 if (err < 0) goto error;
1839 err = at_tok_nexthexint(&line, &resp[1]);
1840 if (err < 0) goto error;
1841 err = at_tok_nexthexint(&line, &resp[2]);
1842 if (err < 0) goto error;
1843 err = at_tok_nextint(&line, &resp[3]);
1844 if (err < 0) goto error;
1845 break;
1846 default:
1847 goto error;
1848 }
1849
1850 if (commas >= 2) {
1851 s_lac = resp[1];
1852 s_cid = resp[2];
1853 }
1854
1855 if (response)
1856 *response = resp;
1857 if (items)
1858 *items = commas + 1;
1859 if (type)
1860 *type = techFromModemType(TECH(sMdmInfo));
1861 return 0;
1862 error:
1863 free(resp);
1864 return -1;
1865 }
1866
1867 static int mapNetworkRegistrationResponse(int in_response) {
1868 int out_response = 0;
1869
1870 switch (in_response) {
1871 case 0:
1872 out_response = RADIO_TECH_GPRS; /* GPRS */
1873 break;
1874 case 3:
1875 out_response = RADIO_TECH_EDGE; /* EDGE */
1876 break;
1877 case 2:
1878 out_response = RADIO_TECH_UMTS; /* TD */
1879 break;
1880 case 4:
1881 out_response = RADIO_TECH_HSDPA; /* HSDPA */
1882 break;
1883 case 5:
1884 out_response = RADIO_TECH_HSUPA; /* HSUPA */
1885 break;
1886 case 6:
1887 out_response = RADIO_TECH_HSPA; /* HSPA */
1888 break;
1889 case 15:
1890 out_response = RADIO_TECH_HSPAP; /* HSPA+ */
1891 break;
1892 case 7:
1893 out_response = RADIO_TECH_LTE; /* LTE */
1894 break;
1895 case 16:
1896 out_response = RADIO_TECH_LTE_CA; /* LTE_CA */
1897 break;
1898 case 11: // NR connected to a 5GCN
1899 case 12: // NG-RAN
1900 case 13: // E-UTRA-NR dual connectivity
1901 out_response = RADIO_TECH_NR; /* NR */
1902 break;
1903 default:
1904 out_response = RADIO_TECH_UNKNOWN; /* UNKNOWN */
1905 break;
1906 }
1907 return out_response;
1908 }
1909
1910 #define REG_STATE_LEN 18
1911 #define REG_DATA_STATE_LEN 14
1912 static void requestRegistrationState(int request, void *data __unused,
1913 size_t datalen __unused, RIL_Token t)
1914 {
1915 int err;
1916 int *registration;
1917 char **responseStr = NULL;
1918 ATResponse *p_response = NULL;
1919 const char *cmd;
1920 const char *prefix;
1921 char *line;
1922 int i = 0, j, numElements = 0;
1923 int count = 3;
1924 int type, startfrom;
1925
1926 RLOGD("requestRegistrationState");
1927 if (request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
1928 cmd = "AT+CREG?";
1929 prefix = "+CREG:";
1930 numElements = REG_STATE_LEN;
1931 } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
1932 cmd = "AT+CGREG?";
1933 prefix = "+CGREG:";
1934 numElements = REG_DATA_STATE_LEN;
1935 if (TECH_BIT(sMdmInfo) == MDM_LTE) {
1936 cmd = "AT+CEREG?";
1937 prefix = "+CEREG:";
1938 }
1939 } else {
1940 assert(0);
1941 goto error;
1942 }
1943
1944 err = at_send_command_singleline(cmd, prefix, &p_response);
1945
1946 if (err < 0 || !p_response->success) goto error;
1947
1948 line = p_response->p_intermediates->line;
1949
1950 if (parseRegistrationState(line, &type, &count, ®istration)) goto error;
1951
1952 responseStr = malloc(numElements * sizeof(char *));
1953 if (!responseStr) goto error;
1954 memset(responseStr, 0, numElements * sizeof(char *));
1955 /**
1956 * The first '4' bytes for both registration states remain the same.
1957 * But if the request is 'DATA_REGISTRATION_STATE',
1958 * the 5th and 6th byte(s) are optional.
1959 */
1960 if (is3gpp2(type) == 1) {
1961 RLOGD("registration state type: 3GPP2");
1962 // TODO: Query modem
1963 startfrom = 3;
1964 if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
1965 asprintf(&responseStr[3], "8"); // EvDo revA
1966 asprintf(&responseStr[4], "1"); // BSID
1967 asprintf(&responseStr[5], "123"); // Latitude
1968 asprintf(&responseStr[6], "222"); // Longitude
1969 asprintf(&responseStr[7], "0"); // CSS Indicator
1970 asprintf(&responseStr[8], "4"); // SID
1971 asprintf(&responseStr[9], "65535"); // NID
1972 asprintf(&responseStr[10], "0"); // Roaming indicator
1973 asprintf(&responseStr[11], "1"); // System is in PRL
1974 asprintf(&responseStr[12], "0"); // Default Roaming indicator
1975 asprintf(&responseStr[13], "0"); // Reason for denial
1976 asprintf(&responseStr[14], "0"); // Primary Scrambling Code of Current cell
1977 } else if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
1978 asprintf(&responseStr[3], "8"); // Available data radio technology
1979 }
1980 } else { // type == RADIO_TECH_3GPP
1981 RLOGD("registration state type: 3GPP");
1982 startfrom = 0;
1983 if (count > 1) {
1984 asprintf(&responseStr[1], "%x", registration[1]);
1985 }
1986 if (count > 2) {
1987 asprintf(&responseStr[2], "%x", registration[2]);
1988 }
1989 if (count > 3) {
1990 asprintf(&responseStr[3], "%d", mapNetworkRegistrationResponse(registration[3]));
1991 }
1992 }
1993 asprintf(&responseStr[0], "%d", registration[0]);
1994
1995 /**
1996 * Optional bytes for DATA_REGISTRATION_STATE request
1997 * 4th byte : Registration denial code
1998 * 5th byte : The max. number of simultaneous Data Calls
1999 */
2000 if (request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
2001 // asprintf(&responseStr[4], "3");
2002 // asprintf(&responseStr[5], "1");
2003 asprintf(&responseStr[11], "%d", s_mcc);
2004 asprintf(&responseStr[12], "%d", s_mnc);
2005 if (s_mncLength == 2) {
2006 asprintf(&responseStr[13], "%03d%02d", s_mcc, s_mnc);
2007 } else {
2008 asprintf(&responseStr[13], "%03d%03d", s_mcc, s_mnc);
2009 }
2010 } else { // Voice
2011 asprintf(&responseStr[15], "%d", s_mcc);
2012 asprintf(&responseStr[16], "%d", s_mnc);
2013 if (s_mncLength == 2) {
2014 asprintf(&responseStr[17], "%03d%02d", s_mcc, s_mnc);
2015 } else {
2016 asprintf(&responseStr[17], "%03d%03d", s_mcc, s_mnc);
2017 }
2018 }
2019
2020
2021 for (j = startfrom; j < numElements; j++) {
2022 if (!responseStr[i]) goto error;
2023 }
2024 free(registration);
2025 registration = NULL;
2026 RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, numElements*sizeof(responseStr));
2027 for (j = 0; j < numElements; j++ ) {
2028 free(responseStr[j]);
2029 responseStr[j] = NULL;
2030 }
2031 free(responseStr);
2032 responseStr = NULL;
2033 at_response_free(p_response);
2034
2035 return;
2036 error:
2037 if (responseStr) {
2038 for (j = 0; j < numElements; j++) {
2039 free(responseStr[j]);
2040 responseStr[j] = NULL;
2041 }
2042 free(responseStr);
2043 responseStr = NULL;
2044 }
2045 RLOGE("requestRegistrationState must never return an error when radio is on");
2046 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2047 at_response_free(p_response);
2048 }
2049
2050 static void requestOperator(void *data __unused, size_t datalen __unused, RIL_Token t)
2051 {
2052 int err;
2053 int i;
2054 int skip;
2055 ATLine *p_cur;
2056 char *response[3];
2057
2058 memset(response, 0, sizeof(response));
2059
2060 ATResponse *p_response = NULL;
2061
2062 err = at_send_command_multiline(
2063 "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
2064 "+COPS:", &p_response);
2065
2066 /* we expect 3 lines here:
2067 * +COPS: 0,0,"T - Mobile"
2068 * +COPS: 0,1,"TMO"
2069 * +COPS: 0,2,"310170"
2070 */
2071
2072 if (err != 0) goto error;
2073
2074 for (i = 0, p_cur = p_response->p_intermediates
2075 ; p_cur != NULL
2076 ; p_cur = p_cur->p_next, i++
2077 ) {
2078 char *line = p_cur->line;
2079
2080 err = at_tok_start(&line);
2081 if (err < 0) goto error;
2082
2083 err = at_tok_nextint(&line, &skip);
2084 if (err < 0) goto error;
2085
2086 // If we're unregistered, we may just get
2087 // a "+COPS: 0" response
2088 if (!at_tok_hasmore(&line)) {
2089 response[i] = NULL;
2090 continue;
2091 }
2092
2093 err = at_tok_nextint(&line, &skip);
2094 if (err < 0) goto error;
2095
2096 // a "+COPS: 0, n" response is also possible
2097 if (!at_tok_hasmore(&line)) {
2098 response[i] = NULL;
2099 continue;
2100 }
2101
2102 err = at_tok_nextstr(&line, &(response[i]));
2103 if (err < 0) goto error;
2104 // Simple assumption that mcc and mnc are 3 digits each
2105 int length = strlen(response[i]);
2106 if (length == 6) {
2107 s_mncLength = 3;
2108 if (sscanf(response[i], "%3d%3d", &s_mcc, &s_mnc) != 2) {
2109 RLOGE("requestOperator expected mccmnc to be 6 decimal digits");
2110 }
2111 } else if (length == 5) {
2112 s_mncLength = 2;
2113 if (sscanf(response[i], "%3d%2d", &s_mcc, &s_mnc) != 2) {
2114 RLOGE("requestOperator expected mccmnc to be 5 decimal digits");
2115 }
2116 }
2117 }
2118
2119 if (i != 3) {
2120 /* expect 3 lines exactly */
2121 goto error;
2122 }
2123
2124 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
2125 at_response_free(p_response);
2126
2127 return;
2128 error:
2129 RLOGE("requestOperator must not return error when radio is on");
2130 s_mncLength = 0;
2131 s_mcc = 0;
2132 s_mnc = 0;
2133 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2134 at_response_free(p_response);
2135 }
2136
2137 static void requestCdmaSendSMS(void *data, size_t datalen, RIL_Token t)
2138 {
2139 int err = 1; // Set to go to error:
2140 RIL_SMS_Response response;
2141 RIL_CDMA_SMS_Message* rcsm;
2142
2143 memset(&response, 0, sizeof(response));
2144
2145 if (getSIMStatus() == SIM_ABSENT) {
2146 RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
2147 return;
2148 }
2149
2150 RLOGD("requestCdmaSendSMS datalen=%zu, sizeof(RIL_CDMA_SMS_Message)=%zu",
2151 datalen, sizeof(RIL_CDMA_SMS_Message));
2152
2153 // verify data content to test marshalling/unmarshalling:
2154 rcsm = (RIL_CDMA_SMS_Message*)data;
2155 RLOGD("TeleserviceID=%d, bIsServicePresent=%d, \
2156 uServicecategory=%d, sAddress.digit_mode=%d, \
2157 sAddress.Number_mode=%d, sAddress.number_type=%d, ",
2158 rcsm->uTeleserviceID, rcsm->bIsServicePresent,
2159 rcsm->uServicecategory,rcsm->sAddress.digit_mode,
2160 rcsm->sAddress.number_mode,rcsm->sAddress.number_type);
2161
2162 if (err != 0) goto error;
2163
2164 // Cdma Send SMS implementation will go here:
2165 // But it is not implemented yet.
2166
2167 response.messageRef = 1;
2168 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
2169 return;
2170
2171 error:
2172 // Cdma Send SMS will always cause send retry error.
2173 response.messageRef = -1;
2174 RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response, sizeof(response));
2175 }
2176
2177 static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
2178 {
2179 int err;
2180 const char *smsc;
2181 const char *pdu;
2182 int tpLayerLength;
2183 char *cmd1, *cmd2;
2184 RIL_SMS_Response response;
2185 ATResponse *p_response = NULL;
2186
2187 if (getSIMStatus() == SIM_ABSENT) {
2188 RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
2189 return;
2190 }
2191
2192 memset(&response, 0, sizeof(response));
2193 RLOGD("requestSendSMS datalen =%zu", datalen);
2194
2195 if (s_ims_gsm_fail != 0) goto error;
2196 if (s_ims_gsm_retry != 0) goto error2;
2197
2198 smsc = ((const char **)data)[0];
2199 pdu = ((const char **)data)[1];
2200
2201 tpLayerLength = strlen(pdu)/2;
2202
2203 // "NULL for default SMSC"
2204 if (smsc == NULL) {
2205 smsc= "00";
2206 }
2207
2208 asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
2209 asprintf(&cmd2, "%s%s", smsc, pdu);
2210
2211 err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
2212
2213 free(cmd1);
2214 free(cmd2);
2215
2216 if (err != 0 || p_response->success == 0) goto error;
2217
2218 int messageRef = 1;
2219 char *line = p_response->p_intermediates->line;
2220
2221 err = at_tok_start(&line);
2222 if (err < 0) goto error;
2223
2224 err = at_tok_nextint(&line, &messageRef);
2225 if (err < 0) goto error;
2226
2227 /* FIXME fill in ackPDU */
2228 response.messageRef = messageRef;
2229 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
2230 at_response_free(p_response);
2231
2232 return;
2233 error:
2234 response.messageRef = -2;
2235 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, &response, sizeof(response));
2236 at_response_free(p_response);
2237 return;
2238 error2:
2239 // send retry error.
2240 response.messageRef = -1;
2241 RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response, sizeof(response));
2242 at_response_free(p_response);
2243 return;
2244 }
2245
2246 static void requestImsSendSMS(void *data, size_t datalen, RIL_Token t)
2247 {
2248 RIL_IMS_SMS_Message *p_args;
2249 RIL_SMS_Response response;
2250
2251 memset(&response, 0, sizeof(response));
2252
2253 RLOGD("requestImsSendSMS: datalen=%zu, "
2254 "registered=%d, service=%d, format=%d, ims_perm_fail=%d, "
2255 "ims_retry=%d, gsm_fail=%d, gsm_retry=%d",
2256 datalen, s_ims_registered, s_ims_services, s_ims_format,
2257 s_ims_cause_perm_failure, s_ims_cause_retry, s_ims_gsm_fail,
2258 s_ims_gsm_retry);
2259
2260 // figure out if this is gsm/cdma format
2261 // then route it to requestSendSMS vs requestCdmaSendSMS respectively
2262 p_args = (RIL_IMS_SMS_Message *)data;
2263
2264 if (0 != s_ims_cause_perm_failure ) goto error;
2265
2266 // want to fail over ims and this is first request over ims
2267 if (0 != s_ims_cause_retry && 0 == p_args->retry) goto error2;
2268
2269 if (RADIO_TECH_3GPP == p_args->tech) {
2270 return requestSendSMS(p_args->message.gsmMessage,
2271 datalen - sizeof(RIL_RadioTechnologyFamily),
2272 t);
2273 } else if (RADIO_TECH_3GPP2 == p_args->tech) {
2274 return requestCdmaSendSMS(p_args->message.cdmaMessage,
2275 datalen - sizeof(RIL_RadioTechnologyFamily),
2276 t);
2277 } else {
2278 RLOGE("requestImsSendSMS invalid format value =%d", p_args->tech);
2279 }
2280
2281 error:
2282 response.messageRef = -2;
2283 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, &response, sizeof(response));
2284 return;
2285
2286 error2:
2287 response.messageRef = -1;
2288 RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response, sizeof(response));
2289 }
2290
2291 /**
2292 * Add for CTS test
2293 * If open logical channel with AID NULL, this means open logical channel to MF.
2294 * If there is P2 value, this P2 value is used for SELECT command.
2295 * In addition, if SELECT command returns 61xx, GET RESPONSE command needs to send to get data.
2296 */
2297 static int sendCmdAgainForOpenChannelWithP2( char *data,
2298 int p2, int *response, int *rspLen) {
2299 int len = 0;
2300 int err = -1;
2301 char *line = NULL;
2302 char cmd[64] = {0};
2303 RIL_Errno errType = RIL_E_GENERIC_FAILURE;
2304 ATResponse *p_response = NULL;
2305 RIL_SIM_IO_Response sr;
2306
2307 memset(&sr, 0, sizeof(sr));
2308 sscanf(data, "%2x", &(response[0])); // response[0] is channel number
2309
2310 // Send SELECT command to MF
2311 snprintf(cmd, sizeof(cmd), "AT+CGLA=%d,14,00A400%02X023F00", response[0],
2312 p2);
2313
2314 err = at_send_command_singleline(cmd, "+CGLA:", &p_response);
2315 if (err < 0) goto done;
2316 if (p_response->success == 0) {
2317 if (!strcmp(p_response->finalResponse, "+CME ERROR: 21") ||
2318 !strcmp(p_response->finalResponse, "+CME ERROR: 50")) {
2319 errType = RIL_E_GENERIC_FAILURE;
2320 }
2321 goto done;
2322 }
2323
2324 line = p_response->p_intermediates->line;
2325
2326 if (at_tok_start(&line) < 0 || at_tok_nextint(&line, &len) < 0 ||
2327 at_tok_nextstr(&line, &(sr.simResponse)) < 0) {
2328 goto done;
2329 }
2330
2331 sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
2332
2333 if (sr.sw1 == 0x90 && sr.sw2 == 0x00) { // 9000 is successful
2334 int length = len / 2;
2335 for (*rspLen = 1; *rspLen <= length; (*rspLen)++) {
2336 sscanf(sr.simResponse, "%02x", &(response[*rspLen]));
2337 sr.simResponse += 2;
2338 }
2339 errType = RIL_E_SUCCESS;
2340 } else { // close channel
2341 snprintf(cmd, sizeof(cmd), "AT+CCHC=%d", response[0]);
2342 at_send_command( cmd, NULL);
2343 }
2344
2345 done:
2346 at_response_free(p_response);
2347 return errType;
2348 }
2349
2350 static void requestSimOpenChannel(void *data, size_t datalen, RIL_Token t)
2351 {
2352 RIL_UNUSED_PARM(datalen);
2353
2354 ATResponse *p_response = NULL;
2355 int response[260] = {0};
2356 int responseLen = 1;
2357 int32_t session_id;
2358 int err;
2359 char cmd[64] = {0};
2360 char complex;
2361 char *line = NULL;
2362 int skip = 0;
2363 char *statusWord = NULL;
2364 int err_no = RIL_E_GENERIC_FAILURE;
2365
2366 RIL_OpenChannelParams *params = (RIL_OpenChannelParams *)data;
2367
2368 // Max length is 16 bytes according to 3GPP spec 27.007 section 8.45
2369 if (params->aidPtr == NULL) {
2370 err = at_send_command_singleline("AT+CSIM=10,\"0070000001\"", "+CSIM:", &p_response);
2371 } else {
2372 snprintf(cmd, sizeof(cmd), "AT+CCHO=%s", params->aidPtr);
2373 err = at_send_command_numeric(cmd, &p_response);
2374 }
2375
2376 if (err < 0 || p_response == NULL || p_response->success == 0) {
2377 ALOGE("Error %d opening logical channel: %d",
2378 err, p_response ? p_response->success : 0);
2379 goto error;
2380 }
2381
2382 // Ensure integer only by scanning for an extra char but expect one result
2383 line = p_response->p_intermediates->line;
2384 if (params->aidPtr == NULL) {
2385
2386 err = at_tok_start(&line);
2387 if (err < 0) goto error;
2388
2389 err = at_tok_nextint(&line, &skip);
2390 if (err < 0) goto error;
2391
2392 err = at_tok_nextstr(&line, &statusWord);
2393 if (err < 0) goto error;
2394
2395 if (params->p2 < 0) {
2396 int length = strlen(statusWord) / 2;
2397 for (responseLen = 0; responseLen < length; responseLen++) {
2398 sscanf(statusWord, "%02x", &(response[responseLen]));
2399 statusWord += 2;
2400 }
2401 err_no = RIL_E_SUCCESS;
2402 } else {
2403 response[0] = 1;
2404 err_no = sendCmdAgainForOpenChannelWithP2(statusWord,
2405 params->p2, response, &responseLen);
2406 if (err_no != RIL_E_SUCCESS) {
2407 goto error;
2408 }
2409 }
2410 RIL_onRequestComplete(t, err_no, response, responseLen * sizeof(int));
2411 at_response_free(p_response);
2412 return;
2413 } else {
2414 if (sscanf(line, "%" SCNd32 "%c", &session_id, &complex) != 1) {
2415 ALOGE("Invalid AT response, expected integer, was '%s'", line);
2416 goto error;
2417 }
2418 }
2419
2420 RIL_onRequestComplete(t, RIL_E_SUCCESS, &session_id, sizeof(session_id));
2421 at_response_free(p_response);
2422 return;
2423
2424 error:
2425 RIL_onRequestComplete(t, err_no, NULL, 0);
2426 at_response_free(p_response);
2427 return;
2428 }
2429
2430 static void requestSimCloseChannel(void *data, size_t datalen, RIL_Token t)
2431 {
2432 ATResponse *p_response = NULL;
2433 int32_t session_id;
2434 int err;
2435 char cmd[32];
2436
2437 if (data == NULL || datalen != sizeof(session_id)) {
2438 ALOGE("Invalid data passed to requestSimCloseChannel");
2439 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2440 return;
2441 }
2442 session_id = ((int32_t *)data)[0];
2443 if (session_id == 0) {
2444 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
2445 return;
2446 }
2447
2448 snprintf(cmd, sizeof(cmd), "AT+CCHC=%" PRId32, session_id);
2449 err = at_send_command_singleline(cmd, "+CCHC", &p_response);
2450
2451 if (err < 0 || p_response == NULL || p_response->success == 0) {
2452 ALOGE("Error %d closing logical channel %d: %d",
2453 err, session_id, p_response ? p_response->success : 0);
2454 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2455 at_response_free(p_response);
2456 return;
2457 }
2458
2459 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2460
2461 at_response_free(p_response);
2462 }
2463
2464 static void requestSimTransmitApduChannel(void *data,
2465 size_t datalen,
2466 RIL_Token t)
2467 {
2468 ATResponse *p_response = NULL;
2469 int err;
2470 int len = 0;
2471 char *cmd;
2472 char *line = NULL;
2473 size_t cmd_size;
2474 RIL_SIM_IO_Response sr = {0};
2475 RIL_SIM_APDU *apdu = (RIL_SIM_APDU *)data;
2476
2477 if (apdu == NULL || datalen != sizeof(RIL_SIM_APDU)) {
2478 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2479 return;
2480 }
2481
2482 cmd_size = 10 + (apdu->data ? strlen(apdu->data) : 0);
2483 asprintf(&cmd, "AT+CGLA=%d,%zu,%02x%02x%02x%02x%02x%s",
2484 apdu->sessionid, cmd_size, apdu->cla, apdu->instruction,
2485 apdu->p1, apdu->p2, apdu->p3, apdu->data ? apdu->data : "");
2486
2487 err = at_send_command_singleline(cmd, "+CGLA:", &p_response);
2488 free(cmd);
2489 if (err < 0 || p_response == NULL || p_response->success == 0) {
2490 ALOGE("Error %d transmitting APDU: %d",
2491 err, p_response ? p_response->success : 0);
2492 goto error;
2493 }
2494
2495 line = p_response->p_intermediates->line;
2496 err = at_tok_start(&line);
2497 if (err < 0) goto error;
2498
2499 err = at_tok_nextint(&line, &len);
2500 if (err < 0) goto error;
2501
2502 err = at_tok_nextstr(&line, &(sr.simResponse));
2503 if (err < 0) goto error;
2504
2505 len = strlen(sr.simResponse);
2506 if (len < 4) goto error;
2507
2508 sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
2509 sr.simResponse[len - 4] = '\0';
2510
2511 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
2512 at_response_free(p_response);
2513 return;
2514
2515 error:
2516 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2517 at_response_free(p_response);
2518 }
2519
2520 static void requestSimAuthentication(int authContext, char* authData, RIL_Token t) {
2521 int err = -1, ret = 0;
2522 int status = 0;
2523 int binSimResponseLen = 0;
2524 char *cmd = NULL;
2525 char *line = NULL;
2526 // Input data
2527 int randLen = 0, autnLen = 0;
2528 char *rand = NULL, *autn = NULL;
2529 // EAP-SIM response data
2530 int kcLen = 0, sresLen = 0;
2531 char *kc = NULL, *sres = NULL;
2532 // EAP-AKA response data
2533 int ckLen = 0, ikLen = 0, resAutsLen = 0;
2534 char *ck = NULL, *ik = NULL, *resAuts = NULL;
2535 unsigned char *binSimResponse = NULL;
2536 unsigned char *binAuthData = NULL;
2537 unsigned char *hexAuthData = NULL;
2538 ATResponse *p_response = NULL;
2539 RIL_SIM_IO_Response response;
2540
2541 memset(&response, 0, sizeof(response));
2542 response.sw1 = 0x90;
2543 response.sw2 = 0;
2544
2545 binAuthData =
2546 (unsigned char *)malloc(sizeof(*binAuthData) * strlen(authData));
2547 if (binAuthData == NULL) {
2548 goto error;
2549 }
2550 if(base64_decode(authData, binAuthData) <= 0) {
2551 RLOGE("base64_decode failed %s %d", __func__, __LINE__);
2552 goto error;
2553 }
2554 hexAuthData =
2555 (unsigned char *)malloc(strlen(authData) * 2 + sizeof(char));
2556 if (hexAuthData == NULL) {
2557 goto error;
2558 }
2559 memset(hexAuthData, 0, strlen(authData) * 2 + sizeof(char));
2560 convertBytesToHexString((char *)binAuthData, strlen(authData), hexAuthData);
2561
2562 randLen = binAuthData[0];
2563 rand = (char *)malloc(sizeof(char) * (randLen * 2 + sizeof(char)));
2564 if (rand == NULL) {
2565 goto error;
2566 }
2567 memcpy(rand, hexAuthData + 2, randLen * 2);
2568 memcpy(rand + randLen * 2, "\0", 1);
2569
2570 if (authContext == AUTH_CONTEXT_EAP_AKA) {
2571 // There's the autn value to parse as well.
2572 autnLen = binAuthData[1 + randLen];
2573 autn = (char*)malloc(sizeof(char) * (autnLen * 2 + sizeof(char)));
2574 if (autn == NULL) {
2575 goto error;
2576 }
2577 memcpy(autn, hexAuthData + 2 + randLen * 2 + 2, autnLen * 2);
2578 memcpy(autn + autnLen * 2, "\0", 1);
2579 }
2580
2581 if (authContext == AUTH_CONTEXT_EAP_SIM) {
2582 ret = asprintf(&cmd, "AT^MBAU=\"%s\"", rand);
2583 } else {
2584 ret = asprintf(&cmd, "AT^MBAU=\"%s,%s\"", rand, autn);
2585 }
2586 if (ret < 0) {
2587 RLOGE("Failed to asprintf");
2588 goto error;
2589 }
2590 err = at_send_command_singleline( cmd, "^MBAU:", &p_response);
2591 free(cmd);
2592
2593 if (err < 0 || p_response->success == 0) {
2594 goto error;
2595 }
2596 line = p_response->p_intermediates->line;
2597 err = at_tok_start(&line);
2598 if (err < 0) goto error;
2599
2600 err = at_tok_nextint(&line, &status);
2601 if (err < 0) goto error;
2602 if (status != SIM_AUTH_RESPONSE_SUCCESS) {
2603 goto error;
2604 }
2605
2606 if (authContext == AUTH_CONTEXT_EAP_SIM) {
2607 err = at_tok_nextstr(&line, &kc);
2608 if (err < 0) goto error;
2609 kcLen = strlen(kc);
2610
2611 err = at_tok_nextstr(&line, &sres);
2612 if (err < 0) goto error;
2613 sresLen = strlen(sres);
2614
2615 // sresLen + sres + kcLen + kc + '\0'
2616 binSimResponseLen = (kcLen + sresLen) / 2 + 3 * sizeof(char);
2617 binSimResponse = (unsigned char*)malloc(binSimResponseLen + sizeof(char));
2618 if (binSimResponse == NULL) goto error;
2619 memset(binSimResponse, 0, binSimResponseLen);
2620 // set sresLen and sres
2621 binSimResponse[0] = (sresLen / 2) & 0xFF;
2622 uint8_t* tmpBinSimResponse = convertHexStringToBytes(sres, sresLen);
2623 snprintf((char*)(binSimResponse + 1), sresLen / 2, "%s", tmpBinSimResponse);
2624 free(tmpBinSimResponse);
2625 tmpBinSimResponse = NULL;
2626 // set kcLen and kc
2627 binSimResponse[1 + sresLen / 2] = (kcLen / 2) & 0xFF;
2628 tmpBinSimResponse = convertHexStringToBytes(kc, kcLen);
2629 snprintf((char*)(binSimResponse + 1 + sresLen / 2 + 1), kcLen / 2, "%s", tmpBinSimResponse);
2630 free(tmpBinSimResponse);
2631 tmpBinSimResponse = NULL;
2632 } else { // AUTH_CONTEXT_EAP_AKA
2633 err = at_tok_nextstr(&line, &ck);
2634 if (err < 0) goto error;
2635 ckLen = strlen(ck);
2636
2637 err = at_tok_nextstr(&line, &ik);
2638 if (err < 0) goto error;
2639 ikLen = strlen(ik);
2640
2641 err = at_tok_nextstr(&line, &resAuts);
2642 if (err < 0) goto error;
2643 resAutsLen = strlen(resAuts);
2644
2645 // 0xDB + ckLen + ck + ikLen + ik + resAutsLen + resAuts + '\0'
2646 binSimResponseLen = (ckLen + ikLen + resAutsLen) / 2 + 5 * sizeof(char);
2647 binSimResponse = (unsigned char*)malloc(binSimResponseLen + sizeof(char));
2648 if (binSimResponse == NULL) goto error;
2649 memset(binSimResponse, 0, binSimResponseLen);
2650 // The DB prefix indicates successful auth. Not produced by the SIM.
2651 binSimResponse[0] = 0xDB;
2652 // Set ckLen and ck
2653 binSimResponse[1] = (ckLen / 2) & 0xFF;
2654 uint8_t* tmpBinSimResponse = convertHexStringToBytes(ck, ckLen);
2655 snprintf((char*)(binSimResponse + 2), ckLen / 2 + 1, "%s", tmpBinSimResponse);
2656 free(tmpBinSimResponse);
2657 tmpBinSimResponse = NULL;
2658 // Set ikLen and ik
2659 binSimResponse[2 + ckLen / 2] = (ikLen / 2) & 0xFF;
2660 tmpBinSimResponse = convertHexStringToBytes(ik, ikLen);
2661 snprintf((char*)(binSimResponse + 2 + ckLen / 2 + 1), ikLen / 2 + 1, "%s",
2662 tmpBinSimResponse);
2663 free(tmpBinSimResponse);
2664 tmpBinSimResponse = NULL;
2665 // Set resAutsLen and resAuts
2666 binSimResponse[2 + ckLen / 2 + 1 + ikLen / 2] = (resAutsLen / 2) & 0xFF;
2667 tmpBinSimResponse = convertHexStringToBytes(resAuts, resAutsLen);
2668 snprintf((char*)(binSimResponse + 2 + ckLen / 2 + 1 + ikLen / 2 + 1), resAutsLen / 2 + 1,
2669 "%s", tmpBinSimResponse);
2670 free(tmpBinSimResponse);
2671 tmpBinSimResponse = NULL;
2672 }
2673
2674 response.simResponse = (char*)malloc(2 * binSimResponseLen + sizeof(char));
2675 if (response.simResponse == NULL) goto error;
2676 if (NULL == base64_encode(binSimResponse, response.simResponse, binSimResponseLen - 1)) {
2677 RLOGE("Failed to call base64_encode %s %d", __func__, __LINE__);
2678 goto error;
2679 }
2680
2681 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
2682 at_response_free(p_response);
2683
2684 free(binAuthData);
2685 free(hexAuthData);
2686 free(rand);
2687 free(autn);
2688 free(response.simResponse);
2689 free(binSimResponse);
2690 return;
2691
2692 error:
2693 free(binAuthData);
2694 free(hexAuthData);
2695 free(rand);
2696 free(autn);
2697 free(response.simResponse);
2698 free(binSimResponse);
2699
2700 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2701 at_response_free(p_response);
2702 }
2703
2704 static void requestTransmitApduBasic( void *data, size_t datalen,
2705 RIL_Token t) {
2706 RIL_UNUSED_PARM(datalen);
2707
2708 int err, len;
2709 char *cmd = NULL;
2710 char *line = NULL;
2711 RIL_SIM_APDU *p_args = NULL;
2712 ATResponse *p_response = NULL;
2713 RIL_SIM_IO_Response sr;
2714
2715 memset(&sr, 0, sizeof(sr));
2716
2717 p_args = (RIL_SIM_APDU *)data;
2718
2719 if ((p_args->data == NULL) || (strlen(p_args->data) == 0)) {
2720 if (p_args->p3 < 0) {
2721 asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x\"", 8, p_args->cla,
2722 p_args->instruction, p_args->p1, p_args->p2);
2723 } else {
2724 asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x%02x\"", 10,
2725 p_args->cla, p_args->instruction, p_args->p1, p_args->p2,
2726 p_args->p3);
2727 }
2728 } else {
2729 asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x%02x%s\"",
2730 10 + (int)strlen(p_args->data), p_args->cla,
2731 p_args->instruction, p_args->p1, p_args->p2, p_args->p3,
2732 p_args->data);
2733 }
2734 err = at_send_command_singleline(cmd, "+CSIM:", &p_response);
2735 free(cmd);
2736 if (err < 0 || p_response->success == 0) {
2737 goto error;
2738 }
2739
2740 line = p_response->p_intermediates->line;
2741 err = at_tok_start(&line);
2742 if (err < 0) goto error;
2743
2744 err = at_tok_nextint(&line, &len);
2745 if (err < 0) goto error;
2746
2747 err = at_tok_nextstr(&line, &(sr.simResponse));
2748 if (err < 0) goto error;
2749
2750 sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
2751 sr.simResponse[len - 4] = '\0';
2752
2753 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
2754 at_response_free(p_response);
2755 return;
2756
2757 error:
2758 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2759 at_response_free(p_response);
2760 }
2761
2762 static int getPDP() {
2763 int ret = -1;
2764
2765 for (int i = 0; i < MAX_PDP; i++) {
2766 if (s_PDP[i].state == PDP_IDLE) {
2767 s_PDP[i].state = PDP_BUSY;
2768 ret = s_PDP[i].cid;
2769 break;
2770 }
2771 }
2772 return ret;
2773 }
2774
2775 static void putPDP(int cid) {
2776 if (cid < 1 || cid > MAX_PDP ) {
2777 return;
2778 }
2779
2780 s_PDP[cid - 1].state = PDP_IDLE;
2781 }
2782
2783 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
2784 {
2785 const char *apn = NULL;
2786 char *cmd = NULL;
2787 int err = -1;
2788 int cid = -1;
2789 ATResponse *p_response = NULL;
2790
2791 apn = ((const char **)data)[2];
2792
2793 #ifdef USE_TI_COMMANDS
2794 // Config for multislot class 10 (probably default anyway eh?)
2795 err = at_send_command("AT%CPRIM=\"GMM\",\"CONFIG MULTISLOT_CLASS=<10>\"",
2796 NULL);
2797
2798 err = at_send_command("AT%DATA=2,\"UART\",1,,\"SER\",\"UART\",0", NULL);
2799 #endif /* USE_TI_COMMANDS */
2800
2801 int fd, qmistatus;
2802 size_t cur = 0;
2803 size_t len;
2804 ssize_t written, rlen;
2805 char status[32] = {0};
2806 int retry = 10;
2807 const char *pdp_type;
2808
2809 RLOGD("requesting data connection to APN '%s'", apn);
2810
2811 fd = open ("/dev/qmi", O_RDWR);
2812 if (fd >= 0) { /* the device doesn't exist on the emulator */
2813
2814 RLOGD("opened the qmi device\n");
2815 asprintf(&cmd, "up:%s", apn);
2816 len = strlen(cmd);
2817
2818 while (cur < len) {
2819 do {
2820 written = write (fd, cmd + cur, len - cur);
2821 } while (written < 0 && errno == EINTR);
2822
2823 if (written < 0) {
2824 RLOGE("### ERROR writing to /dev/qmi");
2825 close(fd);
2826 goto error;
2827 }
2828
2829 cur += written;
2830 }
2831
2832 // wait for interface to come online
2833
2834 do {
2835 sleep(1);
2836 do {
2837 rlen = read(fd, status, 31);
2838 } while (rlen < 0 && errno == EINTR);
2839
2840 if (rlen < 0) {
2841 RLOGE("### ERROR reading from /dev/qmi");
2842 close(fd);
2843 goto error;
2844 } else {
2845 status[rlen] = '\0';
2846 RLOGD("### status: %s", status);
2847 }
2848 } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
2849
2850 close(fd);
2851
2852 if (retry == 0) {
2853 RLOGE("### Failed to get data connection up\n");
2854 goto error;
2855 }
2856
2857 qmistatus = system("netcfg buried_eth0 dhcp");
2858
2859 RLOGD("netcfg buried_eth0 dhcp: status %d\n", qmistatus);
2860
2861 if (qmistatus < 0) goto error;
2862
2863 } else {
2864 const char* radioInterfaceName = getRadioInterfaceName();
2865 if (setInterfaceState(radioInterfaceName, kInterfaceUp) != RIL_E_SUCCESS) {
2866 goto error;
2867 }
2868
2869 if (datalen > 6 * sizeof(char *)) {
2870 pdp_type = ((const char **)data)[6];
2871 } else {
2872 pdp_type = "IP";
2873 }
2874
2875 cid = getPDP();
2876 if (cid < 1) {
2877 RLOGE("SETUP_DATA_CALL MAX_PDP reached.");
2878 RIL_Data_Call_Response_v11 response;
2879 response.status = 0x41 /* PDP_FAIL_MAX_ACTIVE_PDP_CONTEXT_REACHED */;
2880 response.suggestedRetryTime = -1;
2881 response.cid = cid;
2882 response.active = -1;
2883 response.type = "";
2884 response.ifname = "";
2885 response.addresses = "";
2886 response.dnses = "";
2887 response.gateways = "";
2888 response.pcscf = "";
2889 response.mtu = 0;
2890 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(RIL_Data_Call_Response_v11));
2891 at_response_free(p_response);
2892 return;
2893 }
2894
2895 asprintf(&cmd, "AT+CGDCONT=%d,\"%s\",\"%s\",,0,0", cid, pdp_type, apn);
2896 //FIXME check for error here
2897 err = at_send_command(cmd, NULL);
2898 free(cmd);
2899
2900 // Set required QoS params to default
2901 err = at_send_command("AT+CGQREQ=1", NULL);
2902
2903 // Set minimum QoS params to default
2904 err = at_send_command("AT+CGQMIN=1", NULL);
2905
2906 // packet-domain event reporting
2907 err = at_send_command("AT+CGEREP=1,0", NULL);
2908
2909 // Hangup anything that's happening there now
2910 err = at_send_command("AT+CGACT=1,0", NULL);
2911
2912 // Start data on PDP context 1
2913 err = at_send_command("ATD*99***1#", &p_response);
2914
2915 if (err < 0 || p_response->success == 0) {
2916 goto error;
2917 }
2918 }
2919
2920 requestOrSendDataCallList(cid, &t);
2921
2922 at_response_free(p_response);
2923
2924 return;
2925 error:
2926 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2927 at_response_free(p_response);
2928 }
2929
2930 static void requestDeactivateDataCall(void *data, RIL_Token t)
2931 {
2932 const char *p_cid = ((const char **)data)[0];
2933 int cid = p_cid ? atoi(p_cid) : -1;
2934 RIL_Errno rilErrno = RIL_E_GENERIC_FAILURE;
2935 if (cid < 1 || cid > MAX_PDP) {
2936 RIL_onRequestComplete(t, rilErrno, NULL, 0);
2937 return;
2938 }
2939
2940 const char* radioInterfaceName = getRadioInterfaceName();
2941 rilErrno = setInterfaceState(radioInterfaceName, kInterfaceDown);
2942 RIL_onRequestComplete(t, rilErrno, NULL, 0);
2943 putPDP(cid);
2944 requestOrSendDataCallList(-1, NULL);
2945 }
2946
2947 static void requestSMSAcknowledge(void *data, size_t datalen __unused, RIL_Token t)
2948 {
2949 int ackSuccess;
2950 int err;
2951
2952 if (getSIMStatus() == SIM_ABSENT) {
2953 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
2954 return;
2955 }
2956
2957 ackSuccess = ((int *)data)[0];
2958
2959 if (ackSuccess == 1) {
2960 err = at_send_command("AT+CNMA=1", NULL);
2961 if (err < 0) {
2962 goto error;
2963 }
2964 } else if (ackSuccess == 0) {
2965 err = at_send_command("AT+CNMA=2", NULL);
2966 if (err < 0) {
2967 goto error;
2968 }
2969 } else {
2970 RLOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n");
2971 goto error;
2972 }
2973
2974 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
2975
2976 return;
2977 error:
2978 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
2979 }
2980
2981 void convertBytesToHex(uint8_t *bytes, int length, uint8_t *hex_str) {
2982 int i;
2983 unsigned char tmp;
2984
2985 if (bytes == NULL || hex_str == NULL) {
2986 return;
2987 }
2988 for (i = 0; i < length; i++) {
2989 tmp = (unsigned char)((bytes[i] & 0xf0) >> 4);
2990 if (tmp <= 9) {
2991 *hex_str = (unsigned char)(tmp + '0');
2992 } else {
2993 *hex_str = (unsigned char)(tmp + 'A' - 10);
2994 }
2995 hex_str++;
2996 tmp = (unsigned char)(bytes[i] & 0x0f);
2997 if (tmp <= 9) {
2998 *hex_str = (unsigned char)(tmp + '0');
2999 } else {
3000 *hex_str = (unsigned char)(tmp + 'A' - 10);
3001 }
3002 hex_str++;
3003 }
3004 }
3005
3006 #define TYPE_EF 4
3007 #define RESPONSE_EF_SIZE 15
3008 #define TYPE_FILE_DES_LEN 5
3009 #define RESPONSE_DATA_FILE_DES_FLAG 2
3010 #define RESPONSE_DATA_FILE_DES_LEN_FLAG 3
3011 #define RESPONSE_DATA_FILE_TYPE 6
3012 #define RESPONSE_DATA_FILE_SIZE_1 2
3013 #define RESPONSE_DATA_FILE_SIZE_2 3
3014 #define RESPONSE_DATA_STRUCTURE 13
3015 #define RESPONSE_DATA_RECORD_LENGTH 14
3016 #define RESPONSE_DATA_FILE_RECORD_LEN_1 6
3017 #define RESPONSE_DATA_FILE_RECORD_LEN_2 7
3018 #define EF_TYPE_TRANSPARENT 0x01
3019 #define EF_TYPE_LINEAR_FIXED 0x02
3020 #define EF_TYPE_CYCLIC 0x06
3021 #define USIM_DATA_OFFSET_2 2
3022 #define USIM_DATA_OFFSET_3 3
3023 #define USIM_FILE_DES_TAG 0x82
3024 #define USIM_FILE_SIZE_TAG 0x80
3025
3026 bool convertUsimToSim(uint8_t *byteUSIM, int len, uint8_t *hexSIM) {
3027 int desIndex = 0;
3028 int sizeIndex = 0;
3029 int i = 0;
3030 uint8_t byteSIM[RESPONSE_EF_SIZE] = {0};
3031 for (i = 0; i < len; i++) {
3032 if (byteUSIM[i] == USIM_FILE_DES_TAG) {
3033 desIndex = i;
3034 break;
3035 }
3036 }
3037 for (i = desIndex; i < len;) {
3038 if (byteUSIM[i] == USIM_FILE_SIZE_TAG) {
3039 sizeIndex = i;
3040 break;
3041 } else {
3042 i += (byteUSIM[i + 1] + 2);
3043 }
3044 }
3045 byteSIM[RESPONSE_DATA_FILE_SIZE_1] =
3046 byteUSIM[sizeIndex + USIM_DATA_OFFSET_2];
3047 byteSIM[RESPONSE_DATA_FILE_SIZE_2] =
3048 byteUSIM[sizeIndex + USIM_DATA_OFFSET_3];
3049 byteSIM[RESPONSE_DATA_FILE_TYPE] = TYPE_EF;
3050 if ((byteUSIM[desIndex + RESPONSE_DATA_FILE_DES_FLAG] & 0x07) ==
3051 EF_TYPE_TRANSPARENT) {
3052 byteSIM[RESPONSE_DATA_STRUCTURE] = 0;
3053 } else if ((byteUSIM[desIndex + RESPONSE_DATA_FILE_DES_FLAG] & 0x07) ==
3054 EF_TYPE_LINEAR_FIXED) {
3055 if (USIM_FILE_DES_TAG != byteUSIM[RESPONSE_DATA_FILE_DES_FLAG]) {
3056 RLOGE("USIM_FILE_DES_TAG != ...");
3057 goto error;
3058 }
3059 if (TYPE_FILE_DES_LEN != byteUSIM[RESPONSE_DATA_FILE_DES_LEN_FLAG]) {
3060 goto error;
3061 }
3062 byteSIM[RESPONSE_DATA_STRUCTURE] = 1;
3063 byteSIM[RESPONSE_DATA_RECORD_LENGTH] =
3064 ((byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_1] & 0xff) << 8) +
3065 (byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_2] & 0xff);
3066 } else if ((byteUSIM[desIndex + RESPONSE_DATA_FILE_DES_FLAG] & 0x07) ==
3067 EF_TYPE_CYCLIC) {
3068 byteSIM[RESPONSE_DATA_STRUCTURE] = 3;
3069 byteSIM[RESPONSE_DATA_RECORD_LENGTH] =
3070 ((byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_1] & 0xff) << 8) +
3071 (byteUSIM[RESPONSE_DATA_FILE_RECORD_LEN_2] & 0xff);
3072 }
3073
3074 convertBytesToHex(byteSIM, RESPONSE_EF_SIZE, hexSIM);
3075 return true;
3076
3077 error:
3078 return false;
3079 }
3080
3081 static void requestSIM_IO(void *data, size_t datalen __unused, RIL_Token t)
3082 {
3083 ATResponse *p_response = NULL;
3084 RIL_SIM_IO_Response sr;
3085 int err;
3086 char *cmd = NULL;
3087 RIL_SIM_IO_v6 *p_args;
3088 char *line;
3089
3090 /* For Convert USIM to SIM */
3091 uint8_t hexSIM[RESPONSE_EF_SIZE * 2 + sizeof(char)] = {0};
3092
3093 memset(&sr, 0, sizeof(sr));
3094
3095 p_args = (RIL_SIM_IO_v6 *)data;
3096
3097 /* FIXME handle pin2 */
3098
3099 if (p_args->data == NULL) {
3100 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
3101 p_args->command, p_args->fileid,
3102 p_args->p1, p_args->p2, p_args->p3);
3103 } else {
3104 asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
3105 p_args->command, p_args->fileid,
3106 p_args->p1, p_args->p2, p_args->p3, p_args->data);
3107 }
3108
3109 err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
3110
3111 if (err < 0 || p_response->success == 0) {
3112 goto error;
3113 }
3114
3115 line = p_response->p_intermediates->line;
3116
3117 err = parseSimResponseLine(line, &sr);
3118 if (err < 0) {
3119 goto error;
3120 }
3121 if (sr.simResponse != NULL && // Default to be USIM card
3122 p_args->command == 192) { // Get response
3123 uint8_t *bytes = convertHexStringToBytes(sr.simResponse, strlen(sr.simResponse));
3124 if (bytes == NULL) {
3125 RLOGE("Failed to convert sim response to bytes");
3126 goto error;
3127 }
3128 if (bytes[0] != 0x62) {
3129 RLOGE("Wrong FCP flag, unable to convert to sim ");
3130 free(bytes);
3131 goto error;
3132 }
3133 if (convertUsimToSim(bytes, strlen(sr.simResponse) / 2, hexSIM)) {
3134 sr.simResponse = (char *)hexSIM;
3135 }
3136 free(bytes);
3137 }
3138
3139 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
3140 at_response_free(p_response);
3141 free(cmd);
3142 return;
3143
3144 error:
3145 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3146 at_response_free(p_response);
3147 free(cmd);
3148 }
3149
3150 static int getSimlockRemainTimes(const char* type) {
3151 int err = -1;
3152 int remain_times = -1;
3153 char cmd[32] = {0};
3154 char *line = NULL;
3155 char *lock_type = NULL;
3156 ATResponse *p_response = NULL;
3157
3158 snprintf(cmd, sizeof(cmd), "AT+CPINR=\"%s\"", type);
3159 err = at_send_command_multiline(cmd, "+CPINR:", &p_response);
3160 if (err < 0 || p_response->success == 0) {
3161 goto error;
3162 }
3163
3164 line = p_response->p_intermediates->line;
3165 err = at_tok_start(&line);
3166 if (err < 0) goto error;
3167
3168 err = at_tok_nextstr(&line, &lock_type);
3169 if (err < 0) goto error;
3170
3171 err = at_tok_nextint(&line, &remain_times);
3172 if (err < 0) goto error;
3173
3174 error:
3175 at_response_free(p_response);
3176 return remain_times;
3177 }
3178
3179 static void requestEnterSimPin(int request, void* data, size_t datalen, RIL_Token t)
3180 {
3181 ATResponse *p_response = NULL;
3182 int err;
3183 int remaintimes = -1;
3184 char* cmd = NULL;
3185 const char** strings = (const char**)data;;
3186
3187 if (datalen == sizeof(char*) || datalen == 2 * sizeof(char*)) {
3188 asprintf(&cmd, "AT+CPIN=%s", strings[0]);
3189 } else
3190 goto error;
3191
3192 err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
3193 free(cmd);
3194
3195 if (err < 0 || p_response->success == 0) {
3196 error:
3197 if (request == RIL_REQUEST_ENTER_SIM_PIN) {
3198 remaintimes = getSimlockRemainTimes("SIM PIN");
3199 } else if (request == RIL_REQUEST_ENTER_SIM_PIN2) {
3200 remaintimes = getSimlockRemainTimes("SIM PIN2");
3201 }
3202 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &remaintimes,
3203 sizeof(remaintimes));
3204 } else {
3205 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3206 }
3207 at_response_free(p_response);
3208 }
3209
3210 static void requestChangeSimPin(int request, void* data, size_t datalen, RIL_Token t)
3211 {
3212 ATResponse *p_response = NULL;
3213 int err;
3214 int remaintimes = -1;
3215 char* cmd = NULL;
3216 const char** strings = (const char**)data;;
3217
3218 if (datalen == 2 * sizeof(char*) || datalen == 3 * sizeof(char*)) {
3219 asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
3220 } else
3221 goto error;
3222
3223 err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
3224 free(cmd);
3225
3226 if (err < 0 || p_response->success == 0) {
3227 error:
3228 if (request == RIL_REQUEST_CHANGE_SIM_PIN) {
3229 remaintimes = getSimlockRemainTimes("SIM PIN");
3230 } else if (request == RIL_REQUEST_ENTER_SIM_PUK) {
3231 remaintimes = getSimlockRemainTimes("SIM PUK");
3232 } else if (request == RIL_REQUEST_ENTER_SIM_PUK2) {
3233 remaintimes = getSimlockRemainTimes("SIM PUK2");
3234 }
3235 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &remaintimes,
3236 sizeof(remaintimes));
3237 } else {
3238 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3239 }
3240 at_response_free(p_response);
3241 }
3242
3243 static void requestChangeSimPin2(void *data, size_t datalen, RIL_Token t) {
3244 int err, ret;
3245 int remaintime = -1;
3246 char cmd[64] = {0};
3247 const char **strings = (const char **)data;
3248 ATResponse *p_response = NULL;
3249
3250 if (datalen != 3 * sizeof(char *)) {
3251 goto error;
3252 }
3253
3254 snprintf(cmd, sizeof(cmd), "AT+CPWD=\"P2\",\"%s\",\"%s\"", strings[0],
3255 strings[1]);
3256 err = at_send_command(cmd, &p_response);
3257 if (err < 0 || p_response->success == 0) {
3258 remaintime = getSimlockRemainTimes("SIM PIN2");
3259 goto error;
3260 }
3261
3262 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3263 at_response_free(p_response);
3264 return;
3265
3266 error:
3267 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &remaintime,
3268 sizeof(remaintime));
3269 at_response_free(p_response);
3270 }
3271
3272 static void requestSendUSSD(void *data, size_t datalen, RIL_Token t)
3273 {
3274 RIL_UNUSED_PARM(datalen);
3275
3276 int err = -1;
3277 char cmd[128] = {0};
3278 const char *ussdRequest = (char *)(data);
3279 ATResponse *p_response = NULL;
3280
3281 snprintf(cmd, sizeof(cmd), "AT+CUSD=1,\"%s\"", ussdRequest);
3282 err = at_send_command(cmd, &p_response);
3283 if (err < 0 || p_response->success == 0) {
3284 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3285 } else {
3286 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3287 }
3288 at_response_free(p_response);
3289 }
3290
3291 static void requestExitEmergencyMode(void *data __unused, size_t datalen __unused, RIL_Token t)
3292 {
3293 int err;
3294 ATResponse *p_response = NULL;
3295
3296 err = at_send_command("AT+WSOS=0", &p_response);
3297
3298 if (err < 0 || p_response->success == 0) {
3299 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3300 return;
3301 }
3302
3303 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3304 }
3305
3306 static uint64_t s_last_activity_info_query = 0;
3307
3308 static void requestGetActivityInfo(void *data __unused, size_t datalen __unused, RIL_Token t)
3309 {
3310 uint64_t curTime = ril_nano_time();
3311 RIL_ActivityStatsInfo stats =
3312 {
3313 0, // sleep_mode_time_ms
3314 ((curTime - s_last_activity_info_query) / 1000000) - 1, // idle_mode_time_ms
3315 {0, 0, 0, 0, 0}, // tx_mode_time_ms
3316 0 // rx_mode_time_ms
3317 };
3318 s_last_activity_info_query = curTime;
3319
3320 RIL_onRequestComplete(t, RIL_E_SUCCESS, &stats, sizeof(stats));
3321 }
3322
3323 // TODO: Use all radio types
3324 static int techFromModemType(int mdmtype)
3325 {
3326 int ret = -1;
3327 switch (mdmtype) {
3328 case MDM_CDMA:
3329 ret = RADIO_TECH_1xRTT;
3330 break;
3331 case MDM_EVDO:
3332 ret = RADIO_TECH_EVDO_A;
3333 break;
3334 case MDM_GSM:
3335 ret = RADIO_TECH_GPRS;
3336 break;
3337 case MDM_WCDMA:
3338 ret = RADIO_TECH_HSPA;
3339 break;
3340 case MDM_LTE:
3341 ret = RADIO_TECH_LTE;
3342 case MDM_NR:
3343 ret = RADIO_TECH_NR;
3344 break;
3345 }
3346 return ret;
3347 }
3348
3349 static void requestGetCellInfoList(void *data __unused, size_t datalen __unused, RIL_Token t)
3350 {
3351 uint64_t curTime = ril_nano_time();
3352 RIL_CellInfo_v12 ci[1] =
3353 {
3354 { // ci[0]
3355 1, // cellInfoType
3356 1, // registered
3357 RIL_TIMESTAMP_TYPE_MODEM,
3358 curTime - 1000, // Fake some time in the past
3359 { // union CellInfo
3360 { // RIL_CellInfoGsm gsm
3361 { // gsm.cellIdneityGsm
3362 s_mcc, // mcc
3363 s_mnc, // mnc
3364 s_lac, // lac
3365 s_cid, // cid
3366 0, //arfcn unknown
3367 0x1, // Base Station Identity Code set to arbitrarily 1
3368 },
3369 { // gsm.signalStrengthGsm
3370 10, // signalStrength
3371 0 // bitErrorRate
3372 , INT_MAX // timingAdvance invalid value
3373 }
3374 }
3375 }
3376 }
3377 };
3378
3379 RIL_onRequestComplete(t, RIL_E_SUCCESS, ci, sizeof(ci));
3380 }
3381
3382 static void requestGetCellInfoList_1_6(void* data __unused, size_t datalen __unused, RIL_Token t) {
3383 RIL_CellInfo_v16 ci[1] = {{ // ci[0]
3384 3, // cellInfoType
3385 1, // registered
3386 CELL_CONNECTION_PRIMARY_SERVING,
3387 { // union CellInfo
3388 .lte = {// RIL_CellInfoLte_v12 lte
3389 {
3390 // RIL_CellIdentityLte_v12
3391 // lte.cellIdentityLte
3392 s_mcc, // mcc
3393 s_mnc, // mnc
3394 s_cid, // ci
3395 0, // pci
3396 s_lac, // tac
3397 7, // earfcn
3398 },
3399 {
3400 // RIL_LTE_SignalStrength_v8
3401 // lte.signalStrengthLte
3402 10, // signalStrength
3403 44, // rsrp
3404 3, // rsrq
3405 30, // rssnr
3406 0, // cqi
3407 INT_MAX // timingAdvance invalid value
3408 }}}}};
3409
3410 RIL_onRequestComplete(t, RIL_E_SUCCESS, ci, sizeof(ci));
3411 }
3412
3413 static void requestSetCellInfoListRate(void *data, size_t datalen __unused, RIL_Token t)
3414 {
3415 // For now we'll save the rate but no RIL_UNSOL_CELL_INFO_LIST messages
3416 // will be sent.
3417 assert (datalen == sizeof(int));
3418 s_cell_info_rate_ms = ((int *)data)[0];
3419
3420 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3421 }
3422
3423 static void requestGetHardwareConfig(void *data, size_t datalen, RIL_Token t)
3424 {
3425 // TODO - hook this up with real query/info from radio.
3426
3427 RIL_HardwareConfig hwCfg;
3428
3429 RIL_UNUSED_PARM(data);
3430 RIL_UNUSED_PARM(datalen);
3431
3432 hwCfg.type = -1;
3433
3434 RIL_onRequestComplete(t, RIL_E_SUCCESS, &hwCfg, sizeof(hwCfg));
3435 }
3436
3437 static void requestGetTtyMode(void *data, size_t datalen, RIL_Token t)
3438 {
3439 int ttyModeResponse;
3440
3441 RIL_UNUSED_PARM(data);
3442 RIL_UNUSED_PARM(datalen);
3443
3444 ttyModeResponse = (getSIMStatus() == SIM_READY) ? 1 // TTY Full
3445 : 0; // TTY Off
3446
3447 RIL_onRequestComplete(t, RIL_E_SUCCESS, &ttyModeResponse, sizeof(ttyModeResponse));
3448 }
3449
3450 static void requestGetRadioCapability(void *data, size_t datalen, RIL_Token t)
3451 {
3452 RIL_RadioCapability radioCapability;
3453
3454 RIL_UNUSED_PARM(data);
3455 RIL_UNUSED_PARM(datalen);
3456
3457 radioCapability.version = RIL_RADIO_CAPABILITY_VERSION;
3458 radioCapability.session = 0;
3459 radioCapability.phase = 0;
3460 radioCapability.rat = NR | LTE | WCDMA | GSM;
3461 strncpy(radioCapability.logicalModemUuid, "com.android.modem.simulator", MAX_UUID_LENGTH);
3462 radioCapability.status = RC_STATUS_SUCCESS;
3463
3464 RIL_onRequestComplete(t, RIL_E_SUCCESS, &radioCapability, sizeof(radioCapability));
3465 }
3466
3467 static void requestSetRadioCapability(void *data, size_t datalen, RIL_Token t)
3468 {
3469 RIL_RadioCapability* rc = (RIL_RadioCapability*)data;
3470 RLOGV(
3471 "RadioCapability version %d session %d phase %d rat %d "
3472 "logicalModemUuid %s status %d",
3473 rc->version, rc->session, rc->phase, rc->rat, rc->logicalModemUuid,
3474 rc->status);
3475 // TODO(ender): do something about these numbers.
3476 RIL_onRequestComplete(t, RIL_E_SUCCESS, rc, datalen);
3477 }
3478
3479 static void requestGetMute(void *data, size_t datalen, RIL_Token t)
3480 {
3481 RIL_UNUSED_PARM(data);
3482 RIL_UNUSED_PARM(datalen);
3483
3484 int err = -1;
3485 int muteResponse = 0; // Mute disabled
3486 char *line = NULL;
3487 ATResponse *p_response = NULL;
3488
3489 err = at_send_command_singleline("AT+CMUT?", "+CMUT:", &p_response);
3490 if (err < 0 || p_response->success) {
3491 goto done;
3492 }
3493
3494 line = p_response->p_intermediates->line;
3495 err = at_tok_start(&line);
3496 if (err < 0) goto done;
3497
3498 at_tok_nextint(&line, &muteResponse);
3499
3500 done:
3501 RIL_onRequestComplete(t, RIL_E_SUCCESS, &muteResponse, sizeof(muteResponse));
3502 at_response_free(p_response);
3503 }
3504
3505 static void requestSetMute(void *data, size_t datalen, RIL_Token t)
3506 {
3507 RIL_UNUSED_PARM(datalen);
3508
3509 int err = -1;
3510 char cmd[64] = {0};
3511 ATResponse *p_response = NULL;
3512
3513 snprintf(cmd, sizeof(cmd), "AT+CMUT=%d", ((int *)data)[0]);
3514 err = at_send_command(cmd, &p_response);
3515 if (err < 0 || p_response->success) {
3516 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3517 } else {
3518 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3519 }
3520 at_response_free(p_response);
3521 }
3522
3523 static void requestScreenState(void *data, RIL_Token t)
3524 {
3525 int status = *((int *)data);
3526
3527 if (!status) {
3528 /* Suspend */
3529 at_send_command("AT+CEREG=1", NULL);
3530 at_send_command("AT+CREG=1", NULL);
3531 at_send_command("AT+CGREG=1", NULL);
3532 } else {
3533 /* Resume */
3534 at_send_command("AT+CEREG=2", NULL);
3535 at_send_command("AT+CREG=2", NULL);
3536 at_send_command("AT+CGREG=2", NULL);
3537 }
3538
3539 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3540 }
3541
3542 static void requestQueryClip(void *data, size_t datalen, RIL_Token t)
3543 {
3544 RIL_UNUSED_PARM(datalen);
3545 RIL_UNUSED_PARM(data);
3546
3547 int err = -1;
3548 int skip = 0;
3549 int response = 0;
3550 char *line = NULL;
3551 ATResponse *p_response = NULL;
3552
3553 if (getSIMStatus() == SIM_ABSENT) {
3554 RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
3555 return;
3556 }
3557
3558 err = at_send_command_singleline("AT+CLIP?", "+CLIP:", &p_response);
3559 if (err < 0 || p_response->success == 0) {
3560 goto error;
3561 }
3562
3563 line = p_response->p_intermediates->line;
3564 err = at_tok_start(&line);
3565 if (err < 0) goto error;
3566
3567 err = at_tok_nextint(&line, &skip);
3568 if (err < 0) goto error;
3569
3570 err = at_tok_nextint(&line, &response);
3571 if (err < 0) goto error;
3572
3573 RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
3574 at_response_free(p_response);
3575 return;
3576
3577 error:
3578 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3579 at_response_free(p_response);
3580 }
3581
3582 static void requestQueryClir(void *data, size_t datalen, RIL_Token t)
3583 {
3584 RIL_UNUSED_PARM(datalen);
3585 RIL_UNUSED_PARM(data);
3586
3587 int err = -1;
3588 int response[2] = {1, 1};
3589 char *line = NULL;
3590 ATResponse *p_response = NULL;
3591
3592 if (getSIMStatus() == SIM_ABSENT) {
3593 RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
3594 return;
3595 }
3596
3597 err = at_send_command_singleline("AT+CLIR?", "+CLIR:", &p_response);
3598 if (err < 0 || p_response->success == 0) {
3599 goto error;
3600 }
3601
3602 line = p_response->p_intermediates->line;
3603 err = at_tok_start(&line);
3604 if (err < 0) goto error;
3605
3606 err = at_tok_nextint(&line, &response[0]);
3607 if (err < 0) goto error;
3608
3609 err = at_tok_nextint(&line, &response[1]);
3610 if (err < 0) goto error;
3611
3612 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
3613 at_response_free(p_response);
3614 return;
3615
3616 error:
3617 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3618 at_response_free(p_response);
3619 }
3620
3621 static void requestSetClir(void *data, size_t datalen, RIL_Token t)
3622 {
3623 RIL_UNUSED_PARM(datalen);
3624
3625 int err = -1;
3626 int n = ((int *)data)[0];
3627 char cmd[64] = {0};
3628 ATResponse *p_response = NULL;
3629
3630 snprintf(cmd, sizeof(cmd), "AT+CLIR=%d", n);
3631 err = at_send_command(cmd, &p_response);
3632 if (err < 0 || p_response->success == 0) {
3633 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3634 } else {
3635 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3636 }
3637 at_response_free(p_response);
3638 }
3639
3640 static int forwardFromCCFCULine(char *line, RIL_CallForwardInfo *p_forward) {
3641 int err = -1;
3642 int i = 0;
3643
3644 if (line == NULL || p_forward == NULL) {
3645 goto error;
3646 }
3647
3648 err = at_tok_start(&line);
3649 if (err < 0) goto error;
3650
3651 err = at_tok_nextint(&line, &(p_forward->status));
3652 if (err < 0) goto error;
3653
3654 err = at_tok_nextint(&line, &(p_forward->serviceClass));
3655 if (err < 0) goto error;
3656
3657 if (at_tok_hasmore(&line)) {
3658 int numberType = 0;
3659 err = at_tok_nextint(&line, &numberType);
3660 if (err < 0) goto error;
3661
3662 err = at_tok_nextint(&line, &p_forward->toa);
3663 if (err < 0) goto error;
3664
3665 err = at_tok_nextstr(&line, &(p_forward->number));
3666
3667 /* tolerate null here */
3668 if (err < 0) return 0;
3669
3670 if (at_tok_hasmore(&line)) {
3671 for (i = 0; i < 2; i++) {
3672 skipNextComma(&line);
3673 }
3674
3675 if (at_tok_hasmore(&line)) {
3676 err = at_tok_nextint(&line, &p_forward->timeSeconds);
3677 if (err < 0) {
3678 p_forward->timeSeconds = 0;
3679 }
3680 }
3681 }
3682 }
3683
3684 return 0;
3685
3686 error:
3687 return -1;
3688 }
3689
3690 static void requestSetCallForward(RIL_CallForwardInfo *data,
3691 size_t datalen, RIL_Token t) {
3692 int err = -1;
3693 char cmd[128] = {0};
3694 size_t offset = 0;
3695 ATResponse *p_response = NULL;
3696
3697 if (datalen != sizeof(*data) ||
3698 (data->status == 3 && data->number == NULL)) {
3699 goto error;
3700 }
3701
3702 snprintf(cmd, sizeof(cmd), "AT+CCFCU=%d,%d,%d,%d,\"%s\",%d",
3703 data->reason,
3704 data->status,
3705 2,
3706 data->toa,
3707 data->number ? data->number : "",
3708 data->serviceClass);
3709 offset += strlen(cmd);
3710
3711 if (data->serviceClass == 0) {
3712 if (data->timeSeconds != 0 && data->status == 3) {
3713 snprintf(cmd + offset, sizeof(cmd) - offset, ",\"\",\"\",,%d",
3714 data->timeSeconds);
3715 }
3716 } else {
3717 if (data->timeSeconds != 0 && data->status == 3) {
3718 snprintf(cmd + offset, sizeof(cmd) - offset, ",\"\",\"\",,%d",
3719 data->timeSeconds);
3720 } else {
3721 strlcat(cmd, ",\"\"", sizeof(cmd) - offset);
3722 }
3723 }
3724
3725 err = at_send_command_multiline(cmd, "+CCFCU:", &p_response);
3726 if (err < 0 || p_response->success == 0) {
3727 goto error;
3728 }
3729
3730 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3731 at_response_free(p_response);
3732 return;
3733
3734 error:
3735 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3736 at_response_free(p_response);
3737 }
3738
3739 static void requestQueryCallForward(RIL_CallForwardInfo *data,
3740 size_t datalen, RIL_Token t) {
3741 int err = -1;
3742 char cmd[128] = {0};
3743 ATResponse *p_response = NULL;
3744 ATLine *p_cur = NULL;
3745
3746 if (datalen != sizeof(*data)) {
3747 goto error;
3748 }
3749
3750 snprintf(cmd, sizeof(cmd), "AT+CCFCU=%d,2,%d,%d,\"%s\",%d", data->reason, 2,
3751 data->toa, data->number ? data->number : "", data->serviceClass);
3752
3753 err = at_send_command_multiline(cmd, "+CCFCU:", &p_response);
3754 if (err < 0 || p_response->success == 0) {
3755 goto error;
3756 }
3757
3758 RIL_CallForwardInfo **forwardList = NULL, *forwardPool = NULL;
3759 int forwardCount = 0;
3760 int validCount = 0;
3761 int i = 0;
3762
3763 for (p_cur = p_response->p_intermediates; p_cur != NULL;
3764 p_cur = p_cur->p_next, forwardCount++) {
3765 }
3766
3767 forwardList = (RIL_CallForwardInfo **)
3768 alloca(forwardCount * sizeof(RIL_CallForwardInfo *));
3769
3770 forwardPool = (RIL_CallForwardInfo *)
3771 alloca(forwardCount * sizeof(RIL_CallForwardInfo));
3772
3773 memset(forwardPool, 0, forwardCount * sizeof(RIL_CallForwardInfo));
3774
3775 /* init the pointer array */
3776 for (i = 0; i < forwardCount; i++) {
3777 forwardList[i] = &(forwardPool[i]);
3778 }
3779
3780 for (p_cur = p_response->p_intermediates; p_cur != NULL;
3781 p_cur = p_cur->p_next) {
3782 err = forwardFromCCFCULine(p_cur->line, forwardList[validCount]);
3783 forwardList[validCount]->reason = data->reason;
3784 if (err == 0) validCount++;
3785 }
3786
3787 RIL_onRequestComplete(t, RIL_E_SUCCESS, validCount ? forwardList : NULL,
3788 validCount * sizeof (RIL_CallForwardInfo *));
3789 at_response_free(p_response);
3790 return;
3791
3792 error:
3793 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3794 at_response_free(p_response);
3795 }
3796
3797 static void requestQueryCallWaiting(void *data, size_t datalen, RIL_Token t) {
3798 RIL_UNUSED_PARM(datalen);
3799
3800 int err = -1, mode = 0;
3801 int serviceClass = ((int *)data)[0];
3802 int response[2] = {0, 0};
3803 char cmd[32] = {0};
3804 char *line;
3805 ATLine *p_cur;
3806 ATResponse *p_response = NULL;
3807
3808 if (serviceClass == 0) {
3809 snprintf(cmd, sizeof(cmd), "AT+CCWA=1,2");
3810 } else {
3811 snprintf(cmd, sizeof(cmd), "AT+CCWA=1,2,%d", serviceClass);
3812 }
3813 err = at_send_command_multiline(cmd, "+CCWA:", &p_response);
3814 if (err < 0 || p_response->success == 0) {
3815 goto error;
3816 }
3817
3818 for (p_cur = p_response->p_intermediates; p_cur != NULL;
3819 p_cur = p_cur->p_next) {
3820 line = p_cur->line;
3821 err = at_tok_start(&line);
3822 if (err < 0) goto error;
3823
3824 err = at_tok_nextint(&line, &mode);
3825 if (err < 0) goto error;
3826
3827 err = at_tok_nextint(&line, &serviceClass);
3828 if (err < 0) goto error;
3829
3830 response[0] = mode;
3831 response[1] |= serviceClass;
3832 }
3833 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
3834 at_response_free(p_response);
3835 return;
3836
3837 error:
3838 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3839 at_response_free(p_response);
3840 }
3841
3842 static void requestSetCallWaiting(void *data, size_t datalen, RIL_Token t) {
3843 RIL_UNUSED_PARM(datalen);
3844
3845 ATResponse *p_response = NULL;
3846 int err = -1;
3847 char cmd[32] = {0};
3848 int enable = ((int *)data)[0];
3849 int serviceClass = ((int *)data)[1];
3850
3851 if (serviceClass == 0) {
3852 snprintf(cmd, sizeof(cmd), "AT+CCWA=1,%d", enable);
3853 } else {
3854 snprintf(cmd, sizeof(cmd), "AT+CCWA=1,%d,%d", enable, serviceClass);
3855 }
3856
3857 err = at_send_command(cmd, &p_response);
3858 if (err < 0 || p_response->success == 0) {
3859 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3860 } else {
3861 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3862 }
3863 at_response_free(p_response);
3864 }
3865
3866 static void requestSetSuppServiceNotifications(void *data, size_t datalen,
3867 RIL_Token t) {
3868 RIL_UNUSED_PARM(datalen);
3869
3870 int err = 0;
3871 ATResponse *p_response = NULL;
3872 int mode = ((int *)data)[0];
3873 char cmd[32] = {0};
3874
3875 snprintf(cmd, sizeof(cmd), "AT+CSSN=%d,%d", mode, mode);
3876 err = at_send_command(cmd, &p_response);
3877 if (err < 0 || p_response->success == 0) {
3878 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
3879 } else {
3880 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3881 }
3882 at_response_free(p_response);
3883 }
3884
3885 static void requestChangeBarringPassword(char **data, size_t datalen, RIL_Token t) {
3886 int err = -1;
3887 int result;
3888 char cmd[64] = {0};
3889 ATResponse *p_response = NULL;
3890
3891 if (datalen != 3 * sizeof(char *) || data[0] == NULL || data[1] == NULL ||
3892 data[2] == NULL || strlen(data[0]) == 0 || strlen(data[1]) == 0 ||
3893 strlen(data[2]) == 0) {
3894 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
3895 return;
3896 }
3897
3898 snprintf(cmd, sizeof(cmd), "AT+CPWD=\"%s\",\"%s\",\"%s\"", data[0], data[1],
3899 data[2]);
3900
3901 err = at_send_command(cmd, &p_response);
3902 if (err < 0 || p_response->success == 0) {
3903 goto error;
3904 }
3905 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
3906 at_response_free(p_response);
3907 return;
3908
3909 error:
3910 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
3911 at_response_free(p_response);
3912 }
3913
3914 static void requestFacilityLock(int request, char **data,
3915 size_t datalen, RIL_Token t) {
3916 int err = -1;
3917 int status = 0;
3918 int serviceClass = 0;
3919 int remainTimes = 10;
3920 char cmd[128] = {0};
3921 char *line = NULL;
3922 ATLine *p_cur = NULL;
3923 ATResponse *p_response = NULL;
3924 RIL_Errno errnoType = RIL_E_GENERIC_FAILURE;
3925
3926 char *type = data[0];
3927
3928 if (datalen != 5 * sizeof(char *)) {
3929 goto error;
3930 }
3931 if (data[0] == NULL || data[1] == NULL ||
3932 (data[2] == NULL && request == RIL_REQUEST_SET_FACILITY_LOCK) ||
3933 strlen(data[0]) == 0 || strlen(data[1]) == 0 ||
3934 (request == RIL_REQUEST_SET_FACILITY_LOCK && strlen(data[2]) == 0 )) {
3935 errnoType = RIL_E_INVALID_ARGUMENTS;
3936 RLOGE("FacilityLock invalid arguments");
3937 goto error;
3938 }
3939
3940 serviceClass = atoi(data[3]);
3941 if (serviceClass == 0) {
3942 snprintf(cmd, sizeof(cmd), "AT+CLCK=\"%s\",%c,\"%s\"", data[0], *data[1],
3943 data[2]);
3944 } else {
3945 snprintf(cmd, sizeof(cmd), "AT+CLCK=\"%s\",%c,\"%s\",%s", data[0],
3946 *data[1], data[2], data[3]);
3947 }
3948
3949 if (*data[1] == '2') { // query status
3950 err = at_send_command_multiline(cmd, "+CLCK: ", &p_response);
3951 if (err < 0 || p_response->success == 0) {
3952 goto error;
3953 }
3954 line = p_response->p_intermediates->line;
3955
3956 err = at_tok_start(&line);
3957 if (err < 0) goto error;
3958
3959 err = at_tok_nextint(&line, &status);
3960 if (err < 0) goto error;
3961
3962 RIL_onRequestComplete(t, RIL_E_SUCCESS, &status, sizeof(int));
3963 at_response_free(p_response);
3964 return;
3965 } else { // unlock/lock this facility
3966 err = at_send_command(cmd, &p_response);
3967 if (err < 0 || p_response->success == 0) {
3968 errnoType = RIL_E_PASSWORD_INCORRECT;
3969 goto error;
3970 }
3971 errnoType = RIL_E_SUCCESS;
3972 }
3973
3974 error:
3975 if (!strcmp(data[0], "SC")) {
3976 remainTimes = getSimlockRemainTimes("SIM PIN");
3977 } else if (!strcmp(data[0], "FD")) {
3978 remainTimes = getSimlockRemainTimes("SIM PIN2");
3979 } else {
3980 remainTimes = 1;
3981 }
3982
3983 RIL_onRequestComplete(t, errnoType, &remainTimes, sizeof(remainTimes));
3984 at_response_free(p_response);
3985 }
3986
3987 static void requestSetSmscAddress(void *data, size_t datalen, RIL_Token t)
3988 {
3989 ATResponse *p_response = NULL;
3990 char cmd[64] = {0};
3991 int err = -1;
3992
3993 if (getSIMStatus() != SIM_READY) {
3994 RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
3995 return;
3996 }
3997
3998 if (data == NULL || strlen(data) == 0) {
3999 RLOGE("SET_SMSC_ADDRESS invalid address: %s", (char *)data);
4000 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4001 return;
4002 }
4003
4004 snprintf(cmd, sizeof(cmd), "AT+CSCA=%s,%d", (char *)data, (int)datalen);
4005
4006 err = at_send_command_singleline(cmd, "+CSCA:", &p_response);
4007 if (err < 0 || p_response->success == 0) {
4008 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4009 } else {
4010 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4011 }
4012 at_response_free(p_response);
4013 }
4014
4015 static void requestGetSmscAddress(void *data, size_t datalen, RIL_Token t)
4016 {
4017 RIL_UNUSED_PARM(data);
4018 RIL_UNUSED_PARM(datalen);
4019
4020 ATResponse *p_response = NULL;
4021 int err = -1;
4022 char *decidata = NULL;
4023
4024 err = at_send_command_singleline( "AT+CSCA?", "+CSCA:", &p_response);
4025 if (err < 0 || p_response->success == 0) {
4026 goto error;
4027 }
4028
4029 char *line = p_response->p_intermediates->line;
4030 err = at_tok_start(&line);
4031 if (err < 0) goto error;
4032
4033 err = at_tok_nextstr(&line, &decidata);
4034 if (err < 0) goto error;
4035
4036 RIL_onRequestComplete(t, RIL_E_SUCCESS, decidata, strlen(decidata) + 1);
4037 at_response_free(p_response);
4038 return;
4039
4040 error:
4041 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4042 at_response_free(p_response);
4043 }
4044
4045 static void setGsmBroadcastConfigData(int from, int to, int id, int outStrSize, char *outStr) {
4046 if (from < 0 || from > 0xffff || to < 0 || to > 0xffff) {
4047 RLOGE("setGsmBroadcastConfig data is invalid, [%d, %d]", from, to);
4048 return;
4049 }
4050
4051 if (id != 0) {
4052 strlcat(outStr, ",", outStrSize);
4053 }
4054
4055 int len = strlen(outStr);
4056 if (from == to) {
4057 snprintf(outStr + len, outStrSize - len, "%d", from);
4058 } else {
4059 snprintf(outStr + len, outStrSize - len, "%d-%d", from, to);
4060 }
4061 }
4062
4063 static void requestSetSmsBroadcastConfig(void *data, size_t datalen,
4064 RIL_Token t) {
4065 int i = 0;
4066 int count = datalen / sizeof(RIL_GSM_BroadcastSmsConfigInfo *);
4067 int size = count * 16;
4068 char cmd[256] = {0};
4069 char *channel = (char *)alloca(size);
4070 char *languageId = (char *)alloca(size);
4071 ATResponse *p_response = NULL;
4072 RIL_GSM_BroadcastSmsConfigInfo **pGsmBci =
4073 (RIL_GSM_BroadcastSmsConfigInfo **)data;
4074 RIL_GSM_BroadcastSmsConfigInfo gsmBci = {0};
4075
4076 memset(channel, 0, size);
4077 memset(languageId, 0, size);
4078 RLOGD("requestSetGsmBroadcastConfig %zu, count %d", datalen, count);
4079
4080 for (i = 0; i < count; i++) {
4081 gsmBci = *(pGsmBci[i]);
4082 setGsmBroadcastConfigData(gsmBci.fromServiceId, gsmBci.toServiceId, i,
4083 size, channel);
4084 setGsmBroadcastConfigData(gsmBci.fromCodeScheme, gsmBci.toCodeScheme, i,
4085 size, languageId);
4086 }
4087
4088 snprintf(cmd, sizeof(cmd), "AT+CSCB=%d,\"%s\",\"%s\"",
4089 (*pGsmBci[0]).selected ? 0 : 1, channel, languageId);
4090 int err = at_send_command_singleline( cmd, "+CSCB:", &p_response);
4091
4092 if (err < 0 || p_response->success == 0) {
4093 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4094 } else {
4095 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4096 }
4097 at_response_free(p_response);
4098 }
4099
4100 static void requestGetSmsBroadcastConfig(void *data, size_t datalen,
4101 RIL_Token t) {
4102 RIL_UNUSED_PARM(data);
4103 RIL_UNUSED_PARM(datalen);
4104
4105 ATResponse *p_response = NULL;
4106 int err = -1, mode, commas = 0, i = 0;
4107 char *line = NULL;
4108 char *serviceIds = NULL, *codeSchemes = NULL, *p = NULL;
4109 char *serviceId = NULL, *codeScheme = NULL;
4110
4111 err = at_send_command_singleline("AT+CSCB?", "+CSCB:", &p_response);
4112 if (err < 0 || p_response->success == 0) {
4113 goto error;
4114 }
4115
4116 line = p_response->p_intermediates->line;
4117 err = at_tok_start(&line);
4118 if (err < 0) goto error;
4119
4120 err = at_tok_nextint(&line, &mode);
4121 if (err < 0) goto error;
4122
4123 err = at_tok_nextstr(&line, &serviceIds);
4124 if (err < 0) goto error;
4125
4126 err = at_tok_nextstr(&line, &codeSchemes);
4127 if (err < 0) goto error;
4128
4129 for (p = serviceIds; *p != '\0'; p++) {
4130 if (*p == ',') {
4131 commas++;
4132 }
4133 }
4134 RIL_GSM_BroadcastSmsConfigInfo **pGsmBci =
4135 (RIL_GSM_BroadcastSmsConfigInfo **)alloca((commas + 1) *
4136 sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
4137 memset(pGsmBci, 0, (commas + 1) * sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
4138
4139 for (i = 0; i < commas + 1; i++) {
4140 pGsmBci[i] = (RIL_GSM_BroadcastSmsConfigInfo *)alloca(
4141 sizeof(RIL_GSM_BroadcastSmsConfigInfo));
4142 memset(pGsmBci[i], 0, sizeof(RIL_GSM_BroadcastSmsConfigInfo));
4143
4144 err = at_tok_nextstr(&serviceIds, &serviceId);
4145 if (err < 0) goto error;
4146 pGsmBci[i]->toServiceId = pGsmBci[i]->fromServiceId = 0;
4147 if (strstr(serviceId, "-")) {
4148 sscanf(serviceId,"%d-%d", &pGsmBci[i]->fromServiceId,
4149 &pGsmBci[i]->toServiceId);
4150 }
4151
4152 err = at_tok_nextstr(&codeSchemes, &codeScheme);
4153 if (err < 0) goto error;
4154 pGsmBci[i]->toCodeScheme = pGsmBci[i]->fromCodeScheme = 0;
4155 if (strstr(codeScheme, "-")) {
4156 sscanf(codeScheme, "%d-%d", &pGsmBci[i]->fromCodeScheme,
4157 &pGsmBci[i]->toCodeScheme);
4158 }
4159
4160 pGsmBci[i]->selected = (mode == 0 ? false : true);
4161 }
4162 RIL_onRequestComplete(t, RIL_E_SUCCESS, pGsmBci,
4163 (commas + 1) * sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
4164 at_response_free(p_response);
4165 return;
4166
4167 error:
4168 at_response_free(p_response);
4169 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4170 }
4171
4172 /**
4173 * <AcT>: integer type; access technology selected
4174 * 0 GSM
4175 * 1 GSM Compact
4176 * 2 UTRAN
4177 * 3 GSM w/EGPRS (see NOTE 1)
4178 * 4 UTRAN w/HSDPA (see NOTE 2)
4179 * 5 UTRAN w/HSUPA (see NOTE 2)
4180 * 6 UTRAN w/HSDPA and HSUPA (see NOTE 2)
4181 * 7 E-UTRAN
4182 * 8 EC-GSM-IoT (A/Gb mode) (see NOTE 3)
4183 * 9 E-UTRAN (NB-S1 mode) (see NOTE 4)
4184 * 10 E-UTRA connected to a 5GCN (see NOTE 5)
4185 * 11 NR connected to a 5GCN (see NOTE 5)
4186 * 12 NG-RAN
4187 * 13 E-UTRA-NR dual connectivity (see NOTE 6)
4188 */
4189 int mapRadioAccessNetworkToTech(RIL_RadioAccessNetworks network) {
4190 switch (network) {
4191 case GERAN: // GSM EDGE
4192 return 3;
4193 case UTRAN:
4194 return 6;
4195 case EUTRAN:
4196 return 7;
4197 case NGRAN:
4198 return 11;
4199 default:
4200 return 7; // LTE
4201 }
4202 }
4203
4204 static void requestSetNetworlSelectionManual(void *data, RIL_Token t) {
4205 int err = -1;
4206 char cmd[64] = {0};
4207 ATResponse *p_response = NULL;
4208 RIL_NetworkOperator *operator = (RIL_NetworkOperator *)data;
4209
4210 if (operator->act != UNKNOWN) {
4211 snprintf(cmd, sizeof(cmd), "AT+COPS=1,2,\"%s\"", operator->operatorNumeric);
4212 } else {
4213 snprintf(cmd, sizeof(cmd), "AT+COPS=1,2,\"%s\",%d",
4214 operator->operatorNumeric, operator->act);
4215 }
4216 err = at_send_command(cmd, &p_response);
4217 if (err < 0 || p_response->success == 0) {
4218 goto error;
4219 }
4220
4221 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4222 at_response_free(p_response);
4223 return;
4224
4225 error:
4226 if (p_response != NULL &&
4227 !strcmp(p_response->finalResponse, "+CME ERROR: 30")) {
4228 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
4229 } else {
4230 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4231 }
4232 at_response_free(p_response);
4233 }
4234
4235 static void requestStkServiceIsRunning(RIL_Token t)
4236 {
4237 int err = -1;
4238 ATResponse *p_response = NULL;
4239
4240 s_stkServiceRunning = true;
4241 if (NULL != s_stkUnsolResponse) {
4242 RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND,
4243 s_stkUnsolResponse, strlen(s_stkUnsolResponse) + 1);
4244 free(s_stkUnsolResponse);
4245 s_stkUnsolResponse = NULL;
4246 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4247 return;
4248 }
4249
4250 err = at_send_command_singleline("AT+CUSATD?", "+CUSATD:", &p_response);
4251
4252 if (err < 0 || p_response->success == 0) {
4253 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4254 } else {
4255 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4256 }
4257 at_response_free(p_response);
4258 }
4259
4260 static void requestStkSendEnvelope(void *data, RIL_Token t)
4261 {
4262 int ret = -1, err = -1;
4263 char cmd[128] = {0};
4264 ATResponse *p_response = NULL;
4265
4266 if (data == NULL || strlen((char *)data) == 0) {
4267 RLOGE("STK sendEnvelope data is invalid");
4268 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
4269 return;
4270 }
4271
4272 snprintf(cmd, sizeof(cmd), "AT+CUSATE=\"%s\"", (char *)data);
4273 err = at_send_command_singleline(cmd, "+CUSATE:", &p_response);
4274 if (err < 0 || p_response->success == 0) {
4275 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4276 } else {
4277 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4278
4279 // type of alpha data is 85, such as 850C546F6F6C6B6974204D656E75
4280 char *p = strstr(p_response->p_intermediates->line, "85");
4281 if (p != NULL) {
4282 char alphaStrHexLen[3] = {0};
4283 char alphaStr[1024] = {0};
4284 uint8_t *alphaBytes = NULL;
4285 int len = 0;
4286
4287 p = p + strlen("85");
4288 strncpy(alphaStrHexLen, p, 2);
4289 len = strtoul(alphaStrHexLen, NULL, 16);
4290 strncpy(alphaStr, p + 2, len * 2);
4291 alphaBytes = convertHexStringToBytes(alphaStr, strlen(alphaStr));
4292 RIL_onUnsolicitedResponse(RIL_UNSOL_STK_CC_ALPHA_NOTIFY, alphaBytes,
4293 strlen((char *)alphaBytes));
4294 free(alphaBytes);
4295 }
4296 }
4297 at_response_free(p_response);
4298 }
4299
4300 static void requestStksendTerminalResponse(void *data, RIL_Token t)
4301 {
4302 int ret = -1, err = -1;
4303 char cmd[128] = {0};
4304 ATResponse *p_response = NULL;
4305
4306 if (data == NULL || strlen((char *)data) == 0) {
4307 RLOGE("STK sendTerminalResponse data is invalid");
4308 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
4309 return;
4310 }
4311
4312 snprintf(cmd, sizeof(cmd), "AT+CUSATT=\"%s\"", (char *)data);
4313 err = at_send_command_singleline( cmd, "+CUSATT:", &p_response);
4314 if (err < 0 || p_response->success == 0) {
4315 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4316 } else {
4317 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4318 }
4319 at_response_free(p_response);
4320 }
4321
4322 static void requestEccDial(void *data, RIL_Token t) {
4323 char cmd[64] = {0};
4324 const char *clir = NULL;
4325 int err = -1;
4326 RIL_EmergencyDial *p_eccDial = (RIL_EmergencyDial *)data;
4327
4328 switch (p_eccDial->dialInfo.clir) {
4329 case 0: /* subscription default */
4330 clir = "";
4331 break;
4332 case 1: /* invocation */
4333 clir = "I";
4334 break;
4335 case 2: /* suppression */
4336 clir = "i";
4337 break;
4338 default:
4339 break;
4340 }
4341
4342 if (p_eccDial->routing == ROUTING_MERGENCY ||
4343 p_eccDial->routing == ROUTING_UNKNOWN) {
4344 if (p_eccDial->categories == CATEGORY_UNSPECIFIED) {
4345 snprintf(cmd, sizeof(cmd), "ATD%s@,#%s;", p_eccDial->dialInfo.address, clir);
4346 } else {
4347 snprintf(cmd, sizeof(cmd), "ATD%s@%d,#%s;", p_eccDial->dialInfo.address,
4348 p_eccDial->categories, clir);
4349 }
4350 } else { // ROUTING_NORMAL
4351 snprintf(cmd, sizeof(cmd), "ATD%s%s;", p_eccDial->dialInfo.address, clir);
4352 }
4353
4354 err = at_send_command(cmd, NULL);
4355 if (err != 0) goto error;
4356
4357 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4358 return;
4359
4360 error:
4361 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4362 }
4363
4364 static void requestStartKeepalive(void* data, size_t datalen __unused, RIL_Token t) {
4365 RIL_KeepaliveRequest* kaRequest = (RIL_KeepaliveRequest*)data;
4366 if (kaRequest->cid > MAX_PDP) {
4367 RLOGE("Invalid cid for keepalive!");
4368 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
4369 return;
4370 }
4371 RIL_KeepaliveStatus resp;
4372 resp.sessionHandle = __sync_fetch_and_add(&s_session_handle, 1);
4373 resp.code = KEEPALIVE_ACTIVE;
4374 RIL_onRequestComplete(t, RIL_E_SUCCESS, &resp, sizeof(resp));
4375 }
4376
4377 void getConfigSlotStatus(RIL_SimSlotStatus_V1_2 *pSimSlotStatus) {
4378 if (pSimSlotStatus == NULL) {
4379 return;
4380 }
4381 if (getSIMStatus() == SIM_ABSENT) {
4382 pSimSlotStatus->base.cardState = RIL_CARDSTATE_ABSENT;
4383 } else {
4384 pSimSlotStatus->base.cardState = RIL_CARDSTATE_PRESENT;
4385 }
4386 // TODO: slot state is always active now
4387 pSimSlotStatus->base.slotState = SLOT_STATE_ACTIVE;
4388
4389 if (pSimSlotStatus->base.cardState != RIL_CARDSTATE_ABSENT) {
4390 pSimSlotStatus->base.atr = "";
4391 pSimSlotStatus->base.iccid = (char *)calloc(64, sizeof(char));
4392 getIccId(pSimSlotStatus->base.iccid, 64);
4393 }
4394
4395 pSimSlotStatus->base.logicalSlotId = 0;
4396 pSimSlotStatus->eid = "";
4397 }
4398
4399 void sendUnsolNetworkScanResult() {
4400 RIL_NetworkScanResult scanr;
4401 memset(&scanr, 0, sizeof(scanr));
4402 scanr.status = COMPLETE;
4403 scanr.error = RIL_E_SUCCESS;
4404 scanr.network_infos = NULL;
4405 scanr.network_infos_length = 0;
4406 RIL_onUnsolicitedResponse(RIL_UNSOL_NETWORK_SCAN_RESULT, &scanr, sizeof(scanr));
4407 }
4408
4409 void onIccSlotStatus(RIL_Token t) {
4410 RIL_SimSlotStatus_V1_2 *pSimSlotStatusList =
4411 (RIL_SimSlotStatus_V1_2 *)calloc(SIM_COUNT, sizeof(RIL_SimSlotStatus_V1_2));
4412
4413 getConfigSlotStatus(pSimSlotStatusList);
4414
4415 if (t == NULL) {
4416 RIL_onUnsolicitedResponse(RIL_UNSOL_CONFIG_ICC_SLOT_STATUS, pSimSlotStatusList,
4417 SIM_COUNT * sizeof(RIL_SimSlotStatus_V1_2));
4418 } else {
4419 RIL_onRequestComplete(t, RIL_E_SUCCESS, pSimSlotStatusList,
4420 SIM_COUNT * sizeof(RIL_SimSlotStatus_V1_2));
4421 }
4422
4423 if (pSimSlotStatusList != NULL) {
4424 free(pSimSlotStatusList->base.iccid);
4425 free(pSimSlotStatusList);
4426 }
4427 }
4428
4429 /*** Callback methods from the RIL library to us ***/
4430
4431 /**
4432 * Call from RIL to us to make a RIL_REQUEST
4433 *
4434 * Must be completed with a call to RIL_onRequestComplete()
4435 *
4436 * RIL_onRequestComplete() may be called from any thread, before or after
4437 * this function returns.
4438 *
4439 * Because onRequest function could be called from multiple different thread,
4440 * we must ensure that the underlying at_send_command_* function
4441 * is atomic.
4442 */
4443 static void
4444 onRequest (int request, void *data, size_t datalen, RIL_Token t)
4445 {
4446 ATResponse *p_response;
4447 int err;
4448
4449 RLOGD("onRequest: %s, sState: %d", requestToString(request), sState);
4450
4451 /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
4452 * when RADIO_STATE_UNAVAILABLE.
4453 */
4454 if (sState == RADIO_STATE_UNAVAILABLE
4455 && request != RIL_REQUEST_GET_SIM_STATUS
4456 ) {
4457 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
4458 return;
4459 }
4460
4461 /* Ignore all non-power requests when RADIO_STATE_OFF
4462 * (except RIL_REQUEST_GET_SIM_STATUS)
4463 */
4464 if (sState == RADIO_STATE_OFF) {
4465 switch(request) {
4466 case RIL_REQUEST_BASEBAND_VERSION:
4467 case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
4468 case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE:
4469 case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE:
4470 case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
4471 case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
4472 case RIL_REQUEST_CDMA_SUBSCRIPTION:
4473 case RIL_REQUEST_DEVICE_IDENTITY:
4474 case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
4475 case RIL_REQUEST_GET_ACTIVITY_INFO:
4476 case RIL_REQUEST_GET_CARRIER_RESTRICTIONS:
4477 case RIL_REQUEST_GET_CURRENT_CALLS:
4478 case RIL_REQUEST_GET_IMEI:
4479 case RIL_REQUEST_GET_MUTE:
4480 case RIL_REQUEST_SET_MUTE:
4481 case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS:
4482 case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
4483 case RIL_REQUEST_GET_RADIO_CAPABILITY:
4484 case RIL_REQUEST_GET_SIM_STATUS:
4485 case RIL_REQUEST_NV_RESET_CONFIG:
4486 case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE:
4487 case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
4488 case RIL_REQUEST_QUERY_TTY_MODE:
4489 case RIL_REQUEST_RADIO_POWER:
4490 case RIL_REQUEST_SET_BAND_MODE:
4491 case RIL_REQUEST_SET_CARRIER_RESTRICTIONS:
4492 case RIL_REQUEST_SET_LOCATION_UPDATES:
4493 case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
4494 case RIL_REQUEST_SET_TTY_MODE:
4495 case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
4496 case RIL_REQUEST_STOP_LCE:
4497 case RIL_REQUEST_VOICE_RADIO_TECH:
4498 case RIL_REQUEST_SCREEN_STATE:
4499 // Process all the above, even though the radio is off
4500 break;
4501
4502 default:
4503 // For all others, say NOT_AVAILABLE because the radio is off
4504 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
4505 return;
4506 }
4507 }
4508
4509 switch (request) {
4510 case RIL_REQUEST_GET_SIM_STATUS: {
4511 RIL_CardStatus_v1_5 *p_card_status;
4512 char *p_buffer;
4513 int buffer_size;
4514
4515 int result = getCardStatus(&p_card_status);
4516 if (result == RIL_E_SUCCESS) {
4517 p_buffer = (char *)p_card_status;
4518 buffer_size = sizeof(*p_card_status);
4519 } else {
4520 p_buffer = NULL;
4521 buffer_size = 0;
4522 }
4523 RIL_onRequestComplete(t, result, p_buffer, buffer_size);
4524 freeCardStatus(p_card_status);
4525 break;
4526 }
4527 case RIL_REQUEST_GET_CURRENT_CALLS:
4528 requestGetCurrentCalls(data, datalen, t);
4529 break;
4530 case RIL_REQUEST_DIAL:
4531 requestDial(data, datalen, t);
4532 break;
4533 case RIL_REQUEST_HANGUP:
4534 requestHangup(data, datalen, t);
4535 break;
4536 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
4537 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
4538 case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
4539 case RIL_REQUEST_CONFERENCE:
4540 case RIL_REQUEST_UDUB:
4541 requestCallSelection(data, datalen, t, request);
4542 break;
4543 case RIL_REQUEST_ANSWER:
4544 at_send_command("ATA", NULL);
4545
4546 #ifdef WORKAROUND_ERRONEOUS_ANSWER
4547 s_expectAnswer = 1;
4548 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
4549
4550 if (getSIMStatus() != SIM_READY) {
4551 RIL_onRequestComplete(t, RIL_E_MODEM_ERR, NULL, 0);
4552 } else {
4553 // Success or failure is ignored by the upper layer here.
4554 // It will call GET_CURRENT_CALLS and determine success that way.
4555 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4556 }
4557 break;
4558
4559 case RIL_REQUEST_SEPARATE_CONNECTION:
4560 {
4561 char cmd[12];
4562 int party = ((int*)data)[0];
4563
4564 if (getSIMStatus() == SIM_ABSENT) {
4565 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
4566 return;
4567 }
4568 // Make sure that party is in a valid range.
4569 // (Note: The Telephony middle layer imposes a range of 1 to 7.
4570 // It's sufficient for us to just make sure it's single digit.)
4571 if (party > 0 && party < 10) {
4572 sprintf(cmd, "AT+CHLD=2%d", party);
4573 at_send_command(cmd, NULL);
4574 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4575 } else {
4576 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4577 }
4578 }
4579 break;
4580
4581 case RIL_REQUEST_SIGNAL_STRENGTH:
4582 requestSignalStrength(data, datalen, t);
4583 break;
4584 case RIL_REQUEST_VOICE_REGISTRATION_STATE:
4585 case RIL_REQUEST_DATA_REGISTRATION_STATE:
4586 requestRegistrationState(request, data, datalen, t);
4587 break;
4588 case RIL_REQUEST_OPERATOR:
4589 requestOperator(data, datalen, t);
4590 break;
4591 case RIL_REQUEST_RADIO_POWER:
4592 requestRadioPower(data, datalen, t);
4593 break;
4594 case RIL_REQUEST_DTMF: {
4595 char c = ((char *)data)[0];
4596 char *cmd;
4597 asprintf(&cmd, "AT+VTS=%c", (int)c);
4598 at_send_command(cmd, NULL);
4599 free(cmd);
4600 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4601 break;
4602 }
4603 case RIL_REQUEST_SEND_SMS:
4604 case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
4605 requestSendSMS(data, datalen, t);
4606 break;
4607 case RIL_REQUEST_CDMA_SEND_SMS:
4608 requestCdmaSendSMS(data, datalen, t);
4609 break;
4610 case RIL_REQUEST_IMS_SEND_SMS:
4611 requestImsSendSMS(data, datalen, t);
4612 break;
4613 case RIL_REQUEST_SIM_OPEN_CHANNEL:
4614 requestSimOpenChannel(data, datalen, t);
4615 break;
4616 case RIL_REQUEST_SIM_CLOSE_CHANNEL:
4617 requestSimCloseChannel(data, datalen, t);
4618 break;
4619 case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL:
4620 requestSimTransmitApduChannel(data, datalen, t);
4621 break;
4622 case RIL_REQUEST_SIM_AUTHENTICATION: {
4623 RIL_SimAuthentication *sim_auth = (RIL_SimAuthentication *)data;
4624 if ((sim_auth->authContext == AUTH_CONTEXT_EAP_SIM ||
4625 sim_auth->authContext == AUTH_CONTEXT_EAP_AKA) &&
4626 sim_auth->authData != NULL) {
4627 requestSimAuthentication(sim_auth->authContext, sim_auth->authData, t);
4628 } else {
4629 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
4630 }
4631 break;
4632 }
4633 case RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC:
4634 requestTransmitApduBasic(data, datalen, t);
4635 break;
4636 case RIL_REQUEST_SETUP_DATA_CALL:
4637 requestSetupDataCall(data, datalen, t);
4638 break;
4639 case RIL_REQUEST_DEACTIVATE_DATA_CALL:
4640 requestDeactivateDataCall(data, t);
4641 break;
4642 case RIL_REQUEST_SMS_ACKNOWLEDGE:
4643 requestSMSAcknowledge(data, datalen, t);
4644 break;
4645
4646 case RIL_REQUEST_GET_IMSI:
4647 p_response = NULL;
4648 err = at_send_command_numeric("AT+CIMI", &p_response);
4649
4650 if (err < 0 || p_response->success == 0) {
4651 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4652 } else {
4653 RIL_onRequestComplete(t, RIL_E_SUCCESS,
4654 p_response->p_intermediates->line, sizeof(char *));
4655 }
4656 at_response_free(p_response);
4657 break;
4658
4659 case RIL_REQUEST_GET_IMEI:
4660 p_response = NULL;
4661 err = at_send_command_numeric("AT+CGSN", &p_response);
4662
4663 if (err < 0 || p_response->success == 0) {
4664 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4665 } else {
4666 RIL_onRequestComplete(t, RIL_E_SUCCESS,
4667 p_response->p_intermediates->line, sizeof(char *));
4668 }
4669 at_response_free(p_response);
4670 break;
4671
4672
4673 case RIL_REQUEST_SIM_IO:
4674 requestSIM_IO(data,datalen,t);
4675 break;
4676
4677 case RIL_REQUEST_SEND_USSD:
4678 requestSendUSSD(data, datalen, t);
4679 break;
4680
4681 case RIL_REQUEST_CANCEL_USSD:
4682 if (getSIMStatus() == SIM_ABSENT) {
4683 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
4684 break;
4685 }
4686 p_response = NULL;
4687 err = at_send_command_numeric("AT+CUSD=2", &p_response);
4688
4689 if (err < 0 || p_response->success == 0) {
4690 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4691 } else {
4692 RIL_onRequestComplete(t, RIL_E_SUCCESS,
4693 p_response->p_intermediates->line, sizeof(char *));
4694 }
4695 at_response_free(p_response);
4696 break;
4697
4698 case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
4699 if (getSIMStatus() == SIM_ABSENT) {
4700 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
4701 break;
4702 }
4703 p_response = NULL;
4704 err = at_send_command("AT+COPS=0", &p_response);
4705 if (err < 0 || p_response->success == 0) {
4706 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4707 } else {
4708 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4709 }
4710 at_response_free(p_response);
4711 break;
4712
4713 case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL:
4714 requestSetNetworlSelectionManual(data, t);
4715 break;
4716
4717 case RIL_REQUEST_DATA_CALL_LIST:
4718 requestDataCallList(data, datalen, t);
4719 break;
4720
4721 case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
4722 requestQueryNetworkSelectionMode(data, datalen, t);
4723 break;
4724
4725 case RIL_REQUEST_OEM_HOOK_RAW:
4726 // echo back data
4727 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
4728 break;
4729
4730
4731 case RIL_REQUEST_OEM_HOOK_STRINGS: {
4732 int i;
4733 const char ** cur;
4734
4735 RLOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
4736
4737
4738 for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
4739 i > 0 ; cur++, i --) {
4740 RLOGD("> '%s'", *cur);
4741 }
4742
4743 // echo back strings
4744 RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
4745 break;
4746 }
4747
4748 case RIL_REQUEST_WRITE_SMS_TO_SIM:
4749 requestWriteSmsToSim(data, datalen, t);
4750 break;
4751
4752 case RIL_REQUEST_DELETE_SMS_ON_SIM: {
4753 char * cmd;
4754 p_response = NULL;
4755 asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
4756 err = at_send_command(cmd, &p_response);
4757 free(cmd);
4758 if (err < 0 || p_response->success == 0) {
4759 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4760 } else {
4761 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4762 }
4763 at_response_free(p_response);
4764 break;
4765 }
4766
4767 case RIL_REQUEST_ENTER_SIM_PIN:
4768 case RIL_REQUEST_ENTER_SIM_PIN2:
4769 requestEnterSimPin(request, data, datalen, t);
4770 break;
4771
4772 case RIL_REQUEST_ENTER_SIM_PUK:
4773 case RIL_REQUEST_ENTER_SIM_PUK2:
4774 case RIL_REQUEST_CHANGE_SIM_PIN:
4775 requestChangeSimPin(request, data, datalen, t);
4776 break;
4777
4778 case RIL_REQUEST_CHANGE_SIM_PIN2:
4779 requestChangeSimPin2(data, datalen, t);
4780 break;
4781
4782 case RIL_REQUEST_IMS_REGISTRATION_STATE: {
4783 int reply[2];
4784 //0==unregistered, 1==registered
4785 reply[0] = s_ims_registered;
4786
4787 //to be used when changed to include service supporated info
4788 //reply[1] = s_ims_services;
4789
4790 // FORMAT_3GPP(1) vs FORMAT_3GPP2(2);
4791 reply[1] = s_ims_format;
4792
4793 RLOGD("IMS_REGISTRATION=%d, format=%d ",
4794 reply[0], reply[1]);
4795 if (reply[1] != -1) {
4796 RIL_onRequestComplete(t, RIL_E_SUCCESS, reply, sizeof(reply));
4797 } else {
4798 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4799 }
4800 break;
4801 }
4802
4803 case RIL_REQUEST_VOICE_RADIO_TECH:
4804 {
4805 int tech = techFromModemType(TECH(sMdmInfo));
4806 if (tech < 0 )
4807 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
4808 else
4809 RIL_onRequestComplete(t, RIL_E_SUCCESS, &tech, sizeof(tech));
4810 }
4811 break;
4812 case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
4813 requestSetPreferredNetworkType(request, data, datalen, t);
4814 break;
4815
4816 case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
4817 requestGetPreferredNetworkType(request, data, datalen, t);
4818 break;
4819
4820 case RIL_REQUEST_GET_CELL_INFO_LIST:
4821 requestGetCellInfoList(data, datalen, t);
4822 break;
4823
4824 case RIL_REQUEST_GET_CELL_INFO_LIST_1_6:
4825 requestGetCellInfoList_1_6(data, datalen, t);
4826 break;
4827
4828 case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
4829 requestSetCellInfoListRate(data, datalen, t);
4830 break;
4831
4832 case RIL_REQUEST_GET_HARDWARE_CONFIG:
4833 requestGetHardwareConfig(data, datalen, t);
4834 break;
4835
4836 case RIL_REQUEST_SHUTDOWN:
4837 requestShutdown(t);
4838 break;
4839
4840 case RIL_REQUEST_QUERY_TTY_MODE:
4841 requestGetTtyMode(data, datalen, t);
4842 break;
4843
4844 case RIL_REQUEST_GET_RADIO_CAPABILITY:
4845 requestGetRadioCapability(data, datalen, t);
4846 break;
4847
4848 case RIL_REQUEST_SET_RADIO_CAPABILITY:
4849 requestSetRadioCapability(data, datalen, t);
4850 break;
4851
4852 case RIL_REQUEST_GET_MUTE:
4853 requestGetMute(data, datalen, t);
4854 break;
4855
4856 case RIL_REQUEST_SET_MUTE:
4857 requestSetMute(data, datalen, t);
4858 break;
4859
4860 case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: {
4861 int size = 5;
4862 int response[20] = {0};
4863 for (int i = 1; i <= size; i++) {
4864 response[i] = i - 1;
4865 }
4866 RIL_onRequestComplete(t, RIL_E_SUCCESS, response, (size + 1) * sizeof(int));
4867 break;
4868 }
4869
4870 case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
4871 case RIL_REQUEST_ALLOW_DATA:
4872 case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION:
4873 case RIL_REQUEST_SET_BAND_MODE:
4874 case RIL_REQUEST_SET_CARRIER_RESTRICTIONS:
4875 case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS:
4876 case RIL_REQUEST_SET_LOCATION_UPDATES:
4877 case RIL_REQUEST_SET_TTY_MODE:
4878 case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE:
4879 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4880 break;
4881
4882 case RIL_REQUEST_NV_RESET_CONFIG:
4883 requestNvResetConfig(data, datalen, t);
4884 break;
4885
4886 case RIL_REQUEST_BASEBAND_VERSION:
4887 requestCdmaBaseBandVersion(request, data, datalen, t);
4888 break;
4889
4890 case RIL_REQUEST_DEVICE_IDENTITY:
4891 requestDeviceIdentity(request, data, datalen, t);
4892 break;
4893
4894 case RIL_REQUEST_CDMA_SUBSCRIPTION:
4895 requestCdmaSubscription(request, data, datalen, t);
4896 break;
4897
4898 case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
4899 requestCdmaGetSubscriptionSource(request, data, datalen, t);
4900 break;
4901
4902 case RIL_REQUEST_START_LCE:
4903 case RIL_REQUEST_STOP_LCE:
4904 case RIL_REQUEST_PULL_LCEDATA:
4905 if (getSIMStatus() == SIM_ABSENT) {
4906 RIL_onRequestComplete(t, RIL_E_SIM_ABSENT, NULL, 0);
4907 } else {
4908 RIL_onRequestComplete(t, RIL_E_LCE_NOT_SUPPORTED, NULL, 0);
4909 }
4910 break;
4911
4912 case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:
4913 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
4914 requestCdmaGetRoamingPreference(request, data, datalen, t);
4915 } else {
4916 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
4917 }
4918 break;
4919
4920 case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
4921 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
4922 requestCdmaSetSubscriptionSource(request, data, datalen, t);
4923 } else {
4924 // VTS tests expect us to silently do nothing
4925 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4926 }
4927 break;
4928
4929 case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
4930 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
4931 requestCdmaSetRoamingPreference(request, data, datalen, t);
4932 } else {
4933 // VTS tests expect us to silently do nothing
4934 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4935 }
4936 break;
4937
4938 case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
4939 if (TECH_BIT(sMdmInfo) == MDM_CDMA) {
4940 requestExitEmergencyMode(data, datalen, t);
4941 } else {
4942 // VTS tests expect us to silently do nothing
4943 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4944 }
4945 break;
4946
4947 case RIL_REQUEST_GET_ACTIVITY_INFO:
4948 requestGetActivityInfo(data, datalen, t);
4949 break;
4950
4951 case RIL_REQUEST_SCREEN_STATE:
4952 requestScreenState(data, t);
4953 break;
4954
4955 case RIL_REQUEST_SET_DATA_PROFILE:
4956 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
4957 break;
4958
4959 case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS:
4960 requestQueryCallForward(data, datalen, t);
4961 break;
4962
4963 case RIL_REQUEST_SET_CALL_FORWARD:
4964 requestSetCallForward(data, datalen, t);
4965 break;
4966
4967 case RIL_REQUEST_QUERY_CLIP:
4968 requestQueryClip(data, datalen, t);
4969 break;
4970
4971 case RIL_REQUEST_GET_CLIR:
4972 requestQueryClir(data, datalen, t);
4973 break;
4974
4975 case RIL_REQUEST_SET_CLIR:
4976 requestSetClir(data, datalen, t);
4977 break;
4978
4979 case RIL_REQUEST_QUERY_CALL_WAITING:
4980 requestQueryCallWaiting(data, datalen, t);
4981 break;
4982
4983 case RIL_REQUEST_SET_CALL_WAITING:
4984 requestSetCallWaiting(data, datalen, t);
4985 break;
4986
4987 case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION:
4988 requestSetSuppServiceNotifications(data, datalen, t);
4989 break;
4990
4991 case RIL_REQUEST_CHANGE_BARRING_PASSWORD:
4992 requestChangeBarringPassword(data, datalen, t);
4993 break;
4994
4995 case RIL_REQUEST_QUERY_FACILITY_LOCK: {
4996 char *lockData[4];
4997 lockData[0] = ((char **)data)[0];
4998 lockData[1] = "2";
4999 lockData[2] = ((char **)data)[1];
5000 lockData[3] = ((char **)data)[2];
5001 requestFacilityLock(request, lockData, datalen + sizeof(char *), t);
5002 break;
5003 }
5004
5005 case RIL_REQUEST_SET_FACILITY_LOCK:
5006 requestFacilityLock(request, data, datalen, t);
5007 break;
5008
5009 case RIL_REQUEST_GET_SMSC_ADDRESS:
5010 requestGetSmscAddress(data, datalen, t);
5011 break;
5012
5013 case RIL_REQUEST_SET_SMSC_ADDRESS:
5014 requestSetSmscAddress(data, datalen, t);
5015 break;
5016
5017 case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG:
5018 requestSetSmsBroadcastConfig(data, datalen, t);
5019 break;
5020
5021 case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG:
5022 requestGetSmsBroadcastConfig(data, datalen, t);
5023 break;
5024
5025 case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
5026 requestStkServiceIsRunning(t);
5027 break;
5028
5029 case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
5030 requestStkSendEnvelope(data, t);
5031 break;
5032
5033 case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
5034 requestStksendTerminalResponse(data, t);
5035 break;
5036
5037 // New requests after P.
5038 case RIL_REQUEST_START_NETWORK_SCAN:
5039 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5040 // send unsol network scan results after a short while
5041 RIL_requestTimedCallback (sendUnsolNetworkScanResult, NULL, &TIMEVAL_SIMPOLL);
5042 break;
5043 case RIL_REQUEST_GET_MODEM_STACK_STATUS:
5044 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5045 break;
5046 case RIL_REQUEST_ENABLE_MODEM:
5047 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5048 break;
5049 case RIL_REQUEST_EMERGENCY_DIAL:
5050 requestEccDial(data, t);
5051 break;
5052 case RIL_REQUEST_SET_SIM_CARD_POWER:
5053 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5054 break;
5055 case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE_BITMAP:
5056 requestSetPreferredNetworkType(request, data, datalen, t);
5057 break;
5058 case RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP:
5059 requestSetPreferredNetworkType(request, data, datalen, t);
5060 break;
5061 case RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP:
5062 requestGetPreferredNetworkType(request, data, datalen, t);
5063 case RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY:
5064 if (data == NULL || datalen != sizeof(int)) {
5065 RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
5066 break;
5067 }
5068 int nrDualConnectivityState = *(int *)(data);
5069 isNrDualConnectivityEnabled = (nrDualConnectivityState == 1) ? true : false;
5070 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5071 break;
5072 case RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED:
5073 RIL_onRequestComplete(t, RIL_E_SUCCESS, &isNrDualConnectivityEnabled,
5074 sizeof(isNrDualConnectivityEnabled));
5075 break;
5076 case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP:
5077 requestGetPreferredNetworkType(request, data, datalen, t);
5078 break;
5079 case RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS:
5080 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5081 break;
5082 case RIL_REQUEST_GET_SLICING_CONFIG:
5083 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5084 break;
5085 case RIL_REQUEST_GET_CARRIER_RESTRICTIONS:
5086 requestGetCarrierRestrictions(data, datalen, t);
5087
5088 // Radio config requests
5089 case RIL_REQUEST_CONFIG_GET_SLOT_STATUS:
5090 RIL_requestTimedCallback(onIccSlotStatus, (void *)t, NULL);
5091 break;
5092 case RIL_REQUEST_CONFIG_SET_SLOT_MAPPING:
5093 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5094 break;
5095 case RIL_REQUEST_CONFIG_GET_PHONE_CAPABILITY: {
5096 RIL_PhoneCapability *phoneCapability =
5097 (RIL_PhoneCapability *)alloca(sizeof(RIL_PhoneCapability));
5098 phoneCapability->maxActiveData = 1;
5099 // DSDS is 1, and DSDA is 2, now only support DSDS
5100 phoneCapability->maxActiveInternetData = 1;
5101 // DSDA can support internet lingering
5102 phoneCapability->isInternetLingeringSupported = false;
5103 for (int num = 0; num < SIM_COUNT; num++) {
5104 phoneCapability->logicalModemList[num].modemId = num;
5105 }
5106 RIL_onRequestComplete(t, RIL_E_SUCCESS,
5107 phoneCapability, sizeof(RIL_PhoneCapability));
5108 break;
5109 }
5110 case RIL_REQUEST_CONFIG_SET_MODEM_CONFIG: {
5111 RIL_ModemConfig *mdConfig = (RIL_ModemConfig*)(data);
5112 if (mdConfig == NULL || mdConfig->numOfLiveModems != 1) {
5113 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
5114 } else {
5115 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5116 }
5117 break;
5118 }
5119 case RIL_REQUEST_CONFIG_GET_MODEM_CONFIG: {
5120 RIL_ModemConfig mdConfig;
5121 mdConfig.numOfLiveModems = 1;
5122
5123 RIL_onRequestComplete(t, RIL_E_SUCCESS, &mdConfig, sizeof(RIL_ModemConfig));
5124 break;
5125 }
5126 case RIL_REQUEST_CONFIG_SET_PREFER_DATA_MODEM: {
5127 int *modemId = (int*)(data);
5128 if (modemId == NULL || *modemId != 0) {
5129 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
5130 } else {
5131 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5132 }
5133 break;
5134 }
5135 case RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA:
5136 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5137 break;
5138 case RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA:
5139 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5140 break;
5141 case RIL_REQUEST_ENABLE_UICC_APPLICATIONS: {
5142 if (data == NULL || datalen != sizeof(int)) {
5143 RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
5144 break;
5145 }
5146 areUiccApplicationsEnabled = *(int *)(data);
5147 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5148 break;
5149 }
5150 case RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED:
5151 RIL_onRequestComplete(t, RIL_E_SUCCESS, &areUiccApplicationsEnabled,
5152 sizeof(areUiccApplicationsEnabled));
5153 break;
5154 case RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE:
5155 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5156 break;
5157 case RIL_REQUEST_GET_BARRING_INFO:
5158 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5159 break;
5160 case RIL_REQUEST_SET_DATA_THROTTLING:
5161 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5162 break;
5163 case RIL_REQUEST_START_KEEPALIVE:
5164 requestStartKeepalive(data, datalen, t);
5165 break;
5166 case RIL_REQUEST_STOP_KEEPALIVE:
5167 if (data == NULL || datalen != sizeof(int)) {
5168 RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
5169 break;
5170 }
5171 int sessionHandle = *(int*)(data);
5172 if ((int32_t)sessionHandle < s_session_handle) {
5173 // check that the session handle is one we've assigned previously
5174 // note that this doesn't handle duplicate stop requests properly
5175 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5176 } else {
5177 RLOGE("Invalid session handle for keepalive!");
5178 RIL_onRequestComplete(t, RIL_E_INVALID_ARGUMENTS, NULL, 0);
5179 }
5180 break;
5181 case RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER:
5182 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
5183 break;
5184 default:
5185 RLOGD("Request not supported. Tech: %d",TECH(sMdmInfo));
5186 RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
5187 break;
5188 }
5189 }
5190
5191 /**
5192 * Synchronous call from the RIL to us to return current radio state.
5193 * RADIO_STATE_UNAVAILABLE should be the initial state.
5194 */
5195 static RIL_RadioState
5196 currentState()
5197 {
5198 return sState;
5199 }
5200 /**
5201 * Call from RIL to us to find out whether a specific request code
5202 * is supported by this implementation.
5203 *
5204 * Return 1 for "supported" and 0 for "unsupported"
5205 */
5206
5207 static int
5208 onSupports (int requestCode __unused)
5209 {
5210 //@@@ todo
5211
5212 return 1;
5213 }
5214
5215 static void onCancel (RIL_Token t __unused)
5216 {
5217 //@@@todo
5218
5219 }
5220
5221 static const char * getVersion(void)
5222 {
5223 return "android reference-ril 1.0";
5224 }
5225
5226 static void
5227 setRadioTechnology(ModemInfo *mdm, int newtech)
5228 {
5229 RLOGD("setRadioTechnology(%d)", newtech);
5230
5231 int oldtech = TECH(mdm);
5232
5233 if (newtech != oldtech) {
5234 RLOGD("Tech change (%d => %d)", oldtech, newtech);
5235 TECH(mdm) = newtech;
5236 if (techFromModemType(newtech) != techFromModemType(oldtech)) {
5237 int tech = techFromModemType(TECH(sMdmInfo));
5238 if (tech > 0 ) {
5239 RIL_onUnsolicitedResponse(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED,
5240 &tech, sizeof(tech));
5241 }
5242 }
5243 }
5244 }
5245
5246 static void
5247 setRadioState(RIL_RadioState newState)
5248 {
5249 RLOGD("setRadioState(%d)", newState);
5250 RIL_RadioState oldState;
5251
5252 pthread_mutex_lock(&s_state_mutex);
5253
5254 oldState = sState;
5255
5256 if (s_closed > 0) {
5257 // If we're closed, the only reasonable state is
5258 // RADIO_STATE_UNAVAILABLE
5259 // This is here because things on the main thread
5260 // may attempt to change the radio state after the closed
5261 // event happened in another thread
5262 newState = RADIO_STATE_UNAVAILABLE;
5263 }
5264
5265 if (sState != newState || s_closed > 0) {
5266 sState = newState;
5267
5268 pthread_cond_broadcast (&s_state_cond);
5269 }
5270
5271 pthread_mutex_unlock(&s_state_mutex);
5272
5273
5274 /* do these outside of the mutex */
5275 if (sState != oldState) {
5276 RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
5277 NULL, 0);
5278 // Sim state can change as result of radio state change
5279 RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,
5280 NULL, 0);
5281
5282 /* FIXME onSimReady() and onRadioPowerOn() cannot be called
5283 * from the AT reader thread
5284 * Currently, this doesn't happen, but if that changes then these
5285 * will need to be dispatched on the request thread
5286 */
5287 if (sState == RADIO_STATE_ON) {
5288 onRadioPowerOn();
5289 }
5290 }
5291 }
5292
5293 /** Returns RUIM_NOT_READY on error */
5294 static SIM_Status
5295 getRUIMStatus()
5296 {
5297 ATResponse *p_response = NULL;
5298 int err;
5299 int ret;
5300 char *cpinLine;
5301 char *cpinResult;
5302
5303 if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
5304 ret = SIM_NOT_READY;
5305 goto done;
5306 }
5307
5308 err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
5309
5310 if (err != 0) {
5311 ret = SIM_NOT_READY;
5312 goto done;
5313 }
5314
5315 switch (at_get_cme_error(p_response)) {
5316 case CME_SUCCESS:
5317 break;
5318
5319 case CME_SIM_NOT_INSERTED:
5320 ret = SIM_ABSENT;
5321 goto done;
5322
5323 default:
5324 ret = SIM_NOT_READY;
5325 goto done;
5326 }
5327
5328 /* CPIN? has succeeded, now look at the result */
5329
5330 cpinLine = p_response->p_intermediates->line;
5331 err = at_tok_start (&cpinLine);
5332
5333 if (err < 0) {
5334 ret = SIM_NOT_READY;
5335 goto done;
5336 }
5337
5338 err = at_tok_nextstr(&cpinLine, &cpinResult);
5339
5340 if (err < 0) {
5341 ret = SIM_NOT_READY;
5342 goto done;
5343 }
5344
5345 if (0 == strcmp (cpinResult, "SIM PIN")) {
5346 ret = SIM_PIN;
5347 goto done;
5348 } else if (0 == strcmp (cpinResult, "SIM PUK")) {
5349 ret = SIM_PUK;
5350 goto done;
5351 } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
5352 return SIM_NETWORK_PERSONALIZATION;
5353 } else if (0 != strcmp (cpinResult, "READY")) {
5354 /* we're treating unsupported lock types as "sim absent" */
5355 ret = SIM_ABSENT;
5356 goto done;
5357 }
5358
5359 at_response_free(p_response);
5360 p_response = NULL;
5361 cpinResult = NULL;
5362
5363 ret = SIM_READY;
5364
5365 done:
5366 at_response_free(p_response);
5367 return ret;
5368 }
5369
5370 /** Returns SIM_NOT_READY on error */
5371 static SIM_Status
5372 getSIMStatus()
5373 {
5374 ATResponse *p_response = NULL;
5375 int err;
5376 int ret;
5377 char *cpinLine;
5378 char *cpinResult;
5379
5380 RLOGD("getSIMStatus(). sState: %d",sState);
5381 err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
5382
5383 if (err != 0) {
5384 ret = SIM_NOT_READY;
5385 goto done;
5386 }
5387
5388 switch (at_get_cme_error(p_response)) {
5389 case CME_SUCCESS:
5390 break;
5391
5392 case CME_SIM_NOT_INSERTED:
5393 ret = SIM_ABSENT;
5394 goto done;
5395
5396 default:
5397 ret = SIM_NOT_READY;
5398 goto done;
5399 }
5400
5401 /* CPIN? has succeeded, now look at the result */
5402
5403 cpinLine = p_response->p_intermediates->line;
5404 err = at_tok_start (&cpinLine);
5405
5406 if (err < 0) {
5407 ret = SIM_NOT_READY;
5408 goto done;
5409 }
5410
5411 err = at_tok_nextstr(&cpinLine, &cpinResult);
5412
5413 if (err < 0) {
5414 ret = SIM_NOT_READY;
5415 goto done;
5416 }
5417
5418 if (0 == strcmp (cpinResult, "SIM PIN")) {
5419 ret = SIM_PIN;
5420 goto done;
5421 } else if (0 == strcmp (cpinResult, "SIM PUK")) {
5422 ret = SIM_PUK;
5423 goto done;
5424 } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
5425 return SIM_NETWORK_PERSONALIZATION;
5426 } else if (0 != strcmp (cpinResult, "READY")) {
5427 /* we're treating unsupported lock types as "sim absent" */
5428 ret = SIM_ABSENT;
5429 goto done;
5430 }
5431
5432 at_response_free(p_response);
5433 p_response = NULL;
5434 cpinResult = NULL;
5435
5436 ret = (sState == RADIO_STATE_ON) ? SIM_READY : SIM_NOT_READY;
5437
5438 done:
5439 at_response_free(p_response);
5440 return ret;
5441 }
5442
5443 static void getIccId(char *iccid, int size) {
5444 int err = 0;
5445 ATResponse *p_response = NULL;
5446
5447 if (iccid == NULL) {
5448 RLOGE("iccid buffer is null");
5449 return;
5450 }
5451 err = at_send_command_numeric("AT+CICCID", &p_response);
5452 if (err < 0 || p_response->success == 0) {
5453 goto error;
5454 }
5455
5456 snprintf(iccid, size, "%s", p_response->p_intermediates->line);
5457
5458 error:
5459 at_response_free(p_response);
5460 }
5461
5462 /**
5463 * Get the current card status.
5464 *
5465 * This must be freed using freeCardStatus.
5466 * @return: On success returns RIL_E_SUCCESS
5467 */
5468 static int getCardStatus(RIL_CardStatus_v1_5 **pp_card_status) {
5469 static RIL_AppStatus app_status_array[] = {
5470 // SIM_ABSENT = 0
5471 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
5472 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5473 // SIM_NOT_READY = 1
5474 { RIL_APPTYPE_USIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
5475 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5476 // SIM_READY = 2
5477 { RIL_APPTYPE_USIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
5478 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5479 // SIM_PIN = 3
5480 { RIL_APPTYPE_USIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
5481 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
5482 // SIM_PUK = 4
5483 { RIL_APPTYPE_USIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
5484 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
5485 // SIM_NETWORK_PERSONALIZATION = 5
5486 { RIL_APPTYPE_USIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
5487 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
5488 // RUIM_ABSENT = 6
5489 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
5490 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5491 // RUIM_NOT_READY = 7
5492 { RIL_APPTYPE_RUIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
5493 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5494 // RUIM_READY = 8
5495 { RIL_APPTYPE_RUIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
5496 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5497 // RUIM_PIN = 9
5498 { RIL_APPTYPE_RUIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
5499 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
5500 // RUIM_PUK = 10
5501 { RIL_APPTYPE_RUIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
5502 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
5503 // RUIM_NETWORK_PERSONALIZATION = 11
5504 { RIL_APPTYPE_RUIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
5505 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
5506 // ISIM_ABSENT = 12
5507 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
5508 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5509 // ISIM_NOT_READY = 13
5510 { RIL_APPTYPE_ISIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
5511 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5512 // ISIM_READY = 14
5513 { RIL_APPTYPE_ISIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
5514 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
5515 // ISIM_PIN = 15
5516 { RIL_APPTYPE_ISIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
5517 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
5518 // ISIM_PUK = 16
5519 { RIL_APPTYPE_ISIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
5520 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
5521 // ISIM_NETWORK_PERSONALIZATION = 17
5522 { RIL_APPTYPE_ISIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
5523 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
5524
5525 };
5526 RIL_CardState card_state;
5527 int num_apps;
5528
5529 int sim_status = getSIMStatus();
5530 if (sim_status == SIM_ABSENT) {
5531 card_state = RIL_CARDSTATE_ABSENT;
5532 num_apps = 0;
5533 } else {
5534 card_state = RIL_CARDSTATE_PRESENT;
5535 num_apps = 3;
5536 }
5537
5538 // Allocate and initialize base card status.
5539 RIL_CardStatus_v1_5 *p_card_status = calloc(1, sizeof(RIL_CardStatus_v1_5));
5540 p_card_status->base.base.base.card_state = card_state;
5541 p_card_status->base.base.base.universal_pin_state = RIL_PINSTATE_UNKNOWN;
5542 p_card_status->base.base.base.gsm_umts_subscription_app_index = -1;
5543 p_card_status->base.base.base.cdma_subscription_app_index = -1;
5544 p_card_status->base.base.base.ims_subscription_app_index = -1;
5545 p_card_status->base.base.base.num_applications = num_apps;
5546 p_card_status->base.base.physicalSlotId = 0;
5547 p_card_status->base.base.atr = NULL;
5548 p_card_status->base.base.iccid = NULL;
5549 p_card_status->base.eid = "";
5550 if (sim_status != SIM_ABSENT) {
5551 p_card_status->base.base.iccid = (char *)calloc(64, sizeof(char));
5552 getIccId(p_card_status->base.base.iccid, 64);
5553 }
5554
5555 // Initialize application status
5556 int i;
5557 for (i = 0; i < RIL_CARD_MAX_APPS; i++) {
5558 p_card_status->base.base.base.applications[i] = app_status_array[SIM_ABSENT];
5559 }
5560 RLOGD("enter getCardStatus module, num_apps= %d",num_apps);
5561 // Pickup the appropriate application status
5562 // that reflects sim_status for gsm.
5563 if (num_apps != 0) {
5564 p_card_status->base.base.base.num_applications = 3;
5565 p_card_status->base.base.base.gsm_umts_subscription_app_index = 0;
5566 p_card_status->base.base.base.cdma_subscription_app_index = 1;
5567 p_card_status->base.base.base.ims_subscription_app_index = 2;
5568
5569 // Get the correct app status
5570 p_card_status->base.base.base.applications[0] = app_status_array[sim_status];
5571 p_card_status->base.base.base.applications[1] = app_status_array[sim_status + RUIM_ABSENT];
5572 p_card_status->base.base.base.applications[2] = app_status_array[sim_status + ISIM_ABSENT];
5573 }
5574
5575 *pp_card_status = p_card_status;
5576 return RIL_E_SUCCESS;
5577 }
5578
5579 /**
5580 * Free the card status returned by getCardStatus
5581 */
5582 static void freeCardStatus(RIL_CardStatus_v1_5 *p_card_status) {
5583 if (p_card_status == NULL) {
5584 return;
5585 }
5586 free(p_card_status->base.base.iccid);
5587 free(p_card_status);
5588 }
5589
5590 /**
5591 * SIM ready means any commands that access the SIM will work, including:
5592 * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
5593 * (all SMS-related commands)
5594 */
5595
5596 static void pollSIMState (void *param __unused)
5597 {
5598 ATResponse *p_response;
5599 int ret;
5600
5601 if (sState != RADIO_STATE_UNAVAILABLE) {
5602 // no longer valid to poll
5603 return;
5604 }
5605
5606 switch(getSIMStatus()) {
5607 case SIM_ABSENT:
5608 case SIM_PIN:
5609 case SIM_PUK:
5610 case SIM_NETWORK_PERSONALIZATION:
5611 default:
5612 RLOGI("SIM ABSENT or LOCKED");
5613 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
5614 return;
5615
5616 case SIM_NOT_READY:
5617 RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
5618 return;
5619
5620 case SIM_READY:
5621 RLOGI("SIM_READY");
5622 onSIMReady();
5623 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
5624 return;
5625 }
5626 }
5627
5628 /** returns 1 if on, 0 if off, and -1 on error */
5629 static int isRadioOn()
5630 {
5631 ATResponse *p_response = NULL;
5632 int err;
5633 char *line;
5634 char ret;
5635
5636 err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
5637
5638 if (err < 0 || p_response->success == 0) {
5639 // assume radio is off
5640 goto error;
5641 }
5642
5643 line = p_response->p_intermediates->line;
5644
5645 err = at_tok_start(&line);
5646 if (err < 0) goto error;
5647
5648 err = at_tok_nextbool(&line, &ret);
5649 if (err < 0) goto error;
5650
5651 at_response_free(p_response);
5652
5653 return (int)ret;
5654
5655 error:
5656
5657 at_response_free(p_response);
5658 return -1;
5659 }
5660
5661 /**
5662 * Parse the response generated by a +CTEC AT command
5663 * The values read from the response are stored in current and preferred.
5664 * Both current and preferred may be null. The corresponding value is ignored in that case.
5665 *
5666 * @return: -1 if some error occurs (or if the modem doesn't understand the +CTEC command)
5667 * 1 if the response includes the current technology only
5668 * 0 if the response includes both current technology and preferred mode
5669 */
5670 int parse_technology_response( const char *response, int *current, int32_t *preferred )
5671 {
5672 int err;
5673 char *line, *p;
5674 int ct;
5675 int32_t pt = 0;
5676 char *str_pt;
5677
5678 line = p = strdup(response);
5679 RLOGD("Response: %s", line);
5680 err = at_tok_start(&p);
5681 if (err || !at_tok_hasmore(&p)) {
5682 RLOGD("err: %d. p: %s", err, p);
5683 free(line);
5684 return -1;
5685 }
5686
5687 err = at_tok_nextint(&p, &ct);
5688 if (err) {
5689 free(line);
5690 return -1;
5691 }
5692 if (current) *current = ct;
5693
5694 RLOGD("line remaining after int: %s", p);
5695
5696 err = at_tok_nexthexint(&p, &pt);
5697 if (err) {
5698 free(line);
5699 return 1;
5700 }
5701 if (preferred) {
5702 *preferred = pt;
5703 }
5704 free(line);
5705
5706 return 0;
5707 }
5708
5709 int query_supported_techs( ModemInfo *mdm __unused, int *supported )
5710 {
5711 ATResponse *p_response;
5712 int err, val, techs = 0;
5713 char *tok;
5714 char *line;
5715
5716 RLOGD("query_supported_techs");
5717 err = at_send_command_singleline("AT+CTEC=?", "+CTEC:", &p_response);
5718 if (err || !p_response->success)
5719 goto error;
5720 line = p_response->p_intermediates->line;
5721 err = at_tok_start(&line);
5722 if (err || !at_tok_hasmore(&line))
5723 goto error;
5724 while (!at_tok_nextint(&line, &val)) {
5725 techs |= ( 1 << val );
5726 }
5727 if (supported) *supported = techs;
5728 return 0;
5729 error:
5730 at_response_free(p_response);
5731 return -1;
5732 }
5733
5734 /**
5735 * query_ctec. Send the +CTEC AT command to the modem to query the current
5736 * and preferred modes. It leaves values in the addresses pointed to by
5737 * current and preferred. If any of those pointers are NULL, the corresponding value
5738 * is ignored, but the return value will still reflect if retrieving and parsing of the
5739 * values succeeded.
5740 *
5741 * @mdm Currently unused
5742 * @current A pointer to store the current mode returned by the modem. May be null.
5743 * @preferred A pointer to store the preferred mode returned by the modem. May be null.
5744 * @return -1 on error (or failure to parse)
5745 * 1 if only the current mode was returned by modem (or failed to parse preferred)
5746 * 0 if both current and preferred were returned correctly
5747 */
5748 int query_ctec(ModemInfo *mdm __unused, int *current, int32_t *preferred)
5749 {
5750 ATResponse *response = NULL;
5751 int err;
5752 int res;
5753
5754 RLOGD("query_ctec. current: %p, preferred: %p", current, preferred);
5755 err = at_send_command_singleline("AT+CTEC?", "+CTEC:", &response);
5756 if (!err && response->success) {
5757 res = parse_technology_response(response->p_intermediates->line, current, preferred);
5758 at_response_free(response);
5759 return res;
5760 }
5761 RLOGE("Error executing command: %d. response: %p. status: %d", err, response, response? response->success : -1);
5762 at_response_free(response);
5763 return -1;
5764 }
5765
5766 int is_multimode_modem(ModemInfo *mdm)
5767 {
5768 ATResponse *response;
5769 int err;
5770 char *line;
5771 int tech;
5772 int32_t preferred;
5773
5774 if (query_ctec(mdm, &tech, &preferred) == 0) {
5775 mdm->currentTech = tech;
5776 mdm->preferredNetworkMode = preferred;
5777 if (query_supported_techs(mdm, &mdm->supportedTechs)) {
5778 return 0;
5779 }
5780 return 1;
5781 }
5782 return 0;
5783 }
5784
5785 /**
5786 * Find out if our modem is GSM, CDMA or both (Multimode)
5787 */
5788 static void probeForModemMode(ModemInfo *info)
5789 {
5790 ATResponse *response;
5791 int err;
5792 assert (info);
5793 // Currently, our only known multimode modem is qemu's android modem,
5794 // which implements the AT+CTEC command to query and set mode.
5795 // Try that first
5796
5797 if (is_multimode_modem(info)) {
5798 RLOGI("Found Multimode Modem. Supported techs mask: %8.8x. Current tech: %d",
5799 info->supportedTechs, info->currentTech);
5800 return;
5801 }
5802
5803 /* Being here means that our modem is not multimode */
5804 info->isMultimode = 0;
5805
5806 /* CDMA Modems implement the AT+WNAM command */
5807 err = at_send_command_singleline("AT+WNAM","+WNAM:", &response);
5808 if (!err && response->success) {
5809 at_response_free(response);
5810 // TODO: find out if we really support EvDo
5811 info->supportedTechs = MDM_CDMA | MDM_EVDO;
5812 info->currentTech = MDM_CDMA;
5813 RLOGI("Found CDMA Modem");
5814 return;
5815 }
5816 if (!err) at_response_free(response);
5817 // TODO: find out if modem really supports WCDMA/LTE
5818 info->supportedTechs = MDM_GSM | MDM_WCDMA | MDM_LTE;
5819 info->currentTech = MDM_GSM;
5820 RLOGI("Found GSM Modem");
5821 }
5822
5823 /**
5824 * Initialize everything that can be configured while we're still in
5825 * AT+CFUN=0
5826 */
5827 static void initializeCallback(void *param __unused)
5828 {
5829 ATResponse *p_response = NULL;
5830 int err;
5831
5832 setRadioState (RADIO_STATE_OFF);
5833
5834 at_handshake();
5835
5836 probeForModemMode(sMdmInfo);
5837 /* note: we don't check errors here. Everything important will
5838 be handled in onATTimeout and onATReaderClosed */
5839
5840 /* atchannel is tolerant of echo but it must */
5841 /* have verbose result codes */
5842 at_send_command("ATE0Q0V1", NULL);
5843
5844 /* No auto-answer */
5845 at_send_command("ATS0=0", NULL);
5846
5847 /* Extended errors */
5848 at_send_command("AT+CMEE=1", NULL);
5849
5850 /* Network registration events */
5851 err = at_send_command("AT+CREG=2", &p_response);
5852
5853 /* some handsets -- in tethered mode -- don't support CREG=2 */
5854 if (err < 0 || p_response->success == 0) {
5855 at_send_command("AT+CREG=1", NULL);
5856 }
5857
5858 at_response_free(p_response);
5859
5860 /* GPRS registration events */
5861 at_send_command("AT+CGREG=1", NULL);
5862
5863 /* Call Waiting notifications */
5864 at_send_command("AT+CCWA=1", NULL);
5865
5866 /* Alternating voice/data off */
5867 at_send_command("AT+CMOD=0", NULL);
5868
5869 /* Not muted */
5870 at_send_command("AT+CMUT=0", NULL);
5871
5872 /* +CSSU unsolicited supp service notifications */
5873 at_send_command("AT+CSSN=0,1", NULL);
5874
5875 /* no connected line identification */
5876 at_send_command("AT+COLP=0", NULL);
5877
5878 /* HEX character set */
5879 at_send_command("AT+CSCS=\"HEX\"", NULL);
5880
5881 /* USSD unsolicited */
5882 at_send_command("AT+CUSD=1", NULL);
5883
5884 /* Enable +CGEV GPRS event notifications, but don't buffer */
5885 at_send_command("AT+CGEREP=1,0", NULL);
5886
5887 /* SMS PDU mode */
5888 at_send_command("AT+CMGF=0", NULL);
5889
5890 #ifdef USE_TI_COMMANDS
5891
5892 at_send_command("AT%CPI=3", NULL);
5893
5894 /* TI specific -- notifications when SMS is ready (currently ignored) */
5895 at_send_command("AT%CSTAT=1", NULL);
5896
5897 #endif /* USE_TI_COMMANDS */
5898
5899
5900 /* assume radio is off on error */
5901 if (isRadioOn() > 0) {
5902 setRadioState (RADIO_STATE_ON);
5903 }
5904 }
5905
5906 static void waitForClose()
5907 {
5908 pthread_mutex_lock(&s_state_mutex);
5909
5910 while (s_closed == 0) {
5911 pthread_cond_wait(&s_state_cond, &s_state_mutex);
5912 }
5913
5914 pthread_mutex_unlock(&s_state_mutex);
5915 }
5916
5917 static void sendUnsolImsNetworkStateChanged()
5918 {
5919 #if 0 // to be used when unsol is changed to return data.
5920 int reply[2];
5921 reply[0] = s_ims_registered;
5922 reply[1] = s_ims_services;
5923 reply[1] = s_ims_format;
5924 #endif
5925 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED,
5926 NULL, 0);
5927 }
5928
5929 static int parseProactiveCmdInd(char *response) {
5930 int typePos = 0;
5931 int cmdType = 0;
5932 char tempStr[3] = {0};
5933 char *end = NULL;
5934 StkUnsolEvent ret = STK_UNSOL_EVENT_UNKNOWN;
5935
5936 if (response == NULL || strlen(response) < 3) {
5937 return ret;
5938 }
5939
5940 if (response[2] <= '7') {
5941 typePos = 10;
5942 } else {
5943 typePos = 12;
5944 }
5945
5946 if ((int)strlen(response) < typePos + 1) {
5947 return ret;
5948 }
5949
5950 memcpy(tempStr, &(response[typePos]), 2);
5951 cmdType = strtoul(tempStr, &end, 16);
5952 cmdType = 0xFF & cmdType;
5953 RLOGD("cmdType: %d",cmdType);
5954
5955 switch (cmdType) {
5956 case STK_RUN_AT:
5957 case STK_SEND_DTMF:
5958 case STK_SEND_SMS:
5959 case STK_SEND_SS:
5960 case STK_SEND_USSD:
5961 case STK_PLAY_TONE:
5962 case STK_CLOSE_CHANNEL:
5963 ret = STK_UNSOL_EVENT_NOTIFY;
5964 break;
5965 case STK_REFRESH:
5966 if (strncasecmp(&(response[typePos + 2]), "04", 2) == 0) { // SIM_RESET
5967 RLOGD("Type of Refresh is SIM_RESET");
5968 s_stkServiceRunning = false;
5969 ret = STK_UNSOL_PROACTIVE_CMD;
5970 } else {
5971 ret = STK_UNSOL_EVENT_NOTIFY;
5972 }
5973 break;
5974 default:
5975 ret = STK_UNSOL_PROACTIVE_CMD;
5976 break;
5977 }
5978
5979 if (getSIMStatus() == SIM_ABSENT && s_stkServiceRunning) {
5980 s_stkServiceRunning = false;
5981 }
5982
5983 if (false == s_stkServiceRunning) {
5984 ret = STK_UNSOL_EVENT_UNKNOWN;
5985 s_stkUnsolResponse = (char *)calloc((strlen(response) + 1), sizeof(char));
5986 snprintf(s_stkUnsolResponse, strlen(response) + 1, "%s", response);
5987 RLOGD("STK service is not running [%s]", s_stkUnsolResponse);
5988 }
5989
5990 return ret;
5991 }
5992
5993 /**
5994 * Called by atchannel when an unsolicited line appears
5995 * This is called on atchannel's reader thread. AT commands may
5996 * not be issued here
5997 */
5998 static void onUnsolicited (const char *s, const char *sms_pdu)
5999 {
6000 char *line = NULL, *p;
6001 int err;
6002
6003 /* Ignore unsolicited responses until we're initialized.
6004 * This is OK because the RIL library will poll for initial state
6005 */
6006 if (sState == RADIO_STATE_UNAVAILABLE) {
6007 return;
6008 }
6009
6010 #define CGFPCCFG "%CGFPCCFG:"
6011 if (strStartsWith(s, CGFPCCFG)) {
6012 /* cuttlefish/goldfish specific
6013 */
6014 char *response;
6015 line = p = strdup(s);
6016 RLOGD("got CGFPCCFG line %s and %s\n", s, p);
6017 err = at_tok_start(&line);
6018 if(err) {
6019 RLOGE("invalid CGFPCCFG line %s and %s\n", s, p);
6020 }
6021 #define kSize 5
6022 int configs[kSize];
6023 for (int i=0; i < kSize && !err; ++i) {
6024 err = at_tok_nextint(&line, &(configs[i]));
6025 RLOGD("got i %d, val = %d", i, configs[i]);
6026 }
6027 if(err) {
6028 RLOGE("invalid CGFPCCFG line %s and %s\n", s, p);
6029 } else {
6030 int modem_tech = configs[2];
6031 configs[2] = techFromModemType(modem_tech);
6032 RIL_onUnsolicitedResponse (
6033 RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS,
6034 configs, kSize);
6035 }
6036 free(p);
6037 } else if (strStartsWith(s, "%CTZV:")) {
6038 /* TI specific -- NITZ time */
6039 char *response;
6040
6041 line = p = strdup(s);
6042 at_tok_start(&p);
6043
6044 err = at_tok_nextstr(&p, &response);
6045
6046 if (err != 0) {
6047 RLOGE("invalid NITZ line %s\n", s);
6048 } else {
6049 RIL_onUnsolicitedResponse (
6050 RIL_UNSOL_NITZ_TIME_RECEIVED,
6051 response, strlen(response) + 1);
6052 }
6053 free(line);
6054 } else if (strStartsWith(s,"+CRING:")
6055 || strStartsWith(s,"RING")
6056 || strStartsWith(s,"NO CARRIER")
6057 || strStartsWith(s,"+CCWA")
6058 ) {
6059 RIL_onUnsolicitedResponse (
6060 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
6061 NULL, 0);
6062 #ifdef WORKAROUND_FAKE_CGEV
6063 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
6064 #endif /* WORKAROUND_FAKE_CGEV */
6065 } else if (strStartsWith(s,"+CREG:")
6066 || strStartsWith(s,"+CGREG:")
6067 ) {
6068 RIL_onUnsolicitedResponse (
6069 RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
6070 NULL, 0);
6071 #ifdef WORKAROUND_FAKE_CGEV
6072 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
6073 #endif /* WORKAROUND_FAKE_CGEV */
6074 } else if (strStartsWith(s, "+CMT:")) {
6075 RIL_onUnsolicitedResponse (
6076 RIL_UNSOL_RESPONSE_NEW_SMS,
6077 sms_pdu, strlen(sms_pdu));
6078 } else if (strStartsWith(s, "+CDS:")) {
6079 RIL_onUnsolicitedResponse (
6080 RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
6081 sms_pdu, strlen(sms_pdu));
6082 } else if (strStartsWith(s, "+CGEV:")) {
6083 /* Really, we can ignore NW CLASS and ME CLASS events here,
6084 * but right now we don't since extraneous
6085 * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
6086 */
6087 /* can't issue AT commands here -- call on main thread */
6088 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
6089 #ifdef WORKAROUND_FAKE_CGEV
6090 } else if (strStartsWith(s, "+CME ERROR: 150")) {
6091 RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
6092 #endif /* WORKAROUND_FAKE_CGEV */
6093 } else if (strStartsWith(s, "+CTEC: ")) {
6094 int tech, mask;
6095 switch (parse_technology_response(s, &tech, NULL))
6096 {
6097 case -1: // no argument could be parsed.
6098 RLOGE("invalid CTEC line %s\n", s);
6099 break;
6100 case 1: // current mode correctly parsed
6101 case 0: // preferred mode correctly parsed
6102 mask = 1 << tech;
6103 if (mask != MDM_GSM && mask != MDM_CDMA &&
6104 mask != MDM_WCDMA && mask != MDM_LTE) {
6105 RLOGE("Unknown technology %d\n", tech);
6106 } else {
6107 setRadioTechnology(sMdmInfo, tech);
6108 }
6109 break;
6110 }
6111 } else if (strStartsWith(s, "+CCSS: ")) {
6112 int source = 0;
6113 line = p = strdup(s);
6114 if (!line) {
6115 RLOGE("+CCSS: Unable to allocate memory");
6116 return;
6117 }
6118 if (at_tok_start(&p) < 0) {
6119 free(line);
6120 return;
6121 }
6122 if (at_tok_nextint(&p, &source) < 0) {
6123 RLOGE("invalid +CCSS response: %s", line);
6124 free(line);
6125 return;
6126 }
6127 SSOURCE(sMdmInfo) = source;
6128 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED,
6129 &source, sizeof(source));
6130 free(line);
6131 } else if (strStartsWith(s, "+WSOS: ")) {
6132 char state = 0;
6133 int unsol;
6134 line = p = strdup(s);
6135 if (!line) {
6136 RLOGE("+WSOS: Unable to allocate memory");
6137 return;
6138 }
6139 if (at_tok_start(&p) < 0) {
6140 free(line);
6141 return;
6142 }
6143 if (at_tok_nextbool(&p, &state) < 0) {
6144 RLOGE("invalid +WSOS response: %s", line);
6145 free(line);
6146 return;
6147 }
6148 free(line);
6149
6150 unsol = state ?
6151 RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE : RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE;
6152
6153 RIL_onUnsolicitedResponse(unsol, NULL, 0);
6154
6155 } else if (strStartsWith(s, "+WPRL: ")) {
6156 int version = -1;
6157 line = p = strdup(s);
6158 if (!line) {
6159 RLOGE("+WPRL: Unable to allocate memory");
6160 return;
6161 }
6162 if (at_tok_start(&p) < 0) {
6163 RLOGE("invalid +WPRL response: %s", s);
6164 free(line);
6165 return;
6166 }
6167 if (at_tok_nextint(&p, &version) < 0) {
6168 RLOGE("invalid +WPRL response: %s", s);
6169 free(line);
6170 return;
6171 }
6172 free(line);
6173 RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_PRL_CHANGED, &version, sizeof(version));
6174 } else if (strStartsWith(s, "+CFUN: 0")) {
6175 setRadioState(RADIO_STATE_OFF);
6176 } else if (strStartsWith(s, "+CSQ: ")) {
6177 // Accept a response that is at least v6, and up to v12
6178 int minNumOfElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
6179 int maxNumOfElements=sizeof(RIL_SignalStrength_v12)/sizeof(int);
6180 int response[maxNumOfElements];
6181 memset(response, 0, sizeof(response));
6182
6183 line = p = strdup(s);
6184 at_tok_start(&p);
6185
6186 for (int count = 0; count < maxNumOfElements; count++) {
6187 err = at_tok_nextint(&p, &(response[count]));
6188 if (err < 0 && count < minNumOfElements) {
6189 free(line);
6190 return;
6191 }
6192 }
6193
6194 RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH,
6195 response, sizeof(response));
6196 free(line);
6197 } else if (strStartsWith(s, "+CUSATEND")) { // session end
6198 RIL_onUnsolicitedResponse(RIL_UNSOL_STK_SESSION_END, NULL, 0);
6199 } else if (strStartsWith(s, "+CUSATP:")) {
6200 line = p = strdup(s);
6201 if (!line) {
6202 RLOGE("+CUSATP: Unable to allocate memory");
6203 return;
6204 }
6205 if (at_tok_start(&p) < 0) {
6206 RLOGE("invalid +CUSATP response: %s", s);
6207 free(line);
6208 return;
6209 }
6210
6211 char *response = NULL;
6212 if (at_tok_nextstr(&p, &response) < 0) {
6213 RLOGE("%s fail", s);
6214 free(line);
6215 return;
6216 }
6217
6218 StkUnsolEvent ret = parseProactiveCmdInd(response);
6219 if (ret == STK_UNSOL_EVENT_NOTIFY) {
6220 RIL_onUnsolicitedResponse(RIL_UNSOL_STK_EVENT_NOTIFY, response,
6221 strlen(response) + 1);
6222 } else if (ret == STK_UNSOL_PROACTIVE_CMD) {
6223 RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND, response,
6224 strlen(response) + 1);
6225 }
6226
6227 free(line);
6228 } else if (strStartsWith(s, "+REMOTEIDDISCLOSURE")) {
6229 RLOGD("starting REMOTEIDDISCLOSURE %s", s);
6230 line = p = strdup(s);
6231 if (!line) {
6232 RLOGE("+REMOTEIDDISCLOSURE unable to allocate memory");
6233 return;
6234 }
6235 if (at_tok_start(&p) < 0) {
6236 RLOGE("invalid +REMOTEIDDISCLOSURE command: %s", s);
6237 free(line);
6238 return;
6239 }
6240
6241 RIL_CellularIdentifierDisclosure disclosure;
6242
6243 if (at_tok_nextstr(&p, &disclosure.plmn) < 0) {
6244 RLOGE("+REMOTEIDDISCLOSURE unable to parse plmn %s", s);
6245 return;
6246 }
6247 if (at_tok_nextint(&p, &disclosure.identifierType) < 0) {
6248 RLOGE("+REMOTEIDDISCLOSURE unable to parse identifier %s", s);
6249 return;
6250 }
6251 if (at_tok_nextint(&p, &disclosure.protocolMessage) < 0) {
6252 RLOGE("+REMOTEIDDISCLOSURE unable to parse protocol message %s", s);
6253 return;
6254 }
6255 if (at_tok_nextbool(&p, (char*)&disclosure.isEmergency) < 0) {
6256 RLOGE("+REMOTEIDDISCLOSURE unable to parse isEmergency %s", s);
6257 return;
6258 }
6259
6260 RIL_onUnsolicitedResponse(RIL_UNSOL_CELLULAR_IDENTIFIER_DISCLOSED, (void*)&disclosure,
6261 sizeof(disclosure));
6262 free(line);
6263 } else if (strStartsWith(s, "+UPDATESECURITYALGORITHM")) {
6264 RLOGD("starting UPDATESECURITYALGORITHM %s", s);
6265 line = p = strdup(s);
6266 if (!line) {
6267 RLOGE("+UPDATESECURITYALGORITHM unable to allocate memory");
6268 return;
6269 }
6270 if (at_tok_start(&p) < 0) {
6271 RLOGE("invalid +UPDATESECURITYALGORITHM command: %s", s);
6272 free(line);
6273 return;
6274 }
6275
6276 RIL_SecurityAlgorithmUpdate update;
6277
6278 if (at_tok_nextint(&p, &update.connectionEvent) < 0) {
6279 RLOGE("+UPDATESECURITYALGORITHM unable to parse connection event %s", s);
6280 return;
6281 }
6282 if (at_tok_nextint(&p, &update.encryption) < 0) {
6283 RLOGE("+UPDATESECURITYALGORITHM unable to parse encryption %s", s);
6284 return;
6285 }
6286 if (at_tok_nextint(&p, &update.integrity) < 0) {
6287 RLOGE("+UPDATESECURITYALGORITHM unable to parse integrity %s", s);
6288 return;
6289 }
6290 if (at_tok_nextbool(&p, (char*)&update.isUnprotectedEmergency) < 0) {
6291 RLOGE("+UPDATESECURITYALGORITHM unable to parse isUnprotectedEmergency %s", s);
6292 return;
6293 }
6294
6295 RIL_onUnsolicitedResponse(RIL_UNSOL_SECURITY_ALGORITHM_UPDATED, &update, sizeof(update));
6296 free(line);
6297 } else {
6298 RLOGE("Unexpected unsolicited request: %s", s);
6299 }
6300 }
6301
6302 /* Called on command or reader thread */
6303 static void onATReaderClosed()
6304 {
6305 RLOGI("AT channel closed\n");
6306 at_close();
6307 s_closed = 1;
6308
6309 setRadioState (RADIO_STATE_UNAVAILABLE);
6310 }
6311
6312 /* Called on command thread */
6313 static void onATTimeout()
6314 {
6315 RLOGI("AT channel timeout; closing\n");
6316 at_close();
6317
6318 s_closed = 1;
6319
6320 /* FIXME cause a radio reset here */
6321
6322 setRadioState (RADIO_STATE_UNAVAILABLE);
6323 }
6324
6325 /* Called to pass hardware configuration information to telephony
6326 * framework.
6327 */
6328 static void setHardwareConfiguration(int num, RIL_HardwareConfig *cfg)
6329 {
6330 RIL_onUnsolicitedResponse(RIL_UNSOL_HARDWARE_CONFIG_CHANGED, cfg, num*sizeof(*cfg));
6331 }
6332
6333 static void usage(char *s __unused)
6334 {
6335 #ifdef RIL_SHLIB
6336 fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_device\n");
6337 #else
6338 fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]\n", s);
6339 exit(-1);
6340 #endif
6341 }
6342
6343 static void *
6344 mainLoop(void *param __unused)
6345 {
6346 int fd;
6347 int ret;
6348
6349 AT_DUMP("== ", "entering mainLoop()", -1 );
6350 at_set_on_reader_closed(onATReaderClosed);
6351 at_set_on_timeout(onATTimeout);
6352
6353 for (;;) {
6354 fd = -1;
6355 while (fd < 0) {
6356 if (isInEmulator()) {
6357 fd = qemu_open_modem_port();
6358 RLOGD("opening qemu_modem_port %d!", fd);
6359 } else if (s_port > 0) {
6360 fd = socket_network_client("localhost", s_port, SOCK_STREAM);
6361 } else if (s_modem_simulator_port >= 0) {
6362 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
6363 if (fd < 0) {
6364 RLOGD("Can't create AF_VSOCK socket!");
6365 continue;
6366 }
6367 struct sockaddr_vm sa;
6368 memset(&sa, 0, sizeof(struct sockaddr_vm));
6369 sa.svm_family = AF_VSOCK;
6370 sa.svm_cid = VMADDR_CID_HOST;
6371 sa.svm_port = s_modem_simulator_port;
6372
6373 if (connect(fd, (struct sockaddr *)(&sa), sizeof(sa)) < 0) {
6374 RLOGD("Can't connect to port:%ud, errno: %s",
6375 s_modem_simulator_port, strerror(errno));
6376 close(fd);
6377 fd = -1;
6378 continue;
6379 }
6380 } else if (s_device_socket) {
6381 fd = socket_local_client(s_device_path,
6382 ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
6383 SOCK_STREAM);
6384 } else if (s_device_path != NULL) {
6385 fd = open (s_device_path, O_RDWR);
6386 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
6387 /* disable echo on serial ports */
6388 struct termios ios;
6389 tcgetattr( fd, &ios );
6390 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
6391 tcsetattr( fd, TCSANOW, &ios );
6392 }
6393 }
6394
6395 if (fd < 0) {
6396 perror ("opening AT interface. retrying...");
6397 sleep(10);
6398 /* never returns */
6399 }
6400 }
6401
6402 s_closed = 0;
6403 ret = at_open(fd, onUnsolicited);
6404
6405 if (ret < 0) {
6406 RLOGE ("AT error %d on at_open\n", ret);
6407 return 0;
6408 }
6409
6410 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
6411
6412 // Give initializeCallback a chance to dispatched, since
6413 // we don't presently have a cancellation mechanism
6414 sleep(1);
6415
6416 waitForClose();
6417 RLOGI("Re-opening after close");
6418 }
6419 }
6420
6421 #ifdef RIL_SHLIB
6422
6423 pthread_t s_tid_mainloop;
6424
6425 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
6426 {
6427 int ret;
6428 int fd = -1;
6429 int opt;
6430 pthread_attr_t attr;
6431
6432 s_rilenv = env;
6433
6434 RLOGD("RIL_Init");
6435 while ( -1 != (opt = getopt(argc, argv, "p:d:s:c:m:"))) {
6436 switch (opt) {
6437 case 'p':
6438 s_port = atoi(optarg);
6439 if (s_port == 0) {
6440 usage(argv[0]);
6441 return NULL;
6442 }
6443 RLOGI("Opening loopback port %d\n", s_port);
6444 break;
6445
6446 case 'd':
6447 s_device_path = optarg;
6448 RLOGI("Opening tty device %s\n", s_device_path);
6449 break;
6450
6451 case 's':
6452 s_device_path = optarg;
6453 s_device_socket = 1;
6454 RLOGI("Opening socket %s\n", s_device_path);
6455 break;
6456
6457 case 'c':
6458 RLOGI("Client id received %s\n", optarg);
6459 break;
6460
6461 case 'm':
6462 s_modem_simulator_port = strtoul(optarg, NULL, 10);
6463 RLOGI("Opening modem simulator port %ud\n", s_modem_simulator_port);
6464 break;
6465
6466 default:
6467 usage(argv[0]);
6468 return NULL;
6469 }
6470 }
6471
6472 if (s_port < 0 && s_device_path == NULL && !isInEmulator() &&
6473 s_modem_simulator_port < 0) {
6474 usage(argv[0]);
6475 return NULL;
6476 }
6477
6478 sMdmInfo = calloc(1, sizeof(ModemInfo));
6479 if (!sMdmInfo) {
6480 RLOGE("Unable to alloc memory for ModemInfo");
6481 return NULL;
6482 }
6483 pthread_attr_init (&attr);
6484 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6485 ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
6486 if (ret < 0) {
6487 RLOGE("pthread_create: %s:", strerror(errno));
6488 return NULL;
6489 }
6490
6491 return &s_callbacks;
6492 }
6493 #else /* RIL_SHLIB */
6494 int main (int argc, char **argv)
6495 {
6496 int ret;
6497 int fd = -1;
6498 int opt;
6499
6500 while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
6501 switch (opt) {
6502 case 'p':
6503 s_port = atoi(optarg);
6504 if (s_port == 0) {
6505 usage(argv[0]);
6506 }
6507 RLOGI("Opening loopback port %d\n", s_port);
6508 break;
6509
6510 case 'd':
6511 s_device_path = optarg;
6512 RLOGI("Opening tty device %s\n", s_device_path);
6513 break;
6514
6515 case 's':
6516 s_device_path = optarg;
6517 s_device_socket = 1;
6518 RLOGI("Opening socket %s\n", s_device_path);
6519 break;
6520
6521 default:
6522 usage(argv[0]);
6523 }
6524 }
6525
6526 if (s_port < 0 && s_device_path == NULL && !isInEmulator()) {
6527 usage(argv[0]);
6528 }
6529
6530 RIL_register(&s_callbacks);
6531
6532 mainLoop(NULL);
6533
6534 return 0;
6535 }
6536
6537 #endif /* RIL_SHLIB */
6538