~phablet-team/ofono/ofono-bug-updates

« back to all changes in this revision

Viewing changes to drivers/rilmodem/gprs.c

  • Committer: Denis Kenzior
  • Author(s): Lucas De Marchi
  • Date: 2011-03-18 23:31:14 UTC
  • Revision ID: git-v1:888e07863b24026413bac8f449de377c879e1044
message: add cancelled state

Based on patch from Yang Gu <gyagp0@gmail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *
3
 
 *  oFono - Open Source Telephony
4
 
 *
5
 
 *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6
 
 *  Copyright (C) 2010  ST-Ericsson AB.
7
 
 *  Copyright (C) 2013 Canonical Ltd.
8
 
 *  Copyright (C) 2013 Jolla Ltd.
9
 
 *
10
 
 *  This program is free software; you can redistribute it and/or modify
11
 
 *  it under the terms of the GNU General Public License version 2 as
12
 
 *  published by the Free Software Foundation.
13
 
 *
14
 
 *  This program is distributed in the hope that it will be useful,
15
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 *  GNU General Public License for more details.
18
 
 *
19
 
 *  You should have received a copy of the GNU General Public License
20
 
 *  along with this program; if not, write to the Free Software
21
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22
 
 *
23
 
 */
24
 
 
25
 
#ifdef HAVE_CONFIG_H
26
 
#include <config.h>
27
 
#endif
28
 
 
29
 
#define _GNU_SOURCE
30
 
#include <string.h>
31
 
#include <stdlib.h>
32
 
#include <stdio.h>
33
 
#include <errno.h>
34
 
 
35
 
#include <glib.h>
36
 
 
37
 
#include <ofono/log.h>
38
 
#include <ofono/modem.h>
39
 
#include <ofono/gprs.h>
40
 
#include <ofono/types.h>
41
 
 
42
 
#include "gril.h"
43
 
#include "grilutil.h"
44
 
#include "common.h"
45
 
#include "rilmodem.h"
46
 
 
47
 
#include "grilreply.h"
48
 
#include "grilrequest.h"
49
 
#include "grilunsol.h"
50
 
#include "gprs.h"
51
 
 
52
 
/* Time between get data status retries */
53
 
#define GET_STATUS_TIMER_MS 5000
54
 
 
55
 
/*
56
 
 * This module is the ofono_gprs_driver implementation for rilmodem.
57
 
 *
58
 
 * Notes:
59
 
 *
60
 
 * 1. ofono_gprs_suspend/resume() are not used by this module, as
61
 
 *    the concept of suspended GPRS is not exposed by RILD.
62
 
 */
63
 
 
64
 
static int ril_tech_to_bearer_tech(int ril_tech)
65
 
{
66
 
        /*
67
 
         * This code handles the mapping between the RIL_RadioTechnology
68
 
         * and packet bearer values ( see <curr_bearer> values - 27.007
69
 
         * Section 7.29 ).
70
 
         */
71
 
 
72
 
        switch (ril_tech) {
73
 
        case RADIO_TECH_GSM:
74
 
        case RADIO_TECH_UNKNOWN:
75
 
                return PACKET_BEARER_NONE;
76
 
        case RADIO_TECH_GPRS:
77
 
                return PACKET_BEARER_GPRS;
78
 
        case RADIO_TECH_EDGE:
79
 
                return PACKET_BEARER_EGPRS;
80
 
        case RADIO_TECH_UMTS:
81
 
                return PACKET_BEARER_UMTS;
82
 
        case RADIO_TECH_HSDPA:
83
 
                return PACKET_BEARER_HSDPA;
84
 
        case RADIO_TECH_HSUPA:
85
 
                return PACKET_BEARER_HSUPA;
86
 
        case RADIO_TECH_HSPAP:
87
 
        case RADIO_TECH_HSPA:
88
 
                /*
89
 
                 * HSPAP is HSPA+; which ofono doesn't define;
90
 
                 * so, if differentiating HSPA and HSPA+ is
91
 
                 * important, then ofono needs to be patched,
92
 
                 * and we probably also need to introduce a
93
 
                 * new indicator icon.
94
 
                 */
95
 
                return PACKET_BEARER_HSUPA_HSDPA;
96
 
        case RADIO_TECH_LTE:
97
 
                return PACKET_BEARER_EPS;
98
 
        default:
99
 
                return PACKET_BEARER_NONE;
100
 
        }
101
 
}
102
 
 
103
 
