5 * Copyright (C) 2007-2008 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
30 struct connman_network {
31 struct connman_element element;
32 enum connman_network_type type;
37 struct connman_network_driver *driver;
40 struct connman_device *device;
43 static DBusMessage *get_properties(DBusConnection *conn,
44 DBusMessage *msg, void *data)
46 struct connman_network *network = data;
48 DBusMessageIter array, dict;
52 reply = dbus_message_new_method_return(msg);
56 dbus_message_iter_init_append(reply, &array);
58 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
59 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
60 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
61 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
63 if (network->identifier != NULL)
64 connman_dbus_dict_append_variant(&dict, "Name",
65 DBUS_TYPE_STRING, &network->identifier);
67 connman_dbus_dict_append_variant(&dict, "Connected",
68 DBUS_TYPE_BOOLEAN, &network->connected);
70 dbus_message_iter_close_container(&array, &dict);
75 static DBusMessage *set_property(DBusConnection *conn,
76 DBusMessage *msg, void *data)
78 DBusMessageIter iter, value;
83 if (dbus_message_iter_init(msg, &iter) == FALSE)
84 return __connman_error_invalid_arguments(msg);
86 dbus_message_iter_get_basic(&iter, &name);
87 dbus_message_iter_next(&iter);
88 dbus_message_iter_recurse(&iter, &value);
90 if (__connman_security_check_privileges(msg) < 0)
91 return __connman_error_permission_denied(msg);
93 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
96 static DBusMessage *do_connect(DBusConnection *conn,
97 DBusMessage *msg, void *data)
99 struct connman_network *network = data;
102 DBG("conn %p", conn);
104 if (network->driver && network->driver->connect) {
105 err = network->driver->connect(network);
106 if (err < 0 && err != -EINPROGRESS)
107 return __connman_error_failed(msg);
110 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
113 static DBusMessage *do_disconnect(DBusConnection *conn,
114 DBusMessage *msg, void *data)
116 struct connman_network *network = data;
119 DBG("conn %p", conn);
121 if (network->driver && network->driver->disconnect) {
122 err = network->driver->disconnect(network);
123 if (err < 0 && err != -EINPROGRESS)
124 return __connman_error_failed(msg);
127 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
130 static GDBusMethodTable network_methods[] = {
131 { "GetProperties", "", "a{sv}", get_properties },
132 { "SetProperty", "sv", "", set_property },
133 { "Connect", "", "", do_connect },
134 { "Disconnect", "", "", do_disconnect },
138 static GDBusSignalTable network_signals[] = {
139 { "PropertyChanged", "sv" },
143 static DBusConnection *connection;
145 static void emit_networks_signal(void)
149 static int register_interface(struct connman_element *element)
151 struct connman_network *network = element->network;
153 DBG("element %p name %s", element, element->name);
155 g_dbus_unregister_interface(connection, element->path,
156 CONNMAN_NETWORK_INTERFACE);
158 if (g_dbus_register_interface(connection, element->path,
159 CONNMAN_NETWORK_INTERFACE,
160 network_methods, network_signals,
161 NULL, network, NULL) == FALSE) {
162 connman_error("Failed to register %s network", element->path);
166 emit_networks_signal();
171 static void unregister_interface(struct connman_element *element)
173 DBG("element %p name %s", element, element->name);
175 emit_networks_signal();
177 g_dbus_unregister_interface(connection, element->path,
178 CONNMAN_NETWORK_INTERFACE);
181 static GSList *driver_list = NULL;
183 static gint compare_priority(gconstpointer a, gconstpointer b)
185 const struct connman_network_driver *driver1 = a;
186 const struct connman_network_driver *driver2 = b;
188 return driver2->priority - driver1->priority;
192 * connman_network_driver_register:
193 * @driver: network driver definition
195 * Register a new network driver
197 * Returns: %0 on success
199 int connman_network_driver_register(struct connman_network_driver *driver)
201 DBG("driver %p name %s", driver, driver->name);
203 driver_list = g_slist_insert_sorted(driver_list, driver,
210 * connman_network_driver_unregister:
211 * @driver: network driver definition
213 * Remove a previously registered network driver
215 void connman_network_driver_unregister(struct connman_network_driver *driver)
217 DBG("driver %p name %s", driver, driver->name);
219 driver_list = g_slist_remove(driver_list, driver);
222 static void network_destruct(struct connman_element *element)
224 struct connman_network *network = element->network;
226 DBG("element %p name %s", element, element->name);
228 g_free(network->path);
229 g_free(network->identifier);
233 * connman_network_create:
234 * @identifier: network identifier (for example an unqiue name)
236 * Allocate a new network and assign the #identifier to it.
238 * Returns: a newly-allocated #connman_network structure
240 struct connman_network *connman_network_create(const char *identifier,
241 enum connman_network_type type)
243 struct connman_network *network;
245 DBG("identifier %s type %d", identifier, type);
247 network = g_try_new0(struct connman_network, 1);
251 DBG("network %p", network);
253 network->element.refcount = 1;
255 network->element.name = g_strdup(identifier);
256 network->element.type = CONNMAN_ELEMENT_TYPE_NETWORK;
257 network->element.index = -1;
260 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
261 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
262 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH;
264 case CONNMAN_NETWORK_TYPE_HSO:
265 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_CELLULAR;
268 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
272 network->element.network = network;
273 network->element.destruct = network_destruct;
275 network->type = type;
276 network->identifier = g_strdup(identifier);
282 * connman_network_ref:
283 * @network: network structure
285 * Increase reference counter of network
287 struct connman_network *connman_network_ref(struct connman_network *network)
289 if (connman_element_ref(&network->element) == NULL)
296 * connman_network_unref:
297 * @network: network structure
299 * Decrease reference counter of network
301 void connman_network_unref(struct connman_network *network)
303 connman_element_unref(&network->element);
307 * connman_network_get_identifier:
308 * @network: network structure
310 * Get identifier of network
312 const char *connman_network_get_identifier(struct connman_network *network)
314 return network->identifier;
318 * connman_network_set_path:
319 * @network: network structure
322 * Set path name of network
324 void connman_network_set_path(struct connman_network *network, const char *path)
326 g_free(network->element.devpath);
327 network->element.devpath = g_strdup(path);
329 g_free(network->path);
330 network->path = g_strdup(path);
334 * connman_network_get_path:
335 * @network: network structure
337 * Get path name of network
339 const char *connman_network_get_path(struct connman_network *network)
341 return network->path;
345 * connman_network_set_index:
346 * @network: network structure
347 * @index: index number
349 * Set index number of network
351 void connman_network_set_index(struct connman_network *network, int index)
353 network->element.index = index;
357 * connman_network_get_index:
358 * @device: network structure
360 * Get index number of network
362 int connman_network_get_index(struct connman_network *network)
364 return network->element.index;
368 * connman_network_set_connected:
369 * @netowrk: network structure
370 * @connected: connected state
372 * Change connected state of network
374 int connman_network_set_connected(struct connman_network *network,
375 connman_bool_t connected)
377 DBG("network %p connected %d", network, connected);
379 if (network->connected == connected)
382 network->connected = connected;
384 if (connected == TRUE) {
385 struct connman_element *element;
387 element = connman_element_create(NULL);
388 if (element != NULL) {
389 element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
390 element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
391 element->index = network->element.index;
393 if (connman_element_register(element,
394 &network->element) < 0)
395 connman_element_unref(element);
398 connman_element_unregister_children(&network->element);
403 void __connman_network_set_device(struct connman_network *network,
404 struct connman_device *device)
406 network->device = device;
410 * connman_network_get_device:
411 * @network: network structure
413 * Get parent device of network
415 struct connman_device *connman_network_get_device(struct connman_network *network)
417 return network->device;
421 * connman_network_get_data:
422 * @network: network structure
424 * Get private network data pointer
426 void *connman_network_get_data(struct connman_network *network)
428 return network->driver_data;
432 * connman_network_set_data:
433 * @network: network structure
434 * @data: data pointer
436 * Set private network data pointer
438 void connman_network_set_data(struct connman_network *network, void *data)
440 network->driver_data = data;
443 static gboolean match_driver(struct connman_network *network,
444 struct connman_network_driver *driver)
446 if (network->type == driver->type ||
447 driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
453 static int network_probe(struct connman_element *element)
455 struct connman_network *network = element->network;
459 DBG("element %p name %s", element, element->name);
464 for (list = driver_list; list; list = list->next) {
465 struct connman_network_driver *driver = list->data;
467 if (match_driver(network, driver) == FALSE)
470 DBG("driver %p name %s", driver, driver->name);
472 if (driver->probe(network) == 0) {
473 network->driver = driver;
478 if (network->driver == NULL)
481 err = register_interface(element);
483 if (network->driver->remove)
484 network->driver->remove(network);
491 static void network_remove(struct connman_element *element)
493 struct connman_network *network = element->network;
495 DBG("element %p name %s", element, element->name);
500 if (network->driver == NULL)
503 unregister_interface(element);
505 if (network->driver->remove)
506 network->driver->remove(network);
509 static struct connman_driver network_driver = {
511 .type = CONNMAN_ELEMENT_TYPE_NETWORK,
512 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
513 .probe = network_probe,
514 .remove = network_remove,
517 int __connman_network_init(void)
521 connection = connman_dbus_get_connection();
523 return connman_driver_register(&network_driver);
526 void __connman_network_cleanup(void)
530 connman_driver_unregister(&network_driver);
532 dbus_connection_unref(connection);