~awe/phablet-extras/ofono-lp1204683

« back to all changes in this revision

Viewing changes to drivers/atmodem/network-registration.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Salomon
  • Date: 2009-08-15 15:55:11 UTC
  • Revision ID: james.westby@ubuntu.com-20090815155511-frst06dijguhyfi4
Tags: upstream-0.3
ImportĀ upstreamĀ versionĀ 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  oFono - Open Source Telephony
 
4
 *
 
5
 *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
 
6
 *
 
7
 *  This program is free software; you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License version 2 as
 
9
 *  published by the Free Software Foundation.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 *
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
 
 
26
#define _GNU_SOURCE
 
27
#include <string.h>
 
28
#include <stdlib.h>
 
29
#include <stdio.h>
 
30
 
 
31
#include <glib.h>
 
32
 
 
33
#include <ofono/log.h>
 
34
#include <ofono/modem.h>
 
35
#include "driver.h"
 
36
 
 
37
#include "gatchat.h"
 
38
#include "gatresult.h"
 
39
 
 
40
#include "at.h"
 
41
 
 
42
static const char *none_prefix[] = { NULL };
 
43
static const char *creg_prefix[] = { "+CREG:", NULL };
 
44
static const char *cops_prefix[] = { "+COPS:", NULL };
 
45
static const char *csq_prefix[] = { "+CSQ:", NULL };
 
46
 
 
47
struct netreg_data {
 
48
        char mcc[OFONO_MAX_MCC_LENGTH + 1];
 
49
        char mnc[OFONO_MAX_MNC_LENGTH + 1];
 
50
};
 
51
 
 
52
static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
 
53
{
 
54
        /* Three digit country code */
 
55
        strncpy(mcc, str, OFONO_MAX_MCC_LENGTH);
 
56
        mcc[OFONO_MAX_MCC_LENGTH] = '\0';
 
57
 
 
58
        /* Usually a 2 but sometimes 3 digit network code */
 
59
        strncpy(mnc, str + OFONO_MAX_MCC_LENGTH, OFONO_MAX_MNC_LENGTH);
 
60
        mnc[OFONO_MAX_MNC_LENGTH] = '\0';
 
61
}
 
62
 
 
63
static void at_creg_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
64
{
 
65
        struct cb_data *cbd = user_data;
 
66
        GAtResultIter iter;
 
67
        ofono_registration_status_cb_t cb = cbd->cb;
 
68
        int status;
 
69
        const char *str;
 
70
        int lac = -1, ci = -1, tech = -1;
 
71
        struct ofono_error error;
 
72
 
 
73
        dump_response("at_creg_cb", ok, result);
 
74
        decode_at_error(&error, g_at_result_final_response(result));
 
75
 
 
76
        if (!ok) {
 
77
                cb(&error, -1, -1, -1, -1, cbd->data);
 
78
                return;
 
79
        }
 
80
 
 
81
        g_at_result_iter_init(&iter, result);
 
82
 
 
83
        if (!g_at_result_iter_next(&iter, "+CREG:")) {
 
84
                DECLARE_FAILURE(e);
 
85
 
 
86
                cb(&e, -1, -1, -1, -1, cbd->data);
 
87
                return;
 
88
        }
 
89
 
 
90
        /* Skip <n> the unsolicited result code */
 
91
        g_at_result_iter_skip_next(&iter);
 
92
 
 
93
        g_at_result_iter_next_number(&iter, &status);
 
94
 
 
95
        if (g_at_result_iter_next_string(&iter, &str) == TRUE)
 
96
                lac = strtol(str, NULL, 16);
 
97
        else
 
98
                goto out;
 
99
 
 
100
        if (g_at_result_iter_next_string(&iter, &str) == TRUE)
 
101
                ci = strtol(str, NULL, 16);
 
102
        else
 
103
                goto out;
 
104
 
 
105
        g_at_result_iter_next_number(&iter, &tech);
 
106
 
 
107
out:
 
108
        ofono_debug("creg_cb: %d, %d, %d, %d", status, lac, ci, tech);
 
109
 
 
110
        cb(&error, status, lac, ci, tech, cbd->data);
 
111
}
 
112
 
 
113
static void at_registration_status(struct ofono_modem *modem,
 
114
                                        ofono_registration_status_cb_t cb,
 
115
                                        void *data)
 
