3
* oFono - Open Source Telephony
5
* Copyright (C) 2008-2009 Intel Corporation. All rights reserved.
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.
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.
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
33
#include <ofono/log.h>
34
#include <ofono/modem.h>
38
#include "gatresult.h"
42
static const char *none_prefix[] = { NULL };
43
static const char *ccfc_prefix[] = { "+CCFC:", NULL };
45
static void ccfc_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
47
struct cb_data *cbd = user_data;
48
ofono_call_forwarding_query_cb_t cb = cbd->cb;
49
struct ofono_error error;
52
struct ofono_cf_condition *list = NULL;
56
dump_response("ccfc_query_cb", ok, result);
57
decode_at_error(&error, g_at_result_final_response(result));
62
g_at_result_iter_init(&iter, result);
64
while (g_at_result_iter_next(&iter, "+CCFC:"))
67
/* Specification is really unclear about this
68
* generate status=0 for all classes just in case
71
list = g_new0(struct ofono_cf_condition, 1);
75
list->cls = GPOINTER_TO_INT(cbd->user);
80
list = g_new(struct ofono_cf_condition, num);
82
g_at_result_iter_init(&iter, result);
84
maxlen = OFONO_MAX_PHONE_NUMBER_LENGTH;
86
for (num = 0; g_at_result_iter_next(&iter, "+CCFC:"); num++) {
89
g_at_result_iter_next_number(&iter, &(list[num].status));
90
g_at_result_iter_next_number(&iter, &(list[num].cls));
92
list[num].phone_number.number[0] = '\0';
93
list[num].phone_number.type = 129;
96
if (!g_at_result_iter_next_string(&iter, &str))
99
strncpy(list[num].phone_number.number, str, maxlen);
100
list[num].phone_number.number[maxlen] = '\0';
102
g_at_result_iter_next_number(&iter,
103
&(list[num].phone_number.type));
105
if (!g_at_result_iter_skip_next(&iter))
108
if (!g_at_result_iter_skip_next(&iter))
111
g_at_result_iter_next_number(&iter, &(list[num].time));
114
for (i = 0; i < num; i++)
115
ofono_debug("ccfc_cb: %d, %d, %s(%d) - %d sec",
116
list[i].status, list[i].cls,
117
list[i].phone_number.number,
118
list[i].phone_number.type, list[i].time);
121
cb(&error, num, list, cbd->data);
125
static void at_ccfc_query(struct ofono_modem *modem, int type, int cls,
126
ofono_call_forwarding_query_cb_t cb, void *data)
128
struct at_data *at = ofono_modem_get_userdata(modem);
129
struct cb_data *cbd = cb_data_new(modem, cb, data);
135
cbd->user = GINT_TO_POINTER(cls);
138
sprintf(buf, "AT+CCFC=%d,2", type);
140
sprintf(buf, "AT+CCFC=%d,2,,,%d", type, cls);
142
if (g_at_chat_send(at->parser, buf, ccfc_prefix,
143
ccfc_query_cb, cbd, g_free) > 0)
151
DECLARE_FAILURE(error);
152
cb(&error, 0, NULL, data);
156
static void ccfc_set_cb(gboolean ok, GAtResult *result, gpointer user_data)
158
struct cb_data *cbd = user_data;
159
ofono_generic_cb_t cb = cbd->cb;
160
struct ofono_error error;
162
dump_response("ccfc_set_cb", ok, result);
163
decode_at_error(&error, g_at_result_final_response(result));
165
cb(&error, cbd->data);
168
static void at_ccfc_set(struct ofono_modem *modem, const char *buf,
169
ofono_generic_cb_t cb, void *data)
171
struct at_data *at = ofono_modem_get_userdata(modem);
172
struct cb_data *cbd = cb_data_new(modem, cb, data);
177
if (g_at_chat_send(at->parser, buf, none_prefix,
178
ccfc_set_cb, cbd, g_free) > 0)
186
DECLARE_FAILURE(error);
191
static void at_ccfc_erasure(struct ofono_modem *modem, int type, int cls,
192
ofono_generic_cb_t cb, void *data)
197
len = sprintf(buf, "AT+CCFC=%d,4", type);
200
sprintf(buf + len, ",,,%d", cls);
202
at_ccfc_set(modem, buf, cb, data);
205
static void at_ccfc_deactivation(struct ofono_modem *modem, int type, int cls,
206
ofono_generic_cb_t cb, void *data)
211
len = sprintf(buf, "AT+CCFC=%d,0", type);
214
sprintf(buf + len, ",,,%d", cls);
216
at_ccfc_set(modem, buf, cb, data);
219
static void at_ccfc_activation(struct ofono_modem *modem, int type, int cls,
220
ofono_generic_cb_t cb, void *data)
225
len = sprintf(buf, "AT+CCFC=%d,1", type);
228
sprintf(buf + len, ",,,%d", cls);
230
at_ccfc_set(modem, buf, cb, data);
233
static void at_ccfc_registration(struct ofono_modem *modem, int type, int cls,
234
const struct ofono_phone_number *ph,
235
int time, ofono_generic_cb_t cb,
241
offset = sprintf(buf, "AT+CCFC=%d,3,\"%s\",%d,%d", type,
242
ph->number, ph->type, cls);
244
if (type == 2 || type == 4 || type == 5)
245
sprintf(buf+offset, ",,,%d", time);
247
at_ccfc_set(modem, buf, cb, data);
250
static struct ofono_call_forwarding_ops ops = {
251
.registration = at_ccfc_registration,
252
.activation = at_ccfc_activation,
253
.query = at_ccfc_query,
254
.deactivation = at_ccfc_deactivation,
255
.erasure = at_ccfc_erasure
258
void at_call_forwarding_init(struct ofono_modem *modem)
260
ofono_call_forwarding_register(modem, &ops);
263
void at_call_forwarding_exit(struct ofono_modem *modem)
265
ofono_call_forwarding_unregister(modem);