1
|
/**
|
2
|
* This file is part of samsung-ril.
|
3
|
*
|
4
|
* Copyright (C) 2011-2012 Paul Kocialkowski <contact@oaulk.fr>
|
5
|
* Copyright (C) 2011 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
|
6
|
*
|
7
|
* samsung-ril is free software: you can redistribute it and/or modify
|
8
|
* it under the terms of the GNU General Public License as published by
|
9
|
* the Free Software Foundation, either version 3 of the License, or
|
10
|
* (at your option) any later version.
|
11
|
*
|
12
|
* samsung-ril is distributed in the hope that it will be useful,
|
13
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
* GNU General Public License for more details.
|
16
|
*
|
17
|
* You should have received a copy of the GNU General Public License
|
18
|
* along with samsung-ril. If not, see <http://www.gnu.org/licenses/>.
|
19
|
*
|
20
|
*/
|
21
|
|
22
|
#include <netinet/in.h>
|
23
|
#include <arpa/inet.h>
|
24
|
|
25
|
#define LOG_TAG "RIL-GPRS"
|
26
|
#include <utils/Log.h>
|
27
|
#include <cutils/properties.h>
|
28
|
|
29
|
#include "samsung-ril.h"
|
30
|
#include "util.h"
|
31
|
|
32
|
struct ril_gprs_connection **ril_gprs_connections;
|
33
|
int ril_gprs_connections_count;
|
34
|
|
35
|
RIL_LastDataCallActivateFailCause ipc2ril_gprs_fail_cause(unsigned short fail_cause)
|
36
|
{
|
37
|
switch(fail_cause) {
|
38
|
|
39
|
case IPC_GPRS_FAIL_INSUFFICIENT_RESOURCES:
|
40
|
return PDP_FAIL_INSUFFICIENT_RESOURCES;
|
41
|
case IPC_GPRS_FAIL_MISSING_UKNOWN_APN:
|
42
|
return PDP_FAIL_MISSING_UKNOWN_APN;
|
43
|
case IPC_GPRS_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
|
44
|
return PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE;
|
45
|
case IPC_GPRS_FAIL_USER_AUTHENTICATION:
|
46
|
return PDP_FAIL_USER_AUTHENTICATION;
|
47
|
case IPC_GPRS_FAIL_ACTIVATION_REJECT_GGSN:
|
48
|
return PDP_FAIL_ACTIVATION_REJECT_GGSN;
|
49
|
case IPC_GPRS_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
|
50
|
return PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED;
|
51
|
case IPC_GPRS_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
|
52
|
return PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED;
|
53
|
case IPC_GPRS_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
|
54
|
return PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED;
|
55
|
case IPC_GPRS_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
|
56
|
return PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER;
|
57
|
case IPC_GPRS_FAIL_NSAPI_IN_USE:
|
58
|
return PDP_FAIL_NSAPI_IN_USE;
|
59
|
default:
|
60
|
return PDP_FAIL_ERROR_UNSPECIFIED;
|
61
|
}
|
62
|
}
|
63
|
|
64
|
int ipc2ril_gprs_connection_active(unsigned char state)
|
65
|
{
|
66
|
switch(state) {
|
67
|
case IPC_GPRS_STATE_DISABLED:
|
68
|
return 1;
|
69
|
case IPC_GPRS_STATE_ENABLED:
|
70
|
return 2;
|
71
|
case IPC_GPRS_STATE_NOT_ENABLED:
|
72
|
default:
|
73
|
return 0;
|
74
|
}
|
75
|
}
|
76
|
|
77
|
void ril_gprs_connections_init(void)
|
78
|
{
|
79
|
struct ipc_client_gprs_capabilities gprs_capabilities;
|
80
|
struct ipc_client *ipc_client;
|
81
|
int ril_gprs_connections_size = 0;
|
82
|
|
83
|
ipc_client = ((struct ipc_client_object *) ipc_fmt_client->object)->ipc_client;
|
84
|
ipc_client_gprs_get_capabilities(ipc_client, &gprs_capabilities);
|
85
|
|
86
|
ril_gprs_connections_size =
|
87
|
gprs_capabilities.cid_max * sizeof(struct ril_gprs_connection *);
|
88
|
|
89
|
ril_gprs_connections = (struct ril_gprs_connection **)
|
90
|
malloc(ril_gprs_connections_size);
|
91
|
memset((void *) ril_gprs_connections, 0, ril_gprs_connections_size);
|
92
|
|
93
|
ril_gprs_connections_count = gprs_capabilities.cid_max;
|
94
|
}
|
95
|
|
96
|
int ril_gprs_connection_reg_id(void)
|
97
|
{
|
98
|
struct ril_gprs_connection *gprs_connection;
|
99
|
int i;
|
100
|
|
101
|
for(i=0 ; i < ril_gprs_connections_count ; i++) {
|
102
|
if(ril_gprs_connections[i] == NULL)
|
103
|
return i;
|
104
|
}
|
105
|
|
106
|
LOGD("No room left for another GPRS connection, trying to clean one up");
|
107
|
|
108
|
// When all the slots are taken, see if some are in a non-working state
|
109
|
for(i=0 ; i < ril_gprs_connections_count ; i++) {
|
110
|
if(ril_gprs_connections[i]->enabled == 0) {
|
111
|
ril_gprs_connection_del(ril_gprs_connections[i]);
|
112
|
|
113
|
return i;
|
114
|
}
|
115
|
}
|
116
|
|
117
|
return -1;
|
118
|
}
|
119
|
|
120
|
struct ril_gprs_connection *ril_gprs_connection_add(void)
|
121
|
{
|
122
|
struct ril_gprs_connection *gprs_connection = NULL;
|
123
|
int id = ril_gprs_connection_reg_id();
|
124
|
|
125
|
if(id < 0) {
|
126
|
LOGE("Unable to add another GPRS connection!");
|
127
|
return NULL;
|
128
|
}
|
129
|
|
130
|
gprs_connection = malloc(sizeof(struct ril_gprs_connection));
|
131
|
memset(gprs_connection, 0, sizeof(struct ril_gprs_connection));
|
132
|
|
133
|
gprs_connection->cid = id + 1;
|
134
|
gprs_connection->enabled = 0;
|
135
|
gprs_connection->interface = NULL;
|
136
|
gprs_connection->token = (RIL_Token) 0x00;
|
137
|
|
138
|
ril_gprs_connections[id] = gprs_connection;
|
139
|
|
140
|
return gprs_connection;
|
141
|
}
|
142
|
|
143
|
void ril_gprs_connection_del(struct ril_gprs_connection *gprs_connection)
|
144
|
{
|
145
|
int i;
|
146
|
|
147
|
if(gprs_connection == NULL)
|
148
|
return;
|
149
|
|
150
|
if(gprs_connection->interface != NULL)
|
151
|
free(gprs_connection->interface);
|
152
|
|
153
|
for(i=0 ; i < ril_gprs_connections_count ; i++)
|
154
|
if(ril_gprs_connections[i] == gprs_connection)
|
155
|
ril_gprs_connections[i] = NULL;
|
156
|
|
157
|
free(gprs_connection);
|
158
|
}
|
159
|
|
160
|
struct ril_gprs_connection *ril_gprs_connection_get_token(RIL_Token token)
|
161
|
{
|
162
|
int i;
|
163
|
|
164
|
for(i=0 ; i < ril_gprs_connections_count ; i++)
|
165
|
if(ril_gprs_connections[i] != NULL)
|
166
|
if(ril_gprs_connections[i]->token == token)
|
167
|
return ril_gprs_connections[i];
|
168
|
|
169
|
return NULL;
|
170
|
}
|
171
|
|
172
|
struct ril_gprs_connection *ril_gprs_connection_get_cid(int cid)
|
173
|
{
|
174
|
int i;
|
175
|
|
176
|
for(i=0 ; i < ril_gprs_connections_count ; i++)
|
177
|
if(ril_gprs_connections[i] != NULL)
|
178
|
if(ril_gprs_connections[i]->cid == cid)
|
179
|
return ril_gprs_connections[i];
|
180
|
|
181
|
return NULL;
|
182
|
}
|
183
|
|
184
|
void ipc_gprs_pdp_context_enable_complete(struct ipc_message_info *info)
|
185
|
{
|
186
|
struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
|
187
|
struct ril_gprs_connection *gprs_connection;
|
188
|
int rc;
|
189
|
|
190
|
gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq));
|
191
|
|
192
|
if(!gprs_connection) {
|
193
|
LOGE("Unable to find GPRS connection, aborting");
|
194
|
|
195
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
196
|
return;
|
197
|
}
|
198
|
|
199
|
rc = ipc_gen_phone_res_check(phone_res);
|
200
|
if(rc < 0) {
|
201
|
LOGE("There was an error, aborting PDP context complete");
|
202
|
|
203
|
gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
|
204
|
gprs_connection->token = (RIL_Token) 0x00;
|
205
|
ril_state.gprs_last_failed_cid = gprs_connection->cid;
|
206
|
|
207
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
208
|
return;
|
209
|
}
|
210
|
|
211
|
LOGD("Waiting for IP configuration!");
|
212
|
}
|
213
|
|
214
|
void ipc_gprs_define_pdp_context_complete(struct ipc_message_info *info)
|
215
|
{
|
216
|
struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
|
217
|
struct ril_gprs_connection *gprs_connection;
|
218
|
int aseq;
|
219
|
int rc;
|
220
|
|
221
|
gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq));
|
222
|
|
223
|
if(!gprs_connection) {
|
224
|
LOGE("Unable to find GPRS connection, aborting");
|
225
|
|
226
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
227
|
return;
|
228
|
}
|
229
|
|
230
|
rc = ipc_gen_phone_res_check(phone_res);
|
231
|
if(rc < 0) {
|
232
|
LOGE("There was an error, aborting define PDP context complete");
|
233
|
|
234
|
gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
|
235
|
gprs_connection->token = (RIL_Token) 0x00;
|
236
|
ril_state.gprs_last_failed_cid = gprs_connection->cid;
|
237
|
|
238
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
239
|
return;
|
240
|
}
|
241
|
|
242
|
// We need to get a clean new aseq here
|
243
|
aseq = ril_request_reg_id(reqGetToken(info->aseq));
|
244
|
|
245
|
ipc_gen_phone_res_expect_to_func(aseq, IPC_GPRS_PDP_CONTEXT,
|
246
|
ipc_gprs_pdp_context_enable_complete);
|
247
|
|
248
|
ipc_fmt_send(IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET,
|
249
|
(void *) &(gprs_connection->context), sizeof(struct ipc_gprs_pdp_context_set), aseq);
|
250
|
}
|
251
|
|
252
|
void ipc_gprs_port_list_complete(struct ipc_message_info *info)
|
253
|
{
|
254
|
struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
|
255
|
struct ril_gprs_connection *gprs_connection;
|
256
|
int rc;
|
257
|
int aseq;
|
258
|
|
259
|
gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq));
|
260
|
|
261
|
if(!gprs_connection) {
|
262
|
LOGE("Unable to find GPRS connection, aborting");
|
263
|
|
264
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
265
|
return;
|
266
|
}
|
267
|
|
268
|
rc = ipc_gen_phone_res_check(phone_res);
|
269
|
if(rc < 0) {
|
270
|
LOGE("There was an error, aborting port list complete");
|
271
|
|
272
|
gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
|
273
|
gprs_connection->token = (RIL_Token) 0x00;
|
274
|
ril_state.gprs_last_failed_cid = gprs_connection->cid;
|
275
|
|
276
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
277
|
return;
|
278
|
}
|
279
|
|
280
|
// We need to get a clean new aseq here
|
281
|
aseq = ril_request_reg_id(reqGetToken(info->aseq));
|
282
|
|
283
|
ipc_gen_phone_res_expect_to_func(aseq, IPC_GPRS_DEFINE_PDP_CONTEXT,
|
284
|
ipc_gprs_define_pdp_context_complete);
|
285
|
|
286
|
ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET,
|
287
|
(void *) &(gprs_connection->define_context), sizeof(struct ipc_gprs_define_pdp_context), aseq);
|
288
|
}
|
289
|
|
290
|
void ril_request_setup_data_call(RIL_Token t, void *data, int length)
|
291
|
{
|
292
|
struct ril_gprs_connection *gprs_connection = NULL;
|
293
|
struct ipc_client_gprs_capabilities gprs_capabilities;
|
294
|
struct ipc_gprs_port_list port_list;
|
295
|
struct ipc_client *ipc_client;
|
296
|
|
297
|
char *username = NULL;
|
298
|
char *password = NULL;
|
299
|
char *apn = NULL;
|
300
|
|
301
|
ipc_client = ((struct ipc_client_object *) ipc_fmt_client->object)->ipc_client;
|
302
|
|
303
|
apn = ((char **) data)[2];
|
304
|
username = ((char **) data)[3];
|
305
|
password = ((char **) data)[4];
|
306
|
|
307
|
LOGD("Requesting data connection to APN '%s'\n", apn);
|
308
|
|
309
|
gprs_connection = ril_gprs_connection_add();
|
310
|
|
311
|
if(!gprs_connection) {
|
312
|
LOGE("Unable to create GPRS connection, aborting");
|
313
|
|
314
|
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
|
315
|
return;
|
316
|
}
|
317
|
|
318
|
gprs_connection->token = t;
|
319
|
|
320
|
// Create the structs with the apn
|
321
|
ipc_gprs_define_pdp_context_setup(&(gprs_connection->define_context), gprs_connection->cid, 1, apn);
|
322
|
|
323
|
// Create the structs with the username/password tuple
|
324
|
ipc_gprs_pdp_context_setup(&(gprs_connection->context), gprs_connection->cid, 1, username, password);
|
325
|
|
326
|
ipc_client_gprs_get_capabilities(ipc_client, &gprs_capabilities);
|
327
|
|
328
|
// If the device has the capability, deal with port list
|
329
|
if(gprs_capabilities.port_list) {
|
330
|
ipc_gprs_port_list_setup(&port_list);
|
331
|
|
332
|
ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_GPRS_PORT_LIST,
|
333
|
ipc_gprs_port_list_complete);
|
334
|
|
335
|
ipc_fmt_send(IPC_GPRS_PORT_LIST, IPC_TYPE_SET,
|
336
|
(void *) &port_list, sizeof(struct ipc_gprs_port_list), reqGetId(t));
|
337
|
} else {
|
338
|
ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_GPRS_DEFINE_PDP_CONTEXT,
|
339
|
ipc_gprs_define_pdp_context_complete);
|
340
|
|
341
|
ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET,
|
342
|
(void *) &(gprs_connection->define_context), sizeof(struct ipc_gprs_define_pdp_context), reqGetId(t));
|
343
|
}
|
344
|
}
|
345
|
|
346
|
void ipc_gprs_ip_configuration(struct ipc_message_info *info)
|
347
|
{
|
348
|
struct ril_gprs_connection *gprs_connection;
|
349
|
struct ipc_gprs_ip_configuration *ip_configuration =
|
350
|
(struct ipc_gprs_ip_configuration *) info->data;
|
351
|
|
352
|
gprs_connection = ril_gprs_connection_get_cid(ip_configuration->cid);
|
353
|
|
354
|
if(!gprs_connection) {
|
355
|
LOGE("Unable to find GPRS connection, aborting");
|
356
|
|
357
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
358
|
return;
|
359
|
}
|
360
|
|
361
|
LOGD("Obtained IP Configuration");
|
362
|
|
363
|
// Copy the obtained IP configuration to the GPRS connection structure
|
364
|
memcpy(&(gprs_connection->ip_configuration), ip_configuration, sizeof(struct ipc_gprs_ip_configuration));
|
365
|
|
366
|
LOGD("Waiting for GPRS call status");
|
367
|
}
|
368
|
|
369
|
void ipc_gprs_pdp_context_disable_complete(struct ipc_message_info *info)
|
370
|
{
|
371
|
struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
|
372
|
struct ril_gprs_connection *gprs_connection;
|
373
|
int rc;
|
374
|
|
375
|
gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq));
|
376
|
|
377
|
if(!gprs_connection) {
|
378
|
LOGE("Unable to find GPRS connection, aborting");
|
379
|
|
380
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
381
|
return;
|
382
|
}
|
383
|
|
384
|
rc = ipc_gen_phone_res_check(phone_res);
|
385
|
if(rc < 0) {
|
386
|
LOGE("There was an error, aborting PDP context complete");
|
387
|
|
388
|
// RILJ is not going to ask for fail reason
|
389
|
ril_gprs_connection_del(gprs_connection);
|
390
|
|
391
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
392
|
return;
|
393
|
}
|
394
|
|
395
|
LOGD("Waiting for GPRS call status");
|
396
|
}
|
397
|
|
398
|
void ril_request_deactivate_data_call(RIL_Token t, void *data, int length)
|
399
|
{
|
400
|
struct ril_gprs_connection *gprs_connection;
|
401
|
struct ipc_gprs_pdp_context_set context;
|
402
|
|
403
|
char *cid = ((char **) data)[0];
|
404
|
int rc;
|
405
|
|
406
|
gprs_connection = ril_gprs_connection_get_cid(atoi(cid));
|
407
|
|
408
|
if(!gprs_connection) {
|
409
|
LOGE("Unable to find GPRS connection, aborting");
|
410
|
|
411
|
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
|
412
|
return;
|
413
|
}
|
414
|
|
415
|
gprs_connection->token = t;
|
416
|
|
417
|
ipc_gprs_pdp_context_setup(&context, gprs_connection->cid, 0, NULL, NULL);
|
418
|
|
419
|
ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_GPRS_PDP_CONTEXT,
|
420
|
ipc_gprs_pdp_context_disable_complete);
|
421
|
|
422
|
ipc_fmt_send(IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET,
|
423
|
(void *) &context, sizeof(struct ipc_gprs_pdp_context_set), reqGetId(t));
|
424
|
}
|
425
|
|
426
|
int ipc_gprs_connection_enable(struct ril_gprs_connection *gprs_connection, char **setup_data_call_response)
|
427
|
{
|
428
|
struct ipc_client *ipc_client;
|
429
|
struct ipc_gprs_ip_configuration *ip_configuration;
|
430
|
|
431
|
char *interface = NULL;
|
432
|
char *ip;
|
433
|
char *gateway;
|
434
|
char *subnet_mask;
|
435
|
char *dns1;
|
436
|
char *dns2;
|
437
|
|
438
|
char prop_name[PROPERTY_KEY_MAX];
|
439
|
|
440
|
int rc;
|
441
|
|
442
|
ipc_client = ((struct ipc_client_object *) ipc_fmt_client->object)->ipc_client;
|
443
|
|
444
|
ip_configuration = &(gprs_connection->ip_configuration);
|
445
|
|
446
|
asprintf(&ip, "%i.%i.%i.%i", (ip_configuration->ip)[0],(ip_configuration->ip)[1], (ip_configuration->ip)[2],(ip_configuration->ip)[3]);
|
447
|
// FIXME: gateway isn't reliable!
|
448
|
asprintf(&gateway, "%i.%i.%i.%i", (ip_configuration->ip)[0],(ip_configuration->ip)[1], (ip_configuration->ip)[2],(ip_configuration->ip)[3]);
|
449
|
// FIXME: subnet isn't reliable!
|
450
|
asprintf(&subnet_mask, "255.255.255.255");
|
451
|
asprintf(&dns1, "%i.%i.%i.%i", (ip_configuration->dns1)[0],(ip_configuration->dns1)[1], (ip_configuration->dns1)[2],(ip_configuration->dns1)[3]);
|
452
|
asprintf(&dns2, "%i.%i.%i.%i", (ip_configuration->dns2)[0],(ip_configuration->dns2)[1],(ip_configuration->dns2)[2],(ip_configuration->dns2)[3]);
|
453
|
|
454
|
if(ipc_client_gprs_handlers_available(ipc_client)) {
|
455
|
rc = ipc_client_gprs_activate(ipc_client);
|
456
|
if(rc < 0) {
|
457
|
// This is not a critical issue
|
458
|
LOGE("Failed to activate interface!");
|
459
|
}
|
460
|
}
|
461
|
|
462
|
rc = ipc_client_gprs_get_iface(ipc_client, &interface, gprs_connection->cid);
|
463
|
if(rc < 0) {
|
464
|
// This is not a critical issue, fallback to rmnet
|
465
|
LOGE("Failed to get interface name!");
|
466
|
asprintf(&interface, "rmnet%d", gprs_connection->cid - 1);
|
467
|
}
|
468
|
|
469
|
if(gprs_connection->interface == NULL && interface != NULL) {
|
470
|
gprs_connection->interface = strdup(interface);
|
471
|
}
|
472
|
|
473
|
LOGD("Using net interface: %s\n", interface);
|
474
|
|
475
|
LOGD("GPRS configuration: iface: %s, ip:%s, gateway:%s, subnet_mask:%s, dns1:%s, dns2:%s",
|
476
|
interface, ip, gateway, subnet_mask, dns1, dns2);
|
477
|
|
478
|
rc = ifc_configure(interface, inet_addr(ip),
|
479
|
inet_addr(subnet_mask), inet_addr(gateway),
|
480
|
inet_addr(dns1), inet_addr(dns2));
|
481
|
|
482
|
if(rc < 0) {
|
483
|
LOGE("ifc_configure failed");
|
484
|
|
485
|
free(interface);
|
486
|
return -1;
|
487
|
}
|
488
|
|
489
|
snprintf(prop_name, PROPERTY_KEY_MAX, "net.%s.dns1", interface);
|
490
|
property_set(prop_name, dns1);
|
491
|
snprintf(prop_name, PROPERTY_KEY_MAX, "net.%s.dns2", interface);
|
492
|
property_set(prop_name, dns2);
|
493
|
snprintf(prop_name, PROPERTY_KEY_MAX, "net.%s.gw", interface);
|
494
|
property_set(prop_name, gateway);
|
495
|
|
496
|
asprintf(&(setup_data_call_response[0]), "%d", gprs_connection->cid);
|
497
|
setup_data_call_response[1] = interface;
|
498
|
setup_data_call_response[2] = ip;
|
499
|
|
500
|
free(gateway);
|
501
|
free(subnet_mask);
|
502
|
free(dns1);
|
503
|
free(dns2);
|
504
|
|
505
|
return 0;
|
506
|
}
|
507
|
|
508
|
int ipc_gprs_connection_disable(struct ril_gprs_connection *gprs_connection)
|
509
|
{
|
510
|
struct ipc_client *ipc_client;
|
511
|
|
512
|
char *interface;
|
513
|
int rc;
|
514
|
|
515
|
ipc_client = ((struct ipc_client_object *) ipc_fmt_client->object)->ipc_client;
|
516
|
|
517
|
if(gprs_connection->interface == NULL) {
|
518
|
rc = ipc_client_gprs_get_iface(ipc_client, &interface, gprs_connection->cid);
|
519
|
if(rc < 0) {
|
520
|
// This is not a critical issue, fallback to rmnet
|
521
|
LOGE("Failed to get interface name!");
|
522
|
asprintf(&interface, "rmnet%d", gprs_connection->cid);
|
523
|
}
|
524
|
} else {
|
525
|
interface = gprs_connection->interface;
|
526
|
}
|
527
|
|
528
|
LOGD("Using net interface: %s\n", interface);
|
529
|
|
530
|
rc = ifc_down(interface);
|
531
|
|
532
|
if(gprs_connection->interface == NULL)
|
533
|
free(interface);
|
534
|
|
535
|
if(rc < 0) {
|
536
|
LOGE("ifc_down failed");
|
537
|
}
|
538
|
|
539
|
if(ipc_client_gprs_handlers_available(ipc_client)) {
|
540
|
rc = ipc_client_gprs_deactivate(ipc_client);
|
541
|
if(rc < 0) {
|
542
|
// This is not a critical issue
|
543
|
LOGE("Failed to deactivate interface!");
|
544
|
}
|
545
|
}
|
546
|
|
547
|
return 0;
|
548
|
}
|
549
|
|
550
|
void ipc_gprs_call_status(struct ipc_message_info *info)
|
551
|
{
|
552
|
struct ril_gprs_connection *gprs_connection;
|
553
|
struct ipc_gprs_call_status *call_status =
|
554
|
(struct ipc_gprs_call_status *) info->data;
|
555
|
|
556
|
char *setup_data_call_response[3] = { NULL, NULL, NULL };
|
557
|
int rc;
|
558
|
|
559
|
gprs_connection = ril_gprs_connection_get_cid(call_status->cid);
|
560
|
|
561
|
if(!gprs_connection) {
|
562
|
LOGE("Unable to find GPRS connection, aborting");
|
563
|
|
564
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
|
565
|
return;
|
566
|
}
|
567
|
|
568
|
if(call_status->fail_cause == 0) {
|
569
|
if(!gprs_connection->enabled &&
|
570
|
call_status->state == IPC_GPRS_STATE_ENABLED &&
|
571
|
gprs_connection->token != (RIL_Token) 0x00) {
|
572
|
LOGD("GPRS connection is now enabled");
|
573
|
|
574
|
rc = ipc_gprs_connection_enable(gprs_connection, setup_data_call_response);
|
575
|
if(rc < 0) {
|
576
|
LOGE("Failed to enable and configure GPRS interface");
|
577
|
|
578
|
gprs_connection->enabled = 0;
|
579
|
gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
|
580
|
ril_state.gprs_last_failed_cid = gprs_connection->cid;
|
581
|
|
582
|
RIL_onRequestComplete(gprs_connection->token, RIL_E_GENERIC_FAILURE, NULL, 0);
|
583
|
} else {
|
584
|
LOGD("GPRS interface enabled");
|
585
|
|
586
|
gprs_connection->enabled = 1;
|
587
|
|
588
|
RIL_onRequestComplete(gprs_connection->token, RIL_E_SUCCESS, setup_data_call_response, sizeof(setup_data_call_response));
|
589
|
gprs_connection->token = (RIL_Token) 0x00;
|
590
|
}
|
591
|
|
592
|
if(setup_data_call_response[0] != NULL)
|
593
|
free(setup_data_call_response[0]);
|
594
|
if(setup_data_call_response[1] != NULL)
|
595
|
free(setup_data_call_response[1]);
|
596
|
if(setup_data_call_response[2] != NULL)
|
597
|
free(setup_data_call_response[2]);
|
598
|
} else if(gprs_connection->enabled &&
|
599
|
call_status->state == IPC_GPRS_STATE_DISABLED &&
|
600
|
gprs_connection->token != (RIL_Token) 0x00) {
|
601
|
LOGD("GPRS connection is now disabled");
|
602
|
|
603
|
rc = ipc_gprs_connection_disable(gprs_connection);
|
604
|
if(rc < 0) {
|
605
|
LOGE("Failed to disable GPRS interface");
|
606
|
|
607
|
RIL_onRequestComplete(gprs_connection->token, RIL_E_GENERIC_FAILURE, NULL, 0);
|
608
|
|
609
|
// RILJ is not going to ask for fail reason
|
610
|
ril_gprs_connection_del(gprs_connection);
|
611
|
} else {
|
612
|
LOGD("GPRS interface disabled");
|
613
|
|
614
|
gprs_connection->enabled = 0;
|
615
|
|
616
|
RIL_onRequestComplete(gprs_connection->token, RIL_E_SUCCESS, NULL, 0);
|
617
|
|
618
|
ril_gprs_connection_del(gprs_connection);
|
619
|
}
|
620
|
} else {
|
621
|
LOGE("GPRS connection reported as changed though state is not OK:\n\tgprs_connection->enabled=%d\n\tgprs_connection->token=0x%x",
|
622
|
gprs_connection->enabled, gprs_connection->token);
|
623
|
|
624
|
ril_unsol_data_call_list_changed();
|
625
|
}
|
626
|
} else {
|
627
|
if(!gprs_connection->enabled &&
|
628
|
(call_status->state == IPC_GPRS_STATE_NOT_ENABLED ||
|
629
|
call_status->state == IPC_GPRS_STATE_DISABLED) &&
|
630
|
gprs_connection->token != (RIL_Token) 0x00) {
|
631
|
LOGE("Failed to enable GPRS connection");
|
632
|
|
633
|
gprs_connection->enabled = 0;
|
634
|
gprs_connection->fail_cause = ipc2ril_gprs_fail_cause(call_status->fail_cause);
|
635
|
ril_state.gprs_last_failed_cid = gprs_connection->cid;
|
636
|
|
637
|
RIL_onRequestComplete(gprs_connection->token, RIL_E_GENERIC_FAILURE, NULL, 0);
|
638
|
gprs_connection->token = (RIL_Token) 0x00;
|
639
|
|
640
|
ril_unsol_data_call_list_changed();
|
641
|
} else if(gprs_connection->enabled &&
|
642
|
call_status->state == IPC_GPRS_STATE_DISABLED) {
|
643
|
LOGE("GPRS connection suddently got disabled");
|
644
|
|
645
|
rc = ipc_gprs_connection_disable(gprs_connection);
|
646
|
if(rc < 0) {
|
647
|
LOGE("Failed to disable GPRS interface");
|
648
|
|
649
|
// RILJ is not going to ask for fail reason
|
650
|
ril_gprs_connection_del(gprs_connection);
|
651
|
} else {
|
652
|
LOGE("GPRS interface disabled");
|
653
|
|
654
|
gprs_connection->enabled = 0;
|
655
|
ril_gprs_connection_del(gprs_connection);
|
656
|
}
|
657
|
|
658
|
ril_unsol_data_call_list_changed();
|
659
|
} else {
|
660
|
LOGE("GPRS connection reported to have failed though state is OK:\n\tgprs_connection->enabled=%d\n\tgprs_connection->token=0x%x",
|
661
|
gprs_connection->enabled, gprs_connection->token);
|
662
|
|
663
|
ril_unsol_data_call_list_changed();
|
664
|
}
|
665
|
}
|
666
|
}
|
667
|
|
668
|
void ril_request_last_data_call_fail_cause(RIL_Token t)
|
669
|
{
|
670
|
struct ril_gprs_connection *gprs_connection;
|
671
|
int last_failed_cid;
|
672
|
int fail_cause;
|
673
|
|
674
|
last_failed_cid = ril_state.gprs_last_failed_cid;
|
675
|
|
676
|
if(!last_failed_cid) {
|
677
|
LOGE("No GPRS connection was reported to have failed");
|
678
|
|
679
|
goto fail_cause_unspecified;
|
680
|
}
|
681
|
|
682
|
gprs_connection = ril_gprs_connection_get_cid(last_failed_cid);
|
683
|
|
684
|
if(!gprs_connection) {
|
685
|
LOGE("Unable to find GPRS connection");
|
686
|
|
687
|
goto fail_cause_unspecified;
|
688
|
}
|
689
|
|
690
|
fail_cause = gprs_connection->fail_cause;
|
691
|
|
692
|
LOGD("Destroying GPRS connection with cid: %d", gprs_connection->cid);
|
693
|
ril_gprs_connection_del(gprs_connection);
|
694
|
|
695
|
goto fail_cause_return;
|
696
|
|
697
|
fail_cause_unspecified:
|
698
|
fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
|
699
|
|
700
|
fail_cause_return:
|
701
|
ril_state.gprs_last_failed_cid = 0;
|
702
|
RIL_onRequestComplete(t, RIL_E_SUCCESS, &fail_cause, sizeof(fail_cause));
|
703
|
}
|
704
|
|
705
|
/*
|
706
|
* Some modem firmwares have a bug that will make the first cid (1) overriden
|
707
|
* by the current cid, thus reporting it twice, with a wrong 2nd status.
|
708
|
*
|
709
|
* This shouldn't change anything to healthy structures.
|
710
|
*/
|
711
|
void ipc_gprs_pdp_context_fix(RIL_Data_Call_Response *data_call_list, int c)
|
712
|
{
|
713
|
int i, j, k;
|
714
|
|
715
|
for(i=0 ; i < c ; i++) {
|
716
|
for(j=i-1 ; j >= 0 ; j--) {
|
717
|
if(data_call_list[i].cid == data_call_list[j].cid) {
|
718
|
for(k=0 ; k < c ; k++) {
|
719
|
if(data_call_list[k].cid == 1) {
|
720
|
data_call_list[i].cid = 0;
|
721
|
break;
|
722
|
}
|
723
|
}
|
724
|
|
725
|
data_call_list[i].cid = 1;
|
726
|
}
|
727
|
}
|
728
|
}
|
729
|
}
|
730
|
|
731
|
void ipc_gprs_pdp_context(struct ipc_message_info *info)
|
732
|
{
|
733
|
struct ril_gprs_connection *gprs_connection;
|
734
|
struct ipc_gprs_ip_configuration *ip_configuration;
|
735
|
struct ipc_gprs_pdp_context_get *context =
|
736
|
(struct ipc_gprs_pdp_context_get *) info->data;
|
737
|
|
738
|
RIL_Data_Call_Response data_call_list[IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT];
|
739
|
|
740
|
int i;
|
741
|
|
742
|
for(i=0 ; i < IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT ; i++) {
|
743
|
data_call_list[i].cid = context->desc[i].cid;
|
744
|
data_call_list[i].active = ipc2ril_gprs_connection_active(context->desc[i].state);
|
745
|
|
746
|
if(context->desc[i].state == IPC_GPRS_STATE_ENABLED) {
|
747
|
gprs_connection = ril_gprs_connection_get_cid(context->desc[i].cid);
|
748
|
|
749
|
if(gprs_connection == NULL) {
|
750
|
LOGE("CID %d reported as enabled but not listed here");
|
751
|
goto empty;
|
752
|
}
|
753
|
|
754
|
ip_configuration = &(gprs_connection->ip_configuration);
|
755
|
|
756
|
asprintf(&(data_call_list[i].type), "IP");
|
757
|
asprintf(&(data_call_list[i].apn), "%s",
|
758
|
gprs_connection->define_context.apn);
|
759
|
asprintf(&(data_call_list[i].address), "%i.%i.%i.%i",
|
760
|
(ip_configuration->ip)[0],(ip_configuration->ip)[1], (ip_configuration->ip)[2],(ip_configuration->ip)[3]);
|
761
|
|
762
|
continue;
|
763
|
}
|
764
|
|
765
|
empty:
|
766
|
data_call_list[i].type = NULL;
|
767
|
data_call_list[i].apn = NULL;
|
768
|
data_call_list[i].address = NULL;
|
769
|
}
|
770
|
|
771
|
ipc_gprs_pdp_context_fix(data_call_list, IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT);
|
772
|
|
773
|
if(info->aseq == 0xff)
|
774
|
RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, &data_call_list, sizeof(data_call_list));
|
775
|
else
|
776
|
RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, &data_call_list, sizeof(data_call_list));
|
777
|
|
778
|
for(i=0 ; i < IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT ; i++) {
|
779
|
if(data_call_list[i].type != NULL)
|
780
|
free(data_call_list[i].type);
|
781
|
if(data_call_list[i].apn != NULL)
|
782
|
free(data_call_list[i].apn);
|
783
|
if(data_call_list[i].address != NULL)
|
784
|
free(data_call_list[i].address);
|
785
|
}
|
786
|
}
|
787
|
|
788
|
void ril_unsol_data_call_list_changed(void)
|
789
|
{
|
790
|
ipc_fmt_send_get(IPC_GPRS_PDP_CONTEXT, 0xff);
|
791
|
}
|
792
|
|
793
|
void ril_request_data_call_list(RIL_Token t)
|
794
|
{
|
795
|
ipc_fmt_send_get(IPC_GPRS_PDP_CONTEXT, reqGetId(t));
|
796
|
}
|