3
* oFono - Open Source Telephony
5
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
6
* Copyright (C) 2013 Jolla Ltd
7
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
8
* Copyright (C) 2014 Canonical Ltd.
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.
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.
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
36
#include <ofono/log.h>
37
#include <ofono/modem.h>
38
#include <ofono/call-forwarding.h>
41
#include "grilrequest.h"
42
#include "grilreply.h"
43
#include "grilunsol.h"
52
CF_ACTION_INTERROGATE,
53
CF_ACTION_REGISTRATION,
59
enum cf_action last_action;
63
static const char *cf_action_to_string(enum cf_action action)
66
case CF_ACTION_DISABLE:
68
case CF_ACTION_ENABLE:
70
case CF_ACTION_INTERROGATE:
72
case CF_ACTION_REGISTRATION:
73
return "REGISTRATION";
74
case CF_ACTION_ERASURE:
81
static void ril_query_call_fwd_cb(struct ril_msg *message, gpointer user_data)
83
struct cb_data *cbd = user_data;
84
struct forw_data *fd = ofono_call_forwarding_get_data(cbd->user);
85
ofono_call_forwarding_query_cb_t cb = cbd->cb;
86
struct ofono_call_forwarding_condition *list;
87
unsigned int list_size;
89
if (message->error != RIL_E_SUCCESS) {
90
ofono_error("%s: rild error: %s", __func__,
91
ril_error_to_string(message->error));
95
list = g_ril_reply_parse_query_call_fwd(fd->ril, message, &list_size);
99
* Specification is really unclear about this
100
* generate status=0 for all classes just in case
102
if (list_size == 0) {
103
list = g_new0(struct ofono_call_forwarding_condition, 1);
107
list->cls = fd->last_cls;
108
} else if (list == NULL) {
112
CALLBACK_WITH_SUCCESS(cb, (int) list_size, list, cbd->data);
117
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
120
static void ril_set_forward_cb(struct ril_msg *message, gpointer user_data)
122
struct cb_data *cbd = user_data;
123
ofono_call_forwarding_set_cb_t cb = cbd->cb;
124
struct forw_data *fd = ofono_call_forwarding_get_data(cbd->user);
126
if (message->error == RIL_E_SUCCESS) {
127
g_ril_print_response_no_args(fd->ril, message);
128
CALLBACK_WITH_SUCCESS(cb, cbd->data);
130
ofono_error("%s: CF %s failed; rild error: %s", __func__,
131
cf_action_to_string(fd->last_action),
132
ril_error_to_string(message->error));
133
CALLBACK_WITH_FAILURE(cb, cbd->data);
137
static int ril_send_forward_cmd(int type, int cls,
138
const struct ofono_phone_number *number,
141
enum cf_action action)
143
struct ofono_call_forwarding *cf = cbd->user;
144
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
146
struct req_call_fwd fwd_req;
147
int ret = 0, request;
148
GRilResponseFunc response_func;
150
if (action == CF_ACTION_INTERROGATE) {
151
request = RIL_REQUEST_QUERY_CALL_FORWARD_STATUS;
152
response_func = ril_query_call_fwd_cb;
154
request = RIL_REQUEST_SET_CALL_FORWARD;
155
response_func = ril_set_forward_cb;
158
DBG("%s - %s", ril_request_id_to_string(request),
159
cf_action_to_string(action));
162
* Modem seems to respond with error to all queries
163
* or settings made with bearer class
164
* BEARER_CLASS_DEFAULT. Design decision: If given
165
* class is BEARER_CLASS_DEFAULT let's map it to
166
* SERVICE_CLASS_NONE as with it e.g. ./send-ussd '*21*<phone_number>#'
167
* returns cls:53 i.e. 1+4+16+32 as service class.
169
if (cls == BEARER_CLASS_DEFAULT)
170
cls = SERVICE_CLASS_NONE;
172
fd->last_action = action;
175
fwd_req.action = (int) action;
178
fwd_req.number = number;
181
* time has no real meaing for action commands other
182
* then registration, so if not needed, set arbitrary
183
* 60s time so rild doesn't return an error.
190
g_ril_request_call_fwd(fd->ril, &fwd_req, &rilp);
192
ret = g_ril_send(fd->ril, request, &rilp, response_func, cbd, g_free);
194
ofono_error("%s: CF action %s failed", __func__,
195
cf_action_to_string(action));
199
static void ril_activate(struct ofono_call_forwarding *cf,
201
ofono_call_forwarding_set_cb_t cb, void *data)
203
struct cb_data *cbd = cb_data_new(cb, data, cf);
205
if (ril_send_forward_cmd(type, cls, NULL, -1, cbd,
206
CF_ACTION_ENABLE) == 0) {
207
CALLBACK_WITH_FAILURE(cb, cbd->data);
212
static void ril_erasure(struct ofono_call_forwarding *cf,
214
ofono_call_forwarding_set_cb_t cb, void *data)
216
struct cb_data *cbd = cb_data_new(cb, data, cf);
218
if (ril_send_forward_cmd(type, cls, NULL, -1, cbd,
219
CF_ACTION_ERASURE) == 0) {
220
CALLBACK_WITH_FAILURE(cb, cbd->data);
225
static void ril_deactivate(struct ofono_call_forwarding *cf,
227
ofono_call_forwarding_set_cb_t cb, void *data)
229
struct cb_data *cbd = cb_data_new(cb, data, cf);
231
if (ril_send_forward_cmd(type, cls, NULL, -1, cbd,
232
CF_ACTION_DISABLE) == 0) {
233
CALLBACK_WITH_FAILURE(cb, cbd->data);
238
static void ril_registration(struct ofono_call_forwarding *cf, int type,
240
const struct ofono_phone_number *number,
241
int time, ofono_call_forwarding_set_cb_t cb,
244
struct cb_data *cbd = cb_data_new(cb, data, cf);
246
if (ril_send_forward_cmd(type, cls, number, time, cbd,
247
CF_ACTION_REGISTRATION) == 0) {
248
CALLBACK_WITH_FAILURE(cb, cbd->data);
253
static void ril_query(struct ofono_call_forwarding *cf, int type, int cls,
254
ofono_call_forwarding_query_cb_t cb,
257
struct cb_data *cbd = cb_data_new(cb, data, cf);
259
if (ril_send_forward_cmd(type, cls, NULL, -1, cbd,
260
CF_ACTION_INTERROGATE) == 0) {
261
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
266
static gboolean ril_delayed_register(gpointer user_data)
268
struct ofono_call_forwarding *cf = user_data;
270
ofono_call_forwarding_register(cf);
274
static int ril_call_forwarding_probe(struct ofono_call_forwarding *cf,
275
unsigned int vendor, void *user)
278
struct forw_data *fd;
280
fd = g_try_new0(struct forw_data, 1);
284
fd->ril = g_ril_clone(ril);
285
ofono_call_forwarding_set_data(cf, fd);
288
* ofono_call_forwarding_register() needs to be called after
289
* the driver has been set in ofono_call_forwarding_create(),
290
* which calls this function. Most other drivers make
291
* some kind of capabilities query to the modem, and then
292
* call register in the callback; we use an idle event instead.
294
g_idle_add(ril_delayed_register, cf);
299
static void ril_call_forwarding_remove(struct ofono_call_forwarding *cf)
301
struct forw_data *data = ofono_call_forwarding_get_data(cf);
302
ofono_call_forwarding_set_data(cf, NULL);
304
g_ril_unref(data->ril);
308
static struct ofono_call_forwarding_driver driver = {
310
.probe = ril_call_forwarding_probe,
311
.remove = ril_call_forwarding_remove,
312
.erasure = ril_erasure,
313
.deactivation = ril_deactivate,
315
.registration = ril_registration,
316
.activation = ril_activate
319
void ril_call_forwarding_init(void)
321
ofono_call_forwarding_driver_register(&driver);
324
void ril_call_forwarding_exit(void)
326
ofono_call_forwarding_driver_unregister(&driver);