3 * oFono - Open Source Telephony
5 * Copyright (C) 2011-2012 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
28 #include <ofono/log.h>
29 #include <ofono/modem.h>
30 #include <ofono/gprs-context.h>
37 struct gprs_context_data {
38 struct qmi_service *wds;
39 unsigned int active_context;
43 static void pkt_status_notify(struct qmi_result *result, void *user_data)
45 struct ofono_gprs_context *gc = user_data;
46 struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
47 const struct qmi_wds_notify_conn_status *status;
53 status = qmi_result_get(result, QMI_WDS_NOTIFY_CONN_STATUS, &len);
57 DBG("conn status %d", status->status);
59 if (qmi_result_get_uint8(result, QMI_WDS_NOTIFY_IP_FAMILY, &ip_family))
60 DBG("ip family %d", ip_family);
62 switch (status->status) {
63 case QMI_WDS_CONN_STATUS_DISCONNECTED:
64 ofono_gprs_context_deactivated(gc, data->active_context);
65 data->active_context = 0;
70 static void get_settings_cb(struct qmi_result *result, void *user_data)
72 struct cb_data *cbd = user_data;
73 ofono_gprs_context_cb_t cb = cbd->cb;
74 struct ofono_gprs_context *gc = cbd->user;
75 struct ofono_modem *modem;
76 const char *interface;
77 uint8_t pdp_type, ip_family;
81 if (qmi_result_set_error(result, NULL))
84 if (qmi_result_get_uint8(result, QMI_WDS_RESULT_PDP_TYPE, &pdp_type))
85 DBG("PDP type %d", pdp_type);
87 if (qmi_result_get_uint8(result, QMI_WDS_RESULT_IP_FAMILY, &ip_family))
88 DBG("IP family %d", ip_family);
91 modem = ofono_gprs_context_get_modem(gc);
92 interface = ofono_modem_get_string(modem, "NetworkInterface");
94 ofono_gprs_context_set_interface(gc, interface);
96 CALLBACK_WITH_SUCCESS(cb, cbd->data);
101 static void start_net_cb(struct qmi_result *result, void *user_data)
103 struct cb_data *cbd = user_data;
104 ofono_gprs_context_cb_t cb = cbd->cb;
105 struct ofono_gprs_context *gc = cbd->user;
106 struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
107 struct ofono_modem *modem;
108 const char *interface;
113 if (qmi_result_set_error(result, NULL))
116 if (!qmi_result_get_uint32(result, QMI_WDS_RESULT_PKT_HANDLE, &handle))
119 DBG("packet handle %d", handle);
121 data->pkt_handle = handle;
123 if (qmi_service_send(data->wds, QMI_WDS_GET_SETTINGS, NULL,
124 get_settings_cb, cbd, NULL) > 0)
127 modem = ofono_gprs_context_get_modem(gc);
128 interface = ofono_modem_get_string(modem, "NetworkInterface");
130 ofono_gprs_context_set_interface(gc, interface);
132 CALLBACK_WITH_SUCCESS(cb, cbd->data);
139 data->active_context = 0;
141 CALLBACK_WITH_FAILURE(cb, cbd->data);
146 static void qmi_activate_primary(struct ofono_gprs_context *gc,
147 const struct ofono_gprs_primary_context *ctx,
148 ofono_gprs_context_cb_t cb, void *user_data)
150 struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
151 struct cb_data *cbd = cb_data_new(cb, user_data);
152 struct qmi_param *param;
155 DBG("cid %u", ctx->cid);
159 data->active_context = ctx->cid;
161 switch (ctx->proto) {
162 case OFONO_GPRS_PROTO_IP:
165 case OFONO_GPRS_PROTO_IPV6:
172 param = qmi_param_new();
176 qmi_param_append(param, QMI_WDS_PARAM_APN,
177 strlen(ctx->apn), ctx->apn);
179 qmi_param_append_uint8(param, QMI_WDS_PARAM_IP_FAMILY, ip_family);
181 if (qmi_service_send(data->wds, QMI_WDS_START_NET, param,
182 start_net_cb, cbd, NULL) > 0)
185 qmi_param_free(param);
188 data->active_context = 0;
190 CALLBACK_WITH_FAILURE(cb, cbd->data);
195 static void stop_net_cb(struct qmi_result *result, void *user_data)
197 struct cb_data *cbd = user_data;
198 ofono_gprs_context_cb_t cb = cbd->cb;
199 struct ofono_gprs_context *gc = cbd->user;
200 struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
204 if (qmi_result_set_error(result, NULL)) {
205 CALLBACK_WITH_FAILURE(cb, cbd->data);
209 data->active_context = 0;
211 data->pkt_handle = 0;
213 CALLBACK_WITH_SUCCESS(cb, cbd->data);
218 static void qmi_deactivate_primary(struct ofono_gprs_context *gc,
220 ofono_gprs_context_cb_t cb, void *user_data)
222 struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
223 struct cb_data *cbd = cb_data_new(cb, user_data);
224 struct qmi_param *param;
230 param = qmi_param_new_uint32(QMI_WDS_PARAM_PKT_HANDLE,
235 if (qmi_service_send(data->wds, QMI_WDS_STOP_NET, param,
236 stop_net_cb, cbd, NULL) > 0)
239 qmi_param_free(param);
242 CALLBACK_WITH_FAILURE(cb, cbd->data);
247 static void create_wds_cb(struct qmi_service *service, void *user_data)
249 struct ofono_gprs_context *gc = user_data;
250 struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
255 ofono_error("Failed to request WDS service");
256 ofono_gprs_context_remove(gc);
260 data->wds = qmi_service_ref(service);
262 qmi_service_register(data->wds, QMI_WDS_PKT_STATUS_IND,
263 pkt_status_notify, gc, NULL);
266 static int qmi_gprs_context_probe(struct ofono_gprs_context *gc,
267 unsigned int vendor, void *user_data)
269 struct qmi_device *device = user_data;
270 struct gprs_context_data *data;
274 data = g_new0(struct gprs_context_data, 1);
276 ofono_gprs_context_set_data(gc, data);
278 qmi_service_create(device, QMI_SERVICE_WDS, create_wds_cb, gc, NULL);
283 static void qmi_gprs_context_remove(struct ofono_gprs_context *gc)
285 struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
289 ofono_gprs_context_set_data(gc, NULL);
291 qmi_service_unregister_all(data->wds);
293 qmi_service_unref(data->wds);
298 static struct ofono_gprs_context_driver driver = {
300 .probe = qmi_gprs_context_probe,
301 .remove = qmi_gprs_context_remove,
302 .activate_primary = qmi_activate_primary,
303 .deactivate_primary = qmi_deactivate_primary,
306 void qmi_gprs_context_init(void)
308 ofono_gprs_context_driver_register(&driver);
311 void qmi_gprs_context_exit(void)
313 ofono_gprs_context_driver_unregister(&driver);