3
* oFono - Open Source Telephony - RIL Modem Support
5
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
6
* Copyright (C) 2010 ST-Ericsson AB.
7
* Copyright (C) 2012 Canonical Ltd.
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35
#include <ofono/log.h>
36
#include <ofono/modem.h>
37
#include <ofono/netreg.h>
45
char mcc[OFONO_MAX_MCC_LENGTH + 1];
46
char mnc[OFONO_MAX_MNC_LENGTH + 1];
47
int signal_index; /* If strength is reported via CIND */
48
int signal_min; /* min strength reported via CIND */
49
int signal_max; /* max strength reported via CIND */
50
int signal_invalid; /* invalid strength reported via CIND */
52
struct ofono_network_time time;
57
/* 27.007 Section 7.3 <stat> */
58
enum operator_status {
59
OPERATOR_STATUS_UNKNOWN = 0,
60
OPERATOR_STATUS_AVAILABLE = 1,
61
OPERATOR_STATUS_CURRENT = 2,
62
OPERATOR_STATUS_FORBIDDEN = 3,
65
static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
67
/* Three digit country code */
68
strncpy(mcc, str, OFONO_MAX_MCC_LENGTH);
69
mcc[OFONO_MAX_MCC_LENGTH] = '\0';
71
/* Usually a 2 but sometimes 3 digit network code */
72
strncpy(mnc, str + OFONO_MAX_MCC_LENGTH, OFONO_MAX_MNC_LENGTH);
73
mnc[OFONO_MAX_MNC_LENGTH] = '\0';
77
* TODO: The functions in this file are stubbed out, and
78
* will need to be re-worked to talk to the /gril layer
79
* in order to get real values from RILD.
82
static void ril_creg_cb(struct ril_msg *message, gpointer user_data)
84
struct cb_data *cbd = user_data;
85
ofono_netreg_status_cb_t cb = cbd->cb;
86
struct netreg_data *nd = cbd->user;
87
struct ofono_error error;
88
int status, lac, ci, tech;
92
if (message->error != RIL_E_SUCCESS) {
93
decode_ril_error(&error, "FAIL");
94
ofono_error("Failed to pull registration state");
95
cb(&error, -1, -1, -1, -1, cbd->data);
99
decode_ril_error(&error, "OK");
101
if (ril_util_parse_reg(nd->ril, message, &status,
102
&lac, &ci, &tech, NULL) == FALSE) {
103
CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
108
cb(&error, status, lac, ci, tech, cbd->data);
111
static void ril_creg_notify(struct ofono_error *error, int status, int lac,
112
int ci, int tech, gpointer user_data)
114
struct ofono_netreg *netreg = user_data;
116
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
117
DBG("Error during status notification");
121
ofono_netreg_status_notify(netreg, status, lac, ci, tech);
124
static void ril_network_state_change(struct ril_msg *message, gpointer user_data)
126
struct ofono_netreg *netreg = user_data;
127
struct netreg_data *nd = ofono_netreg_get_data(netreg);
128
struct cb_data *cbd = cb_data_new(ril_creg_notify, netreg);
129
int request = RIL_REQUEST_VOICE_REGISTRATION_STATE;
134
if (message->req != RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED)
137
g_ril_print_unsol_no_args(nd->ril, message);
139
ret = g_ril_send(nd->ril, request, NULL,
140
0, ril_creg_cb, cbd, g_free);
142
/* For operator update ofono will use the current_operator cb
143
* so we don't need to probe ril here */
145
g_ril_print_request_no_args(nd->ril, ret, request);
151
ofono_error("Unable to request network state changed");
155
static void ril_registration_status(struct ofono_netreg *netreg,
156
ofono_netreg_status_cb_t cb,
159
struct netreg_data *nd = ofono_netreg_get_data(netreg);
160
struct cb_data *cbd = cb_data_new(cb, data);
161
int request = RIL_REQUEST_VOICE_REGISTRATION_STATE;
166
ret = g_ril_send(nd->ril, request, NULL,
167
0, ril_creg_cb, cbd, g_free);
169
g_ril_print_request_no_args(nd->ril, ret, request);
173
CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
177
static void ril_cops_cb(struct ril_msg *message, gpointer user_data)
179
struct cb_data *cbd = user_data;
180
ofono_netreg_operator_cb_t cb = cbd->cb;
181
struct netreg_data *nd = cbd->user;
182
struct ofono_error error;
184
struct ofono_network_operator op;
185
gchar *lalpha, *salpha, *numeric;
187
if (message->error == RIL_E_SUCCESS) {
188
decode_ril_error(&error, "OK");
190
ofono_error("Failed to retrive the current operator");
194
ril_util_init_parcel(message, &rilp);
196
/* Size of char ** */
197
if (parcel_r_int32(&rilp) == 0)
200
lalpha = parcel_r_string(&rilp);
201
salpha = parcel_r_string(&rilp);
202
numeric = parcel_r_string(&rilp);
204
/* Try to use long by default */
206
strncpy(op.name, lalpha, OFONO_MAX_OPERATOR_NAME_LENGTH);
208
strncpy(op.name, salpha, OFONO_MAX_OPERATOR_NAME_LENGTH);
210
extract_mcc_mnc(numeric, op.mcc, op.mnc);
213
op.status = OPERATOR_STATUS_CURRENT;
216
g_ril_append_print_buf(nd->ril,
217
"(lalpha=%s, salpha=%s, numeric=%s, %s, mcc=%s, mnc=%s, %s)",
218
lalpha, salpha, numeric,
219
op.name, op.mcc, op.mnc,
220
registration_tech_to_string(op.tech));
221
g_ril_print_response(nd->ril, message);
227
cb(&error, &op, cbd->data);
232
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
235
static void ril_current_operator(struct ofono_netreg *netreg,
236
ofono_netreg_operator_cb_t cb, void *data)
238
struct netreg_data *nd = ofono_netreg_get_data(netreg);
239
struct cb_data *cbd = cb_data_new(cb, data);
240
int request = RIL_REQUEST_OPERATOR;
245
ret = g_ril_send(nd->ril, request, NULL,
246
0, ril_cops_cb, cbd, g_free);
248
g_ril_print_request_no_args(nd->ril, ret, request);
252
CALLBACK_WITH_FAILURE(cb, NULL, data);
256
static void ril_cops_list_cb(struct ril_msg *message, gpointer user_data)
258
struct cb_data *cbd = user_data;
259
ofono_netreg_operator_list_cb_t cb = cbd->cb;
260
struct netreg_data *nd = cbd->user;
261
struct ofono_network_operator *list;
262
struct ofono_error error;
265
gchar *lalpha, *salpha, *numeric, *status;
267
if (message->error == RIL_E_SUCCESS) {
268
decode_ril_error(&error, "OK");
270
ofono_error("Failed to retrive the list of operators");
274
ril_util_init_parcel(message, &rilp);
276
g_ril_append_print_buf(nd->ril, "{");
278
/* Number of operators at the list (4 strings for every operator) */
279
noperators = parcel_r_int32(&rilp) / 4;
280
DBG("noperators = %d", noperators);
282
list = g_try_new0(struct ofono_network_operator, noperators);
286
for (i = 0; i < noperators; i++) {
287
lalpha = parcel_r_string(&rilp);
288
salpha = parcel_r_string(&rilp);
289
numeric = parcel_r_string(&rilp);
290
status = parcel_r_string(&rilp);
292
/* Try to use long by default */
294
strncpy(list[i].name, lalpha,
295
OFONO_MAX_OPERATOR_NAME_LENGTH);
297
strncpy(list[i].name, salpha,
298
OFONO_MAX_OPERATOR_NAME_LENGTH);
301
extract_mcc_mnc(numeric, list[i].mcc, list[i].mnc);
303
/* FIXME: need to fix this for CDMA */
304
/* Use GSM as default, as RIL doesn't pass that info to us */
305
list[i].tech = ACCESS_TECHNOLOGY_GSM;
307
/* Set the proper status */
308
if (!strcmp(status, "unknown"))
309
list[i].status = OPERATOR_STATUS_UNKNOWN;
310
else if (!strcmp(status, "available"))
311
list[i].status = OPERATOR_STATUS_AVAILABLE;
312
else if (!strcmp(status, "current"))
313
list[i].status = OPERATOR_STATUS_CURRENT;
314
else if (!strcmp(status, "forbidden"))
315
list[i].status = OPERATOR_STATUS_FORBIDDEN;
317
g_ril_append_print_buf(nd->ril,
318
"%s [operator=%s, %s, %s, status: %s]",
320
list[i].name, list[i].mcc,
321
list[i].mnc, status);
329
g_ril_append_print_buf(nd->ril, "%s}", print_buf);
330
g_ril_print_response(nd->ril, message);
332
cb(&error, noperators, list, cbd->data);
337
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
340
static void ril_list_operators(struct ofono_netreg *netreg,
341
ofono_netreg_operator_list_cb_t cb, void *data)
343
struct netreg_data *nd = ofono_netreg_get_data(netreg);
344
struct cb_data *cbd = cb_data_new(cb, data);
345
int request = RIL_REQUEST_QUERY_AVAILABLE_NETWORKS;
350
ret = g_ril_send(nd->ril, request, NULL,
351
0, ril_cops_list_cb, cbd, g_free);
353
g_ril_print_request_no_args(nd->ril, ret, request);
357
CALLBACK_WITH_FAILURE(cb, 0, NULL, data);
361
static void ril_register_cb(struct ril_msg *message, gpointer user_data)
363
struct cb_data *cbd = user_data;
364
ofono_netreg_register_cb_t cb = cbd->cb;
365
struct netreg_data *nd = cbd->user;
366
struct ofono_error error;
368
if (message->error == RIL_E_SUCCESS) {
369
decode_ril_error(&error, "OK");
371
g_ril_print_response_no_args(nd->ril, message);
374
decode_ril_error(&error, "FAIL");
377
cb(&error, cbd->data);
380
static void ril_register_auto(struct ofono_netreg *netreg,
381
ofono_netreg_register_cb_t cb, void *data)
383
struct netreg_data *nd = ofono_netreg_get_data(netreg);
384
struct cb_data *cbd = cb_data_new(cb, data);
385
int request = RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC;
389
ret = g_ril_send(nd->ril, request,
390
NULL, 0, ril_register_cb, cbd, g_free);
392
g_ril_print_request_no_args(nd->ril, ret, request);
396
CALLBACK_WITH_FAILURE(cb, data);
400
static void ril_register_manual(struct ofono_netreg *netreg,
401
const char *mcc, const char *mnc,
402
ofono_netreg_register_cb_t cb, void *data)
404
struct netreg_data *nd = ofono_netreg_get_data(netreg);
405
struct cb_data *cbd = cb_data_new(cb, data);
406
char buf[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];
408
int request = RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL;
413
/* RIL expects a char * specifying MCCMNC of network to select */
414
snprintf(buf, sizeof(buf), "%s%s", mcc, mnc);
415
parcel_w_string(&rilp, buf);
417
ret = g_ril_send(nd->ril, request,
418
rilp.data, rilp.size, ril_register_cb,
422
g_ril_append_print_buf(nd->ril, "(%s)", buf);
423
g_ril_print_request(nd->ril, ret, request);
425
/* In case of error free cbd and return the cb with failure */
428
CALLBACK_WITH_FAILURE(cb, data);
432
static void ril_strength_notify(struct ril_msg *message, gpointer user_data)
434
struct ofono_netreg *netreg = user_data;
435
struct netreg_data *nd = ofono_netreg_get_data(netreg);
438
g_assert(message->req == RIL_UNSOL_SIGNAL_STRENGTH);
440
strength = ril_util_get_signal(nd->ril, message);
441
ofono_netreg_strength_notify(netreg, strength);
446
static void ril_strength_cb(struct ril_msg *message, gpointer user_data)
448
struct cb_data *cbd = user_data;
449
ofono_netreg_strength_cb_t cb = cbd->cb;
450
struct netreg_data *nd = cbd->user;
451
struct ofono_error error;
454
if (message->error == RIL_E_SUCCESS) {
455
decode_ril_error(&error, "OK");
457
ofono_error("Failed to retrive the signal strength");
461
strength = ril_util_get_signal(nd->ril, message);
462
cb(&error, strength, cbd->data);
467
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
470
static void ril_signal_strength(struct ofono_netreg *netreg,
471
ofono_netreg_strength_cb_t cb, void *data)
473
struct netreg_data *nd = ofono_netreg_get_data(netreg);
474
struct cb_data *cbd = cb_data_new(cb, data);
475
int request = RIL_REQUEST_SIGNAL_STRENGTH;
480
ret = g_ril_send(nd->ril, request,
481
NULL, 0, ril_strength_cb, cbd, g_free);
483
g_ril_print_request_no_args(nd->ril, ret, request);
486
ofono_error("Send RIL_REQUEST_SIGNAL_STRENGTH failed.");
489
CALLBACK_WITH_FAILURE(cb, -1, data);
493
static void ril_nitz_notify(struct ril_msg *message, gpointer user_data)
495
struct ofono_netreg *netreg = user_data;
496
struct netreg_data *nd = ofono_netreg_get_data(netreg);
498
int year, mon, mday, hour, min, sec, dst, tzi;
502
if (message->req != RIL_UNSOL_NITZ_TIME_RECEIVED)
506
ril_util_init_parcel(message, &rilp);
508
nitz = parcel_r_string(&rilp);
510
g_ril_append_print_buf(nd->ril, "(%s)", nitz);
511
g_ril_print_unsol(nd->ril, message);
513
sscanf(nitz, "%u/%u/%u,%u:%u:%u%c%u,%u", &year, &mon, &mday,
514
&hour, &min, &sec, &tzs, &tzi, &dst);
515
sprintf(tz, "%c%d", tzs, tzi);
517
nd->time.utcoff = atoi(tz) * 15 * 60;
521
nd->time.hour = hour;
522
nd->time.mday = mday;
524
nd->time.year = 2000 + year;
526
ofono_netreg_time_notify(netreg, &nd->time);
533
ofono_error("Unable to notify ofono about nitz");
536
static gboolean ril_delayed_register(gpointer user_data)
538
struct ofono_netreg *netreg = user_data;
539
struct netreg_data *nd = ofono_netreg_get_data(netreg);
540
ofono_netreg_register(netreg);
542
/* Register for network state changes */
543
g_ril_register(nd->ril, RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
544
ril_network_state_change, netreg);
546
/* Register for network time update reports */
547
g_ril_register(nd->ril, RIL_UNSOL_NITZ_TIME_RECEIVED,
548
ril_nitz_notify, netreg);
550
/* Register for signal strength changes */
551
g_ril_register(nd->ril, RIL_UNSOL_SIGNAL_STRENGTH,
552
ril_strength_notify, netreg);
554
/* This makes the timeout a single-shot */
558
static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
562
struct netreg_data *nd;
564
nd = g_new0(struct netreg_data, 1);
566
nd->ril = g_ril_clone(ril);
577
ofono_netreg_set_data(netreg, nd);
580
* TODO: analyze if capability check is needed
581
* and/or timer should be adjusted.
583
* ofono_netreg_register() needs to be called after
584
* the driver has been set in ofono_netreg_create(),
585
* which calls this function. Most other drivers make
586
* some kind of capabilities query to the modem, and then
587
* call register in the callback; we use a timer instead.
589
g_timeout_add_seconds(1, ril_delayed_register, netreg);
594
static void ril_netreg_remove(struct ofono_netreg *netreg)
596
struct netreg_data *nd = ofono_netreg_get_data(netreg);
598
if (nd->nitz_timeout)
599
g_source_remove(nd->nitz_timeout);
601
ofono_netreg_set_data(netreg, NULL);
603
g_ril_unref(nd->ril);
607
static struct ofono_netreg_driver driver = {
609
.probe = ril_netreg_probe,
610
.remove = ril_netreg_remove,
611
.registration_status = ril_registration_status,
612
.current_operator = ril_current_operator,
613
.list_operators = ril_list_operators,
614
.register_auto = ril_register_auto,
615
.register_manual = ril_register_manual,
616
.strength = ril_signal_strength,
619
void ril_netreg_init(void)
621
ofono_netreg_driver_register(&driver);
624
void ril_netreg_exit(void)
626
ofono_netreg_driver_unregister(&driver);