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
31 struct connman_device {
32 struct connman_element element;
33 enum connman_device_type type;
34 enum connman_device_mode mode;
35 enum connman_device_policy policy;
42 struct connman_device_driver *driver;
48 static const char *type2description(enum connman_device_type type)
51 case CONNMAN_DEVICE_TYPE_ETHERNET:
53 case CONNMAN_DEVICE_TYPE_WIFI:
55 case CONNMAN_DEVICE_TYPE_WIMAX:
57 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
64 static const char *type2string(enum connman_device_type type)
67 case CONNMAN_DEVICE_TYPE_ETHERNET:
69 case CONNMAN_DEVICE_TYPE_WIFI:
71 case CONNMAN_DEVICE_TYPE_WIMAX:
73 case CONNMAN_DEVICE_TYPE_MODEM:
75 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
82 static const char *policy2string(enum connman_device_policy policy)
85 case CONNMAN_DEVICE_POLICY_IGNORE:
87 case CONNMAN_DEVICE_POLICY_AUTO:
89 case CONNMAN_DEVICE_POLICY_OFF:
96 static int set_powered(struct connman_device *device, gboolean powered)
98 struct connman_device_driver *driver = device->driver;
101 DBG("device %p powered %d", device, powered);
106 if (powered == TRUE) {
108 err = driver->enable(device);
113 err = driver->disable(device);
121 static void append_networks(struct connman_device *device,
122 DBusMessageIter *entry)
124 DBusMessageIter value, iter;
125 const char *key = "Networks";
127 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
129 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
130 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
133 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
134 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
135 /* FIXME append networks */
136 dbus_message_iter_close_container(&value, &iter);
138 dbus_message_iter_close_container(entry, &value);
141 static DBusMessage *get_properties(DBusConnection *conn,
142 DBusMessage *msg, void *data)
144 struct connman_device *device = data;
146 DBusMessageIter array, dict, entry;
149 DBG("conn %p", conn);
151 reply = dbus_message_new_method_return(msg);
155 dbus_message_iter_init_append(reply, &array);
157 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
158 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
159 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
160 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
162 str = type2description(device->type);
163 if (str != NULL && device->interface != NULL) {
164 char *name = g_strdup_printf("%s (%s)", str, device->interface);
166 connman_dbus_dict_append_variant(&dict, "Name",
167 DBUS_TYPE_STRING, &name);
171 str = type2string(device->type);
173 connman_dbus_dict_append_variant(&dict, "Type",
174 DBUS_TYPE_STRING, &str);
176 if (device->interface != NULL)
177 connman_dbus_dict_append_variant(&dict, "Interface",
178 DBUS_TYPE_STRING, &device->interface);
180 str = policy2string(device->policy);
182 connman_dbus_dict_append_variant(&dict, "Policy",
183 DBUS_TYPE_STRING, &str);
185 connman_dbus_dict_append_variant(&dict, "Powered",
186 DBUS_TYPE_BOOLEAN, &device->powered);
188 if (device->driver && device->driver->scan)
189 connman_dbus_dict_append_variant(&dict, "Scanning",
190 DBUS_TYPE_BOOLEAN, &device->scanning);
192 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK) {
193 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
195 append_networks(device, &entry);
196 dbus_message_iter_close_container(&dict, &entry);
199 dbus_message_iter_close_container(&array, &dict);
204 static DBusMessage *set_property(DBusConnection *conn,
205 DBusMessage *msg, void *data)
207 struct connman_device *device = data;
208 DBusMessageIter iter, value;
211 DBG("conn %p", conn);
213 if (dbus_message_iter_init(msg, &iter) == FALSE)
214 return __connman_error_invalid_arguments(msg);
216 dbus_message_iter_get_basic(&iter, &name);
217 dbus_message_iter_next(&iter);
218 dbus_message_iter_recurse(&iter, &value);
220 if (__connman_security_check_privileges(msg) < 0)
221 return __connman_error_permission_denied(msg);
223 if (g_str_equal(name, "Powered") == TRUE) {
227 dbus_message_iter_get_basic(&value, &powered);
229 if (device->powered == powered)
230 return __connman_error_invalid_arguments(msg);
232 err = set_powered(device, powered);
233 if (err < 0 && err != -EINPROGRESS)
234 return __connman_error_failed(msg);
237 __connman_element_store(&device->element);
239 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
242 static DBusMessage *create_network(DBusConnection *conn,
243 DBusMessage *msg, void *data)
245 DBG("conn %p", conn);
247 if (__connman_security_check_privileges(msg) < 0)
248 return __connman_error_permission_denied(msg);
250 return __connman_error_invalid_arguments(msg);
253 static DBusMessage *remove_network(DBusConnection *conn,
254 DBusMessage *msg, void *data)
256 DBG("conn %p", conn);
258 if (__connman_security_check_privileges(msg) < 0)
259 return __connman_error_permission_denied(msg);
261 return __connman_error_invalid_arguments(msg);
264 static DBusMessage *propose_scan(DBusConnection *conn,
265 DBusMessage *msg, void *data)
267 struct connman_device *device = data;
270 DBG("conn %p", conn);
272 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
273 return __connman_error_not_supported(msg);
275 if (!device->driver || !device->driver->scan)
276 return __connman_error_not_supported(msg);
278 err = device->driver->scan(device);
280 return __connman_error_failed(msg);
282 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
285 static GDBusMethodTable device_methods[] = {
286 { "GetProperties", "", "a{sv}", get_properties },
287 { "SetProperty", "sv", "", set_property },
288 { "CreateNetwork", "a{sv}", "o", create_network },
289 { "RemoveNetwork", "o", "", remove_network },
290 { "ProposeScan", "", "", propose_scan },
294 static GDBusSignalTable device_signals[] = {
295 { "PropertyChanged", "sv" },
299 static DBusConnection *connection;
301 static int register_interface(struct connman_element *element)
303 struct connman_device *device = element->device;
305 g_dbus_unregister_interface(connection, element->path,
306 CONNMAN_DEVICE_INTERFACE);
308 if (g_dbus_register_interface(connection, element->path,
309 CONNMAN_DEVICE_INTERFACE,
310 device_methods, device_signals,
311 NULL, device, NULL) == FALSE) {
312 connman_error("Failed to register %s device", element->path);
319 static void unregister_interface(struct connman_element *element)
321 g_dbus_unregister_interface(connection, element->path,
322 CONNMAN_DEVICE_INTERFACE);
325 static GSList *driver_list = NULL;
327 static gint compare_priority(gconstpointer a, gconstpointer b)
329 const struct connman_device_driver *driver1 = a;
330 const struct connman_device_driver *driver2 = b;
332 return driver2->priority - driver1->priority;
336 * connman_device_driver_register:
337 * @driver: device driver definition
339 * Register a new device driver
341 * Returns: %0 on success
343 int connman_device_driver_register(struct connman_device_driver *driver)
345 DBG("driver %p name %s", driver, driver->name);
347 driver_list = g_slist_insert_sorted(driver_list, driver,
350 //__connman_driver_rescan(&device_driver);
356 * connman_device_driver_unregister:
357 * @driver: device driver definition
359 * Remove a previously registered device driver
361 void connman_device_driver_unregister(struct connman_device_driver *driver)
363 DBG("driver %p name %s", driver, driver->name);
365 driver_list = g_slist_remove(driver_list, driver);
368 static void unregister_network(gpointer data)
370 struct connman_network *network = data;
372 DBG("network %p", network);
374 connman_element_unregister((struct connman_element *) network);
376 connman_network_unref(network);
379 static void device_destruct(struct connman_element *element)
381 struct connman_device *device = element->device;
383 DBG("element %p name %s", element, element->name);
385 g_free(device->interface);
387 g_hash_table_destroy(device->networks);
391 * connman_device_create:
392 * @node: device node name (for example an address)
395 * Allocate a new device of given #type and assign the #node name to it.
397 * Returns: a newly-allocated #connman_device structure
399 struct connman_device *connman_device_create(const char *node,
400 enum connman_device_type type)
402 struct connman_device *device;
404 DBG("node %s type %d", node, type);
406 device = g_try_new0(struct connman_device, 1);
410 DBG("device %p", device);
412 device->element.refcount = 1;
414 device->element.name = g_strdup(node);
415 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
416 device->element.index = -1;
418 device->element.device = device;
419 device->element.destruct = device_destruct;
422 device->mode = CONNMAN_DEVICE_MODE_NO_NETWORK;
423 device->policy = CONNMAN_DEVICE_POLICY_AUTO;
425 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
426 g_free, unregister_network);
432 * connman_device_ref:
433 * @device: device structure
435 * Increase reference counter of device
437 struct connman_device *connman_device_ref(struct connman_device *device)
439 if (connman_element_ref(&device->element) == NULL)
446 * connman_device_unref:
447 * @device: device structure
449 * Decrease reference counter of device
451 void connman_device_unref(struct connman_device *device)
453 connman_element_unref(&device->element);
457 * connman_device_set_path:
458 * @device: device structure
461 * Set path name of device
463 void connman_device_set_path(struct connman_device *device, const char *path)
465 g_free(device->element.devpath);
466 device->element.devpath = g_strdup(path);
468 g_free(device->path);
469 device->path = g_strdup(path);
473 * connman_device_get_path:
474 * @device: device structure
476 * Get path name of device
478 const char *connman_device_get_path(struct connman_device *device)
484 * connman_device_set_index:
485 * @device: device structure
486 * @index: index number
488 * Set index number of device
490 void connman_device_set_index(struct connman_device *device, int index)
492 device->element.index = index;
496 * connman_device_get_index:
497 * @device: device structure
499 * Get index number of device
501 int connman_device_get_index(struct connman_device *device)
503 return device->element.index;
507 * connman_device_set_interface:
508 * @device: device structure
509 * @interface: interface name
511 * Set interface name of device
513 void connman_device_set_interface(struct connman_device *device,
514 const char *interface)
516 g_free(device->element.devname);
517 device->element.devname = g_strdup(interface);
519 g_free(device->interface);
520 device->interface = g_strdup(interface);
524 * connman_device_get_interface:
525 * @device: device structure
527 * Get interface name of device
529 const char *connman_device_get_interface(struct connman_device *device)
531 return device->interface;
535 * connman_device_set_mode:
536 * @device: device structure
537 * @mode: network mode
539 * Change network mode of device
541 void connman_device_set_mode(struct connman_device *device,
542 enum connman_device_mode mode)
548 * connman_device_set_powered:
549 * @device: device structure
550 * @powered: powered state
552 * Change power state of device
554 int connman_device_set_powered(struct connman_device *device,
558 DBusMessageIter entry, value;
559 const char *key = "Powered";
561 DBG("driver %p powered %d", device, powered);
563 if (device->powered == powered)
566 device->powered = powered;
568 signal = dbus_message_new_signal(device->element.path,
569 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
573 dbus_message_iter_init_append(signal, &entry);
575 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
577 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
578 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
579 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
580 dbus_message_iter_close_container(&entry, &value);
582 g_dbus_send_message(connection, signal);
588 * connman_device_set_carrier:
589 * @device: device structure
590 * @carrier: carrier state
592 * Change carrier state of device (only for device without scanning)
594 int connman_device_set_carrier(struct connman_device *device,
597 DBG("driver %p carrier %d", device, carrier);
599 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK)
602 if (device->carrier == carrier)
605 device->carrier = carrier;
607 if (carrier == TRUE) {
608 struct connman_element *element;
610 element = connman_element_create(NULL);
611 if (element != NULL) {
612 element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
613 element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
614 element->index = device->element.index;
616 if (connman_element_register(element,
617 &device->element) < 0)
618 connman_element_unref(element);
621 connman_element_unregister_children(&device->element);
627 * connman_device_set_scanning:
628 * @device: device structure
629 * @scanning: scanning state
631 * Change scanning state of device
633 int connman_device_set_scanning(struct connman_device *device,
637 DBusMessageIter entry, value;
638 const char *key = "Scanning";
640 DBG("driver %p scanning %d", device, scanning);
642 if (!device->driver || !device->driver->scan)
645 if (device->scanning == scanning)
648 device->scanning = scanning;
650 signal = dbus_message_new_signal(device->element.path,
651 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
655 dbus_message_iter_init_append(signal, &entry);
657 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
659 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
660 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
661 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
662 dbus_message_iter_close_container(&entry, &value);
664 g_dbus_send_message(connection, signal);
670 * connman_device_add_network:
671 * @device: device structure
672 * @network: network structure
674 * Add new network to the device
676 int connman_device_add_network(struct connman_device *device,
677 struct connman_network *network)
679 const char *identifier = connman_network_get_identifier(network);
682 DBG("device %p network %p", device, network);
684 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
687 err = connman_element_register(&device->element,
688 (struct connman_element *) network);
692 g_hash_table_insert(device->networks, g_strdup(identifier),
699 * connman_device_get_network:
700 * @device: device structure
701 * @identifier: network identifier
703 * Get network for given identifier
705 struct connman_network *connman_device_get_network(struct connman_device *device,
706 const char *identifier)
708 DBG("device %p identifier %s", device, identifier);
710 return g_hash_table_lookup(device->networks, identifier);
714 * connman_device_remove_network:
715 * @device: device structure
716 * @identifier: network identifier
718 * Remove network for given identifier
720 int connman_device_remove_network(struct connman_device *device,
721 const char *identifier)
723 DBG("device %p identifier %s", device, identifier);
725 g_hash_table_remove(device->networks, identifier);
731 * connman_device_register:
732 * @device: device structure
734 * Register device with the system
736 int connman_device_register(struct connman_device *device)
738 return connman_element_register(&device->element, NULL);
742 * connman_device_unregister:
743 * @device: device structure
745 * Unregister device with the system
747 void connman_device_unregister(struct connman_device *device)
749 connman_element_unregister(&device->element);
753 * connman_device_get_data:
754 * @device: device structure
756 * Get private device data pointer
758 void *connman_device_get_data(struct connman_device *device)
760 return device->driver_data;
764 * connman_device_set_data:
765 * @device: device structure
766 * @data: data pointer
768 * Set private device data pointer
770 void connman_device_set_data(struct connman_device *device, void *data)
772 device->driver_data = data;
775 static void device_enable(struct connman_device *device)
777 DBG("device %p", device);
779 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
782 if (device->powered == TRUE)
785 if (device->driver->enable)
786 device->driver->enable(device);
789 static void device_disable(struct connman_device *device)
791 DBG("device %p", device);
793 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
796 if (device->powered == FALSE)
799 if (device->driver->disable)
800 device->driver->disable(device);
803 static gboolean match_driver(struct connman_device *device,
804 struct connman_device_driver *driver)
806 if (device->type == driver->type ||
807 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
813 static int device_probe(struct connman_element *element)
815 struct connman_device *device = element->device;
819 DBG("element %p name %s", element, element->name);
824 err = register_interface(element);
828 for (list = driver_list; list; list = list->next) {
829 struct connman_device_driver *driver = list->data;
831 if (match_driver(device, driver) == FALSE)
834 DBG("driver %p name %s", driver, driver->name);
836 if (driver->probe(device) == 0) {
837 device->driver = driver;
838 device_enable(device);
846 static void device_remove(struct connman_element *element)
848 struct connman_device *device = element->device;
850 DBG("element %p name %s", element, element->name);
855 unregister_interface(element);
857 if (device->driver) {
858 device_disable(device);
860 if (device->driver->remove)
861 device->driver->remove(device);
865 static struct connman_driver device_driver = {
867 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
868 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
869 .probe = device_probe,
870 .remove = device_remove,
873 int __connman_device_init(void)
877 connection = connman_dbus_get_connection();
879 return connman_driver_register(&device_driver);
882 void __connman_device_cleanup(void)
886 connman_driver_unregister(&device_driver);
888 dbus_connection_unref(connection);