5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
6 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #define CONNMAN_API_SUBJECT_TO_CHANGE
34 #include <connman/plugin.h>
35 #include <connman/device.h>
36 #include <connman/network.h>
37 #include <connman/dbus.h>
38 #include <connman/log.h>
40 #define OFONO_SERVICE "org.ofono"
42 #define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager"
43 #define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem"
44 #define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
45 #define OFONO_NETREG_INTERFACE OFONO_SERVICE ".NetworkRegistration"
46 #define OFONO_CM_INTERFACE OFONO_SERVICE ".ConnectionManager"
47 #define OFONO_CONTEXT_INTERFACE OFONO_SERVICE ".ConnectionContext"
49 #define MODEM_ADDED "ModemAdded"
50 #define MODEM_REMOVED "ModemRemoved"
51 #define PROPERTY_CHANGED "PropertyChanged"
52 #define CONTEXT_ADDED "ContextAdded"
53 #define CONTEXT_REMOVED "ContextRemoved"
55 #define GET_MODEMS "GetModems"
59 static DBusConnection *connection;
61 static GHashTable *modem_hash;
67 static gboolean context_changed(DBusConnection *connection,
74 static gboolean cm_context_added(DBusConnection *connection,
81 static gboolean cm_context_removed(DBusConnection *connection,
88 static gboolean netreg_changed(DBusConnection *connection, DBusMessage *message,
94 static gboolean cm_changed(DBusConnection *connection, DBusMessage *message,
100 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
106 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
112 static void add_modem(const char *path, DBusMessageIter *prop)
114 struct modem_data *modem;
118 modem = g_hash_table_lookup(modem_hash, path);
121 * When oFono powers up we ask for the modems and oFono is
122 * reporting with modem_added signal the modems. Only
128 modem = g_try_new0(struct modem_data, 1);
132 modem->path = g_strdup(path);
134 g_hash_table_insert(modem_hash, g_strdup(path), modem);
137 static void remove_modem(gpointer data)
139 struct modem_data *modem = data;
141 DBG("%s", modem->path);
148 static gboolean modem_added(DBusConnection *connection,
149 DBusMessage *message, void *user_data)
151 DBusMessageIter iter, properties;
156 if (dbus_message_iter_init(message, &iter) == FALSE)
159 dbus_message_iter_get_basic(&iter, &path);
161 dbus_message_iter_next(&iter);
162 dbus_message_iter_recurse(&iter, &properties);
164 add_modem(path, &properties);
169 static gboolean modem_removed(DBusConnection *connection,
170 DBusMessage *message, void *user_data)
172 DBusMessageIter iter;
177 if (dbus_message_iter_init(message, &iter) == FALSE)
180 dbus_message_iter_get_basic(&iter, &path);
182 g_hash_table_remove(modem_hash, path);
187 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
191 DBusMessageIter array, dict;
195 reply = dbus_pending_call_steal_reply(call);
197 dbus_error_init(&error);
199 if (dbus_set_error_from_message(&error, reply) == TRUE) {
200 connman_error("%s", error.message);
201 dbus_error_free(&error);
205 if (dbus_message_iter_init(reply, &array) == FALSE)
208 dbus_message_iter_recurse(&array, &dict);
210 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
211 DBusMessageIter value, properties;
214 dbus_message_iter_recurse(&dict, &value);
215 dbus_message_iter_get_basic(&value, &path);
217 dbus_message_iter_next(&value);
218 dbus_message_iter_recurse(&value, &properties);
220 add_modem(path, &properties);
222 dbus_message_iter_next(&dict);
226 dbus_message_unref(reply);
228 dbus_pending_call_unref(call);
231 static int manager_get_modems(void)
233 DBusMessage *message;
234 DBusPendingCall *call;
238 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
239 OFONO_MANAGER_INTERFACE, GET_MODEMS);
243 if (dbus_connection_send_with_reply(connection, message,
244 &call, TIMEOUT) == FALSE) {
245 connman_error("Failed to call GetModems()");
246 dbus_message_unref(message);
251 connman_error("D-Bus connection not available");
252 dbus_message_unref(message);
256 dbus_pending_call_set_notify(call, manager_get_modems_reply,
259 dbus_message_unref(message);
264 static void ofono_connect(DBusConnection *conn, void *user_data)
268 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
269 g_free, remove_modem);
270 if (modem_hash == NULL)
273 manager_get_modems();
276 static void ofono_disconnect(DBusConnection *conn, void *user_data)
280 if (modem_hash == NULL)
283 g_hash_table_destroy(modem_hash);
287 static int network_probe(struct connman_network *network)
289 DBG("network %p", network);
294 static void network_remove(struct connman_network *network)
296 DBG("network %p", network);
299 static int network_connect(struct connman_network *network)
301 DBG("network %p", network);
306 static int network_disconnect(struct connman_network *network)
308 DBG("network %p", network);
313 static struct connman_network_driver network_driver = {
315 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
316 .probe = network_probe,
317 .remove = network_remove,
318 .connect = network_connect,
319 .disconnect = network_disconnect,
322 static int modem_probe(struct connman_device *device)
324 DBG("device %p", device);
329 static void modem_remove(struct connman_device *device)
331 DBG("device %p", device);
334 static int modem_enable(struct connman_device *device)
336 DBG("device %p", device);
341 static int modem_disable(struct connman_device *device)
343 DBG("device %p", device);
348 static struct connman_device_driver modem_driver = {
350 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
351 .probe = modem_probe,
352 .remove = modem_remove,
353 .enable = modem_enable,
354 .disable = modem_disable,
358 static guint modem_added_watch;
359 static guint modem_removed_watch;
360 static guint modem_watch;
361 static guint cm_watch;
362 static guint sim_watch;
363 static guint context_added_watch;
364 static guint context_removed_watch;
365 static guint netreg_watch;
366 static guint context_watch;
368 static int ofono_init(void)
374 connection = connman_dbus_get_connection();
375 if (connection == NULL)
378 watch = g_dbus_add_service_watch(connection,
379 OFONO_SERVICE, ofono_connect,
380 ofono_disconnect, NULL, NULL);
382 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
383 OFONO_MANAGER_INTERFACE,
388 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
389 OFONO_MANAGER_INTERFACE,
394 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
395 OFONO_MODEM_INTERFACE,
400 cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
406 sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
412 context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
418 context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
424 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
425 OFONO_CONTEXT_INTERFACE,
430 netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
431 OFONO_NETREG_INTERFACE,
437 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
438 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
439 context_added_watch == 0 ||
440 context_removed_watch == 0 ||
441 context_watch == 0 || netreg_watch == 0) {
446 err = connman_network_driver_register(&network_driver);
450 err = connman_device_driver_register(&modem_driver);
452 connman_network_driver_unregister(&network_driver);
459 g_dbus_remove_watch(connection, netreg_watch);
460 g_dbus_remove_watch(connection, context_watch);
461 g_dbus_remove_watch(connection, context_removed_watch);
462 g_dbus_remove_watch(connection, context_added_watch);
463 g_dbus_remove_watch(connection, sim_watch);
464 g_dbus_remove_watch(connection, cm_watch);
465 g_dbus_remove_watch(connection, modem_watch);
466 g_dbus_remove_watch(connection, modem_removed_watch);
467 g_dbus_remove_watch(connection, modem_added_watch);
468 g_dbus_remove_watch(connection, watch);
469 dbus_connection_unref(connection);
474 static void ofono_exit(void)
478 if (modem_hash != NULL) {
479 g_hash_table_destroy(modem_hash);
483 connman_device_driver_unregister(&modem_driver);
484 connman_network_driver_unregister(&network_driver);
486 g_dbus_remove_watch(connection, netreg_watch);
487 g_dbus_remove_watch(connection, context_watch);
488 g_dbus_remove_watch(connection, context_removed_watch);
489 g_dbus_remove_watch(connection, context_added_watch);
490 g_dbus_remove_watch(connection, sim_watch);
491 g_dbus_remove_watch(connection, cm_watch);
492 g_dbus_remove_watch(connection, modem_watch);
493 g_dbus_remove_watch(connection, modem_added_watch);
494 g_dbus_remove_watch(connection, modem_removed_watch);
495 g_dbus_remove_watch(connection, watch);
497 dbus_connection_unref(connection);
500 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
501 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)