116
{
 
117
        struct at_data *at = ofono_modem_get_userdata(modem);
 
118
        struct cb_data *cbd = cb_data_new(modem, cb, data);
 
119
 
 
120
        if (!cbd)
 
121
                goto error;
 
122
 
 
123
        if (g_at_chat_send(at->parser, "AT+CREG?", creg_prefix,
 
124
                                at_creg_cb, cbd, g_free) > 0)
 
125
                return;
 
126
 
 
127
error:
 
128
        if (cbd)
 
129
                g_free(cbd);
 
130
 
 
131
        {
 
132
                DECLARE_FAILURE(error);
 
133
                cb(&error, -1, -1, -1, -1, data);
 
134
        }
 
135
}
 
136
 
 
137
static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
138
{
 
139
        struct cb_data *cbd = user_data;
 
140
        struct at_data *at = ofono_modem_get_userdata(cbd->modem);
 
141
        ofono_current_operator_cb_t cb = cbd->cb;
 
142
        struct ofono_network_operator op;
 
143
        GAtResultIter iter;
 
144
        int format, tech;
 
145
        const char *name;
 
146
        struct ofono_error error;
 
147
 
 
148
        dump_response("cops_cb", ok, result);
 
149
        decode_at_error(&error, g_at_result_final_response(result));
 
150
 
 
151
        if (!ok || at->netreg->mcc[0] == '\0' || at->netreg->mnc[0] == '\0') {
 
152
                cb(&error, NULL, cbd->data);
 
153
                goto out;
 
154
        }
 
155
 
 
156
        g_at_result_iter_init(&iter, result);
 
157
 
 
158
        if (!g_at_result_iter_next(&iter, "+COPS:"))
 
159
                goto error;
 
160
 
 
161
        g_at_result_iter_skip_next(&iter);
 
162
 
 
163
        ok = g_at_result_iter_next_number(&iter, &format);
 
164
 
 
165
        if (ok == FALSE || format != 0)
 
166
                goto error;
 
167
 
 
168
        if (g_at_result_iter_next_string(&iter, &name) == FALSE)
 
169
                goto error;
 
170
 
 
171
        /* Default to GSM */
 
172
        if (g_at_result_iter_next_number(&iter, &tech) == FALSE)
 
173
                tech = 0;
 
174
 
 
175
        strncpy(op.name, name, OFONO_MAX_OPERATOR_NAME_LENGTH);
 
176
        op.name[OFONO_MAX_OPERATOR_NAME_LENGTH] = '\0';
 
177
 
 
178
        strncpy(op.mcc, at->netreg->mcc, OFONO_MAX_MCC_LENGTH);
 
179
        op.mcc[OFONO_MAX_MCC_LENGTH] = '\0';
 
180
 
 
181
        strncpy(op.mnc, at->netreg->mnc, OFONO_MAX_MNC_LENGTH);
 
182
        op.mnc[OFONO_MAX_MNC_LENGTH] = '\0';
 
183
 
 
184
        op.status = -1;
 
185
        op.tech = tech;
 
186
 
 
187
        ofono_debug("cops_cb: %s, %s %s %d", name, at->netreg->mcc,
 
188
                        at->netreg->mnc, tech);
 
189
 
 
190
        cb(&error, &op, cbd->data);
 
191
 
 
192
out:
 
193
        g_free(cbd);
 
194
 
 
195
        return;
 
196
 
 
197
error:
 
198
        {
 
199
                DECLARE_FAILURE(e);
 
200
 
 
201
                cb(&e, NULL, cbd->data);
 
202
        }
 
203
 
 
204
        g_free(cbd);
 
205
}
 