static void ril_gprs_state_change(struct ril_msg *message, gpointer user_data)
104
 
{
105
 
        struct ofono_gprs *gprs = user_data;
106
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
107
 
 
108
 
        g_ril_print_unsol_no_args(gd->ril, message);
109
 
 
110
 
        /*
111
 
         * We just want to track network data status if ofono
112
 
         * itself is attached, so we avoid unnecessary data state requests.
113
 
         */
114
 
        if (gd->ofono_attached == TRUE)
115
 
                ril_gprs_registration_status(gprs, NULL, NULL);
116
 
}
117
 
 
118
 
gboolean ril_gprs_set_attached_cb(gpointer user_data)
119
 
{
120
 
        struct cb_data *cbd = user_data;
121
 
        ofono_gprs_cb_t cb = cbd->cb;
122
 
 
123
 
        DBG("");
124
 
 
125
 
        CALLBACK_WITH_SUCCESS(cb, cbd->data);
126
 
        g_free(cbd);
127
 
 
128
 
        /* Run once per g_idle_add() call */
129
 
        return FALSE;
130
 
}
131
 
 
132
 
static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached,
133
 
                                        ofono_gprs_cb_t cb, void *data)
134
 
{
135
 
        struct cb_data *cbd = cb_data_new(cb, data, NULL);
136
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
137
 
 
138
 
        DBG("attached: %d", attached);
139
 
 
140
 
        /*
141
 
         * As RIL offers no actual control over the GPRS 'attached'
142
 
         * state, we save the desired state, and use it to override
143
 
         * the actual modem's state in the 'attached_status' function.
144
 
         * This is similar to the way the core ofono gprs code handles
145
 
         * data roaming ( see src/gprs.c gprs_netreg_update().
146
 
         *
147
 
         * The core gprs code calls driver->set_attached() when a netreg
148
 
         * notificaiton is received and any configured roaming conditions
149
 
         * are met.
150
 
         */
151
 
        gd->ofono_attached = attached;
152
 
 
153
 
        /*
154
 
         * Call from idle loop, so core can set driver_attached before
155
 
         * the callback is invoked.
156
 
         */
157
 
        g_idle_add(ril_gprs_set_attached_cb, cbd);
158
 
}
159
 
 
160
 
static gboolean ril_get_status_retry(gpointer user_data)
161
 
{
162
 
        struct ofono_gprs *gprs = user_data;
163
 
 
164
 
        ril_gprs_registration_status(gprs, NULL, NULL);
165
 
 
166
 
        return FALSE;
167
 
}
168
 
 
169
 
static void ril_data_reg_cb(struct ril_msg *message, gpointer user_data)
170
 
{
171
 
        struct cb_data *cbd = user_data;
172
 
        ofono_gprs_status_cb_t cb = cbd->cb;
173
 
        struct ofono_gprs *gprs = cbd->user;
174
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
175
 
        struct reply_reg_state *reply;
176
 
        gboolean attached = FALSE;
177
 
        gboolean notify_status = FALSE;
178
 
        int old_status;
179
 
 
180
 
        old_status = gd->rild_status;
181
 
 
182
 
        if (message->error != RIL_E_SUCCESS) {
183
 
                ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s",
184
 
                                __func__,
185
 
                                ril_error_to_string(message->error));
186
 
                goto error;
187
 
        }
188
 
 
189
 
        if ((reply = g_ril_reply_parse_reg_state(gd->ril, message)) == NULL)
190
 
                goto error;
191
 
 
192
 
        /*
193
 
         * There are three cases that can result in this callback
194
 
         * running:
195
 
         *
196
 
         * 1) The driver's probe() method was called, and thus an
197
 
         *    internal call to ril_gprs_registration_status() is
198
 
         *    generated.  No ofono cb exists.
199
 
         *
200
 
         * 2) ril_gprs_state_change() is called due to an unsolicited
201
 
         *    event from RILD.  No ofono cb exists.
202
 
         *
203
 
         * 3) The ofono code code calls the driver's attached_status()
204
 
         *    function.  A valid ofono cb exists.
205
 
         */
206
 
 
207
 
        if (gd->rild_status != reply->status) {
208
 
                gd->rild_status = reply->status;
209
 
 
210
 
                if (cb == NULL)
211
 
                        notify_status = TRUE;
212
 
        }
213
 
 
214
 
        /*
215
 
         * Override the actual status based upon the desired
216
 
         * attached status set by the core GPRS code ( controlled
217
 
         * by the ConnnectionManager's 'Powered' property ).
218
 
         */
219
 
        attached = (reply->status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
220
 
                        reply->status == NETWORK_REGISTRATION_STATUS_ROAMING);
221
 
 
222
 
        if (attached && gd->ofono_attached == FALSE) {
223
 
                DBG("attached=true; ofono_attached=false; return !REGISTERED");
224
 
                reply->status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
225
 
 
226
 
                /*
227
 
                 * Further optimization so that if ril_status ==
228
 
                 * NOT_REGISTERED, ofono_attached == false, and status ==
229
 
                 * ROAMING | REGISTERED, then notify gets cleared...
230
 
                 *
231
 
                 * As is, this results in unecessary status notify calls
232
 
                 * when nothing has changed.
233
 
                 */
234
 
                if (notify_status && reply->status == old_status)
235
 
                        notify_status = FALSE;
236
 
        }
237
 
 
238
 
        if (old_status == -1) {
239
 
                ofono_gprs_register(gprs);
240
 
 
241
 
                /* Different rild implementations use different events here */
242
 
                g_ril_register(gd->ril,
243
 
                                gd->state_changed_unsol,
244
 
                                ril_gprs_state_change, gprs);
245
 
 
246
 
                if (reply->max_cids == 0)
247
 
                        gd->max_cids = RIL_MAX_NUM_ACTIVE_DATA_CALLS;
248
 
                else if (reply->max_cids < RIL_MAX_NUM_ACTIVE_DATA_CALLS)
249
 
                        gd->max_cids = reply->max_cids;
250
 
                else
251
 
                        gd->max_cids = RIL_MAX_NUM_ACTIVE_DATA_CALLS;
252
 
 
253
 
                DBG("Setting max cids to %d", gd->max_cids);
254
 
                ofono_gprs_set_cid_range(gprs, 1, gd->max_cids);
255
 
 
256
 
                /*
257
 
                 * This callback is a result of the inital call
258
 
                 * to probe(), so should return after registration.
259
 
                 */
260
 
                g_free(reply);
261
 
 
262
 
                return;
263
 
        }
264
 
 
265
 
        /* Just need to notify ofono if it's already attached */
266
 
        if (notify_status) {
267
 
 
268
 
                /*
269
 
                 * If network disconnect has occurred, call detached_notify()
270
 
                 * instead of status_notify().
271
 
                 */
272
 
                if (!attached &&
273
 
                        (old_status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
274
 
                                old_status ==
275
 
                                        NETWORK_REGISTRATION_STATUS_ROAMING)) {
276
 
                        DBG("calling ofono_gprs_detached_notify()");
277
 
                        ofono_gprs_detached_notify(gprs);
278
 
                        reply->tech = RADIO_TECH_UNKNOWN;
279
 
                } else {
280
 
                        DBG("calling ofono_gprs_status_notify()");
281
 
                        ofono_gprs_status_notify(gprs, reply->status);
282
 
                }
283
 
        }
284
 
 
285
 
        if (gd->tech != reply->tech) {
286
 
                gd->tech = reply->tech;
287
 
 
288
 
                ofono_gprs_bearer_notify(gprs,
289
 
                                        ril_tech_to_bearer_tech(reply->tech));
290
 
        }
291
 
 
292
 
        if (cb)
293
 
                CALLBACK_WITH_SUCCESS(cb, reply->status, cbd->data);
294
 
 
295
 
        g_free(reply);
296
 
 
297
 
        return;
298
 
error:
299
 
 
300
 
        /*
301
 
         * For some modems DATA_REGISTRATION_STATE will return an error until we
302
 
         * are registered in the voice network.
303
 
         */
304
 
        if (old_status == -1 && message->error == RIL_E_GENERIC_FAILURE)
305
 
                g_timeout_add(GET_STATUS_TIMER_MS, ril_get_status_retry, gprs);
306
 
 
307
 
        if (cb)
308
 
                CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
309
 
}
310
 
 
311
 
void ril_gprs_registration_status(struct ofono_gprs *gprs,
312
 
                                        ofono_gprs_status_cb_t cb, void *data)
313
 
{
314
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
315
 
        struct cb_data *cbd = cb_data_new(cb, data, gprs);
316
 
 
317
 
        DBG("");
318
 
 
319
 
        if (g_ril_send(gd->ril, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL,
320
 
                        ril_data_reg_cb, cbd, g_free) == 0) {
321
 
                ofono_error("%s: send "
322
 
                                "RIL_REQUEST_DATA_REGISTRATION_STATE failed",
323
 
                                __func__);
324
 
                g_free(cbd);
325
 
 
326
 
                if (cb != NULL)
327
 
                        CALLBACK_WITH_FAILURE(cb, -1, data);
328
 
        }
329
 
}
330
 
 
331
 
static void drop_data_call_cb(struct ril_msg *message, gpointer user_data)
332
 
{
333
 
        struct ofono_gprs *gprs = user_data;
334
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
335
 
 
336
 
        if (message->error == RIL_E_SUCCESS)
337
 
                g_ril_print_response_no_args(gd->ril, message);
338
 
        else
339
 
                ofono_error("%s: RIL error %s", __func__,
340
 
                                ril_error_to_string(message->error));
341
 
 
342
 
        if (--(gd->pending_deact_req) == 0)
343
 
                ril_gprs_registration_status(gprs, NULL, NULL);
344
 
}
345
 
 
346
 
static int drop_data_call(struct ofono_gprs *gprs, int cid)
347
 
{
348
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
349
 
        struct req_deactivate_data_call request;
350
 
        struct parcel rilp;
351
 
        struct ofono_error error;
352
 
 
353
 
        request.cid = cid;
354
 
        request.reason = RIL_DEACTIVATE_DATA_CALL_NO_REASON;
355
 
 
356
 
        g_ril_request_deactivate_data_call(gd->ril, &request, &rilp, &error);
357
 
 
358
 
        if (g_ril_send(gd->ril, RIL_REQUEST_DEACTIVATE_DATA_CALL,
359
 
                        &rilp, drop_data_call_cb, gprs, NULL) == 0) {
360
 
                ofono_error("%s: send failed", __func__);
361
 
                return -1;
362
 
        }
363
 
 
364
 
        return 0;
365
 
}
366
 
 
367
 
static void get_active_data_calls_cb(struct ril_msg *message,
368
 
                                        gpointer user_data)
369
 
{
370
 
        struct ofono_gprs *gprs = user_data;
371
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
372
 
        struct ril_data_call_list *call_list = NULL;
373
 
        GSList *iterator;
374
 
        struct ril_data_call *call;
375
 
 
376
 
        if (message->error != RIL_E_SUCCESS) {
377
 
                ofono_error("%s: RIL error %s", __func__,
378
 
                                ril_error_to_string(message->error));
379
 
                goto end;
380
 
        }
381
 
 
382
 
        /* reply can be NULL when there are no existing data calls */
383
 
        call_list = g_ril_unsol_parse_data_call_list(gd->ril, message);
384
 
        if (call_list == NULL)
385
 
                goto end;
386
 
 
387
 
        /*
388
 
         * We disconnect from previous calls here, which might be needed
389
 
         * because of a previous ofono abort, as some rild implementations do
390
 
         * not disconnect the calls even after the ril socket is closed.
391
 
         */
392
 
        for (iterator = call_list->calls; iterator; iterator = iterator->next) {
393
 
                call = iterator->data;
394
 
                DBG("Standing data call with cid %d", call->cid);
395
 
                if (drop_data_call(gprs, call->cid) == 0)
396
 
                        ++(gd->pending_deact_req);
397
 
        }
398
 
 
399
 
        g_ril_unsol_free_data_call_list(call_list);
400
 
 
401
 
end:
402
 
        if (gd->pending_deact_req == 0)
403
 
                ril_gprs_registration_status(gprs, NULL, NULL);
404
 
}
405
 
 
406
 
static void get_active_data_calls(struct ofono_gprs *gprs)
407
 
{
408
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
409
 
 
410
 
        if (g_ril_send(gd->ril, RIL_REQUEST_DATA_CALL_LIST, NULL,
411
 
                        get_active_data_calls_cb, gprs, NULL) == 0)
412
 
                ofono_error("%s: send failed", __func__);
413
 
}
414
 
 
415
 
void ril_gprs_start(GRil *ril, struct ofono_gprs *gprs,
416
 
                        struct ril_gprs_data *gd)
417
 
{
418
 
        gd->ril = g_ril_clone(ril);
419
 
        gd->ofono_attached = FALSE;
420
 
        gd->max_cids = 0;
421
 
        gd->rild_status = -1;
422
 
        gd->tech = RADIO_TECH_UNKNOWN;
423
 
        /* AOSP RILD tracks data network state together with voice */
424
 
        gd->state_changed_unsol =
425
 
                RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED;
426
 
 
427
 
        ofono_gprs_set_data(gprs, gd);
428
 
 
429
 
        get_active_data_calls(gprs);
430
 
}
431
 
 
432
 
int ril_gprs_probe(struct ofono_gprs *gprs, unsigned int vendor, void *data)
433
 
{
434
 
        GRil *ril = data;
435
 
        struct ril_gprs_data *gd;
436
 
 
437
 
        gd = g_try_new0(struct ril_gprs_data, 1);
438
 
        if (gd == NULL)
439
 
                return -ENOMEM;
440
 
 
441
 
        ril_gprs_start(ril, gprs, gd);
442
 
 
443
 
        return 0;
444
 
}
445
 
 
446
 
void ril_gprs_remove(struct ofono_gprs *gprs)
447
 
{
448
 
        struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
449
 
 
450
 
        DBG("");
451
 
 
452
 
        ofono_gprs_set_data(gprs, NULL);
453
 
 
454
 
        g_ril_unref(gd->ril);
455
 
        g_free(gd);
456
 
}
457
 
 
458
 
static struct ofono_gprs_driver driver = {
459
 
        .name                   = RILMODEM,
460
 
        .probe                  = ril_gprs_probe,
461
 
        .remove                 = ril_gprs_remove,
462
 
        .set_attached           = ril_gprs_set_attached,
463
 
        .attached_status        = ril_gprs_registration_status,
464
 
};
465
 
 
466
 
void ril_gprs_init(void)
467
 
{
468
 
        ofono_gprs_driver_register(&driver);
469
 
}
470
 
 
471
 
void ril_gprs_exit(void)
472
 
{
473
 
        ofono_gprs_driver_unregister(&driver);
474
 
}