206
 
 
207
static void cops_numeric_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
208
{
 
209
        struct cb_data *cbd = user_data;
 
210
        struct at_data *at = ofono_modem_get_userdata(cbd->modem);
 
211
        GAtResultIter iter;
 
212
        const char *str;
 
213
        int format;
 
214
 
 
215
        dump_response("cops_numeric_cb", ok, result);
 
216
 
 
217
        if (!ok)
 
218
                goto error;
 
219
 
 
220
        g_at_result_iter_init(&iter, result);
 
221
 
 
222
        if (!g_at_result_iter_next(&iter, "+COPS:"))
 
223
                goto error;
 
224
 
 
225
        g_at_result_iter_skip_next(&iter);
 
226
 
 
227
        ok = g_at_result_iter_next_number(&iter, &format);
 
228
 
 
229
        if (ok == FALSE || format != 2)
 
230
                goto error;
 
231
 
 
232
        if (g_at_result_iter_next_string(&iter, &str) == FALSE ||
 
233
                strlen(str) == 0)
 
234
                goto error;
 
235
 
 
236
        extract_mcc_mnc(str, at->netreg->mcc, at->netreg->mnc);
 
237
 
 
238
        ofono_debug("Cops numeric got mcc: %s, mnc: %s",
 
239
                        at->netreg->mcc, at->netreg->mnc);
 
240
 
 
241
        return;
 
242
 
 
243
error:
 
244
        at->netreg->mcc[0] = '\0';
 
245
        at->netreg->mnc[0] = '\0';
 
246
}
 
247
 
 
248
static void at_current_operator(struct ofono_modem *modem,
 
249
                                ofono_current_operator_cb_t cb, void *data)
 
250
{
 
251
        struct at_data *at = ofono_modem_get_userdata(modem);
 
252
        struct cb_data *cbd = cb_data_new(modem, cb, data);
 
253
        gboolean ok;
 
254
 
 
255
        if (!cbd)
 
256
                goto error;
 
257
 
 
258
        ok = g_at_chat_send(at->parser, "AT+COPS=3,2", none_prefix,
 
259
                                NULL, NULL, NULL);
 
260
 
 
261
        if (ok)
 
262
                ok = g_at_chat_send(at->parser, "AT+COPS?", cops_prefix,
 
263
                                        cops_numeric_cb, cbd, NULL);
 
264
 
 
265
        if (ok)
 
266
                ok = g_at_chat_send(at->parser, "AT+COPS=3,0", none_prefix,
 
267
                                        NULL, NULL, NULL);
 
268
 
 
269
        if (ok)
 
270
                ok = g_at_chat_send(at->parser, "AT+COPS?", cops_prefix,
 
271
                                        cops_cb, cbd, NULL);
 
272
 
 
273
        if (ok)
 
274
                return;
 
275
 
 
276
error:
 
277
        if (cbd)
 
278
                g_free(cbd);
 
279
 
 
280
        {
 
281
                DECLARE_FAILURE(error);
 
282
                cb(&error, NULL, data);
 
283
        }
 
284
}
 
285
 
 
286
static void cops_list_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
287
{
 
288
        struct cb_data *cbd = user_data;
 
289
        ofono_operator_list_cb_t cb = cbd->cb;
 
290
        struct ofono_network_operator *list;
 
291
        GAtResultIter iter;
 
292
        int num = 0;
 
293
        struct ofono_error error;
 
294
 
 
295
        dump_response("cops_list_cb", ok, result);
 
296
        decode_at_error(&error, g_at_result_final_response(result));
 
297
 
 
298
        if (!ok) {
 
299
                cb(&error, 0, NULL, cbd->data);
 
300
                return;
 
301
        }
 
302
 
 
303
        g_at_result_iter_init(&iter, result);
 
304
 
 
305
        while (g_at_result_iter_next(&iter, "+COPS:")) {
 
306
                while (g_at_result_iter_skip_next(&iter))
 
307
                        num += 1;
 
308
        }
 
309
 
 
310
        ofono_debug("Got %d elements", num);
 
311
 
 
312
        list = g_try_new0(struct ofono_network_operator, num);
 
313
 
 
314
        if (!list) {
 
315
                DECLARE_FAILURE(e);
 
316
                cb(&e, 0, NULL, cbd->data);
 
317
                return;
 
318
        }
 
319
 
 
320
        num = 0;
 
321
        g_at_result_iter_init(&iter, result);
 
322
 
 
323
        while (g_at_result_iter_next(&iter, "+COPS:")) {
 
324
                int status, tech;
 
325
                const char *l, *s, *n;
 
326
                gboolean have_long = FALSE;
 
327
 
 
328
                while (1) {
 
329
                        if (!g_at_result_iter_open_list(&iter))
 
330
                                break;
 
331
 
 
332
                        if (!g_at_result_iter_next_number(&iter, &status))
 
333
                                break;
 
334
 
 
335
                        list[num].status = status;
 
336
 
 
337
                        if (!g_at_result_iter_next_string(&iter, &l))
 
338
                                break;
 
339
 
 
340
                        if (strlen(l) > 0) {
 
341
                                have_long = TRUE;
 
342
                                strncpy(list[num].name, l,
 
343
                                        OFONO_MAX_OPERATOR_NAME_LENGTH);
 
344
                        }
 
345
 
 
346
                        if (!g_at_result_iter_next_string(&iter, &s))
 
347
                                break;
 
348
 
 
349
                        if (strlen(s) > 0 && !have_long)
 
350
                                strncpy(list[num].name, s,
 
351
                                        OFONO_MAX_OPERATOR_NAME_LENGTH);
 
352
 
 
353
                        list[num].name[OFONO_MAX_OPERATOR_NAME_LENGTH] = '\0';
 
354
 
 
355
                        if (!g_at_result_iter_next_string(&iter, &n))
 
356
                                break;
 
357
 
 
358
                        extract_mcc_mnc(n, list[num].mcc, list[num].mnc);
 
359
 
 
360
                        if (!g_at_result_iter_next_number(&iter, &tech))
 
361
                                tech = 0;
 
362
 
 
363
                        list[num].tech = tech;
 
364
 
 
365
                        if (!g_at_result_iter_close_list(&iter))
 
366
                                break;
 
367
 
 
368
                        num += 1;
 
369
                }
 
370
        }
 
371
 
 
372
        ofono_debug("Got %d operators", num);
 
373
 
 
374
{
 
375
        int i = 0;
 
376
 
 
377
        for (; i < num; i++) {
 
378
                ofono_debug("Operator: %s, %s, %s, status: %d, %d",
 
379
                                list[i].name, list[i].mcc, list[i].mnc,
 
380
                                list[i].status, list[i].tech);
 
381
        }
 
382
}
 
383
 
 
384
        cb(&error, num, list, cbd->data);
 
385
 
 
386
        g_free(list);
 
387
}
 
388
 
 
389
static void at_list_operators(struct ofono_modem *modem, ofono_operator_list_cb_t cb,
 
390
                                void *data)
 
391
{
 
392
        struct at_data *at = ofono_modem_get_userdata(modem);
 
393
        struct cb_data *cbd = cb_data_new(modem, cb, data);
 
394
 
 
395
        if (!cbd)
 
396
                goto error;
 
397
 
 
398
        if (g_at_chat_send(at->parser, "AT+COPS=?", cops_prefix,
 
399
                                cops_list_cb, cbd, g_free) > 0)
 
400
                return;
 
401
 
 
402
error:
 
403
        if (cbd)
 
404
                g_free(cbd);
 
405
 
 
406
        {
 
407
                DECLARE_FAILURE(error);
 
408
                cb(&error, 0, NULL, data);
 
409
        }
 
410
}
 
411
 
 
412
static void register_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
413
{
 
414
        struct cb_data *cbd = user_data;
 
415
        ofono_generic_cb_t cb = cbd->cb;
 
416
        struct ofono_error error;
 
417
 
 
418
        dump_response("register_cb", ok, result);
 
419
        decode_at_error(&error, g_at_result_final_response(result));
 
420
 
 
421
        cb(&error, cbd->data);
 
422
}
 
423
 
 
424
static void at_register_auto(struct ofono_modem *modem, ofono_generic_cb_t cb,
 
425
                                void *data)
 
426
{
 
427
        struct at_data *at = ofono_modem_get_userdata(modem);
 
428
        struct cb_data *cbd = cb_data_new(modem, cb, data);
 
429
 
 
430
        if (!cbd)
 
431
                goto error;
 
432
 
 
433
        if (g_at_chat_send(at->parser, "AT+COPS=0", none_prefix,
 
434
                                register_cb, cbd, g_free) > 0)
 
435
                return;
 
436
 
 
437
error:
 
438
        if (cbd)
 
439
                g_free(cbd);
 
440
 
 
441
        {
 
442
                DECLARE_FAILURE(error);
 
443
                cb(&error, data);
 
444
        }
 
445
}
 
446
 
 
447
static void at_register_manual(struct ofono_modem *modem,
 
448
                                const struct ofono_network_operator *oper,
 
449
                                ofono_generic_cb_t cb, void *data)
 
450
{
 
451
        struct at_data *at = ofono_modem_get_userdata(modem);
 
452
        struct cb_data *cbd = cb_data_new(modem, cb, data);
 
453
        char buf[128];
 
454
 
 
455
        if (!cbd)
 
456
                goto error;
 
457
 
 
458
        sprintf(buf, "AT+COPS=1,2,\"%s%s\"", oper->mcc, oper->mnc);
 
459
 
 
460
        if (g_at_chat_send(at->parser, buf, none_prefix,
 
461
                                register_cb, cbd, g_free) > 0)
 
462
                return;
 
463
 
 
464
error:
 
465
        if (cbd)
 
466
                g_free(cbd);
 
467
 
 
468
        {
 
469
                DECLARE_FAILURE(error);
 
470
                cb(&error, data);
 
471
        }
 
472
}
 
473
 
 
474
static void at_deregister(struct ofono_modem *modem, ofono_generic_cb_t cb,
 
475
                                void *data)
 
476
{
 
477
        struct at_data *at = ofono_modem_get_userdata(modem);
 
478
        struct cb_data *cbd = cb_data_new(modem, cb, data);
 
479
 
 
480
        if (!cbd)
 
481
                goto error;
 
482
 
 
483
        if (g_at_chat_send(at->parser, "AT+COPS=2", none_prefix,
 
484
                                register_cb, cbd, g_free) > 0)
 
485
                return;
 
486
 
 
487
error:
 
488
        if (cbd)
 
489
                g_free(cbd);
 
490
 
 
491
        {
 
492
                DECLARE_FAILURE(error);
 
493
                cb(&error, data);
 
494
        }
 
495
}
 
496
 
 
497
static void csq_notify(GAtResult *result, gpointer user_data)
 
498
{
 
499
        struct ofono_modem *modem = user_data;
 
500
        int strength;
 
501
        GAtResultIter iter;
 
502
 
 
503
        dump_response("csq_notify", TRUE, result);
 
504
 
 
505
        g_at_result_iter_init(&iter, result);
 
506
 
 
507
        if (!g_at_result_iter_next(&iter, "+CSQ:"))
 
508
                return;
 
509
 
 
510
        if (!g_at_result_iter_next_number(&iter, &strength))
 
511
                return;
 
512
 
 
513
        ofono_debug("csq_notify: %d", strength);
 
514
 
 
515
        if (strength == 99)
 
516
                strength = -1;
 
517
        else
 
518
                strength = strength * 100 / 31;
 
519
 
 
520
        ofono_signal_strength_notify(modem, strength);
 
521
}
 
522
 
 
523
static void csq_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
524
{
 
525
        struct cb_data *cbd = user_data;
 
526
        ofono_signal_strength_cb_t cb = cbd->cb;
 
527
        int strength;
 
528
        GAtResultIter iter;
 
529
        struct ofono_error error;
 
530
 
 
531
        dump_response("csq_cb", ok, result);
 
532
        decode_at_error(&error, g_at_result_final_response(result));
 
533
 
 
534
        if (!ok) {
 
535
                cb(&error, -1, cbd->data);
 
536
                return;
 
537
        }
 
538
 
 
539
        g_at_result_iter_init(&iter, result);
 
540
 
 
541
        if (!g_at_result_iter_next(&iter, "+CSQ:")) {
 
542
                DECLARE_FAILURE(e);
 
543
 
 
544
                cb(&e, -1, cbd->data);
 
545
                return;
 
546
        }
 
547
 
 
548
        g_at_result_iter_next_number(&iter, &strength);
 
549
 
 
550
        ofono_debug("csq_cb: %d", strength);
 
551
 
 
552
        if (strength == 99)
 
553
                strength = -1;
 
554
        else
 
555
                strength = strength * 100 / 31;
 
556
 
 
557
        cb(&error, strength, cbd->data);
 
558
}
 
559
 
 
560
static void at_signal_strength(struct ofono_modem *modem,
 
561
                                ofono_signal_strength_cb_t cb, void *data)
 
562
{
 
563
        struct at_data *at = ofono_modem_get_userdata(modem);
 
564
        struct cb_data *cbd = cb_data_new(modem, cb, data);
 
565
 
 
566
        if (!cbd)
 
567
                goto error;
 
568
 
 
569
        if (g_at_chat_send(at->parser, "AT+CSQ", csq_prefix,
 
570
                                csq_cb, cbd, g_free) > 0)
 
571
                return;
 
572
 
 
573
error:
 
574
        if (cbd)
 
575
                g_free(cbd);
 
576
 
 
577
        {
 
578
                DECLARE_FAILURE(error);
 
579
                cb(&error, -1, data);
 
580
        }
 
581
}
 
582
 
 
583
static void creg_notify(GAtResult *result, gpointer user_data)
 
584
{
 
585
        struct ofono_modem *modem = user_data;
 
586
        GAtResultIter iter;
 
587
        int status;
 
588
        int lac = -1, ci = -1, tech = -1;
 
589
        const char *str;
 
590
 
 
591
        dump_response("creg_notify", TRUE, result);
 
592
 
 
593
        g_at_result_iter_init(&iter, result);
 
594
 
 
595
        if (!g_at_result_iter_next(&iter, "+CREG:"))
 
596
                return;
 
597
 
 
598
        g_at_result_iter_next_number(&iter, &status);
 
599
 
 
600
        if (g_at_result_iter_next_string(&iter, &str) == TRUE)
 
601
                lac = strtol(str, NULL, 16);
 
602
        else
 
603
                goto out;
 
604
 
 
605
        if (g_at_result_iter_next_string(&iter, &str) == TRUE)
 
606
                ci = strtol(str, NULL, 16);
 
607
        else
 
608
                goto out;
 
609
 
 
610
        g_at_result_iter_next_number(&iter, &tech);
 
611
 
 
612
out:
 
613
        ofono_debug("creg_notify: %d, %d, %d, %d", status, lac, ci, tech);
 
614
 
 
615
        ofono_network_registration_notify(modem, status, lac, ci, tech);
 
616
}
 
617
 
 
618
static struct ofono_network_registration_ops ops = {
 
619
        .registration_status            = at_registration_status,
 
620
        .current_operator               = at_current_operator,
 
621
        .list_operators                 = at_list_operators,
 
622
        .register_auto                  = at_register_auto,
 
623
        .register_manual                = at_register_manual,
 
624
        .deregister                     = at_deregister,
 
625
        .signal_strength                = at_signal_strength,
 
626
};
 
627
 
 
628
static void at_network_registration_initialized(gboolean ok, GAtResult *result,
 
629
                                                        gpointer user_data)
 
630
{
 
631
        struct ofono_modem *modem = user_data;
 
632
        struct at_data *at = ofono_modem_get_userdata(modem);
 
633
 
 
634
        if (!ok) {
 
635
                ofono_error("Unable to initialize Network Registration");
 
636
                return;
 
637
        }
 
638
 
 
639
        g_at_chat_register(at->parser, "+CREG:",
 
640
                                creg_notify, FALSE, modem, NULL);
 
641
        g_at_chat_register(at->parser, "+CSQ:",
 
642
                                csq_notify, FALSE, modem, NULL);
 
643
 
 
644
        ofono_network_registration_register(modem, &ops);
 
645
}
 
646
 
 
647
void at_network_registration_init(struct ofono_modem *modem)
 
648
{
 
649
        struct at_data *at = ofono_modem_get_userdata(modem);
 
650
 
 
651
        at->netreg = g_try_new0(struct netreg_data, 1);
 
652
 
 
653
        if (!at->netreg)
 
654
                return;
 
655
 
 
656
        g_at_chat_send(at->parser, "AT+CREG=2", NULL,
 
657
                                at_network_registration_initialized,
 
658
                                modem, NULL);
 
659
}
 
660
 
 
661
void at_network_registration_exit(struct ofono_modem *modem)
 
662
{
 
663
        struct at_data *at = ofono_modem_get_userdata(modem);
 
664
 
 
665
        if (!at->netreg)
 
666
                return;
 
667
 
 
668
        g_free(at->netreg);
 
669
        at->netreg = NULL;
 
670
 
 
671
        ofono_network_registration_unregister(modem);
 
672
}