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:
59 case CONNMAN_DEVICE_TYPE_HSO:
66 static const char *type2string(enum connman_device_type type)
69 case CONNMAN_DEVICE_TYPE_ETHERNET:
71 case CONNMAN_DEVICE_TYPE_WIFI:
73 case CONNMAN_DEVICE_TYPE_WIMAX:
75 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
77 case CONNMAN_DEVICE_TYPE_HSO:
84 static const char *policy2string(enum connman_device_policy policy)
87 case CONNMAN_DEVICE_POLICY_IGNORE:
89 case CONNMAN_DEVICE_POLICY_OFF:
91 case CONNMAN_DEVICE_POLICY_AUTO:
93 case CONNMAN_DEVICE_POLICY_MANUAL:
100 static enum connman_device_policy string2policy(const char *policy)
102 if (g_str_equal(policy, "ignore") == TRUE)
103 return CONNMAN_DEVICE_POLICY_IGNORE;
104 else if (g_str_equal(policy, "off") == TRUE)
105 return CONNMAN_DEVICE_POLICY_OFF;
106 else if (g_str_equal(policy, "auto") == TRUE)
107 return CONNMAN_DEVICE_POLICY_AUTO;
108 else if (g_str_equal(policy, "manual") == TRUE)
109 return CONNMAN_DEVICE_POLICY_MANUAL;
111 return CONNMAN_DEVICE_POLICY_UNKNOWN;
114 static int set_powered(struct connman_device *device, gboolean powered)
116 struct connman_device_driver *driver = device->driver;
119 DBG("device %p powered %d", device, powered);
124 if (powered == TRUE) {
126 err = driver->enable(device);
131 err = driver->disable(device);
139 static int set_policy(DBusConnection *connection,
140 struct connman_device *device,
141 enum connman_device_policy policy)
144 DBusMessageIter entry, value;
145 const char *str, *key = "Policy";
148 DBG("device %p policy %d", device, policy);
150 if (device->policy == policy)
154 case CONNMAN_DEVICE_POLICY_OFF:
155 if (device->powered == TRUE)
156 err = set_powered(device, FALSE);
158 case CONNMAN_DEVICE_POLICY_AUTO:
159 case CONNMAN_DEVICE_POLICY_MANUAL:
160 if (device->powered == FALSE)
161 err = set_powered(device, TRUE);
170 device->policy = policy;
172 signal = dbus_message_new_signal(device->element.path,
173 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
177 dbus_message_iter_init_append(signal, &entry);
179 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
181 str = policy2string(policy);
183 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
184 DBUS_TYPE_STRING_AS_STRING, &value);
185 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
186 dbus_message_iter_close_container(&entry, &value);
188 g_dbus_send_message(connection, signal);
193 static void append_networks(struct connman_device *device,
194 DBusMessageIter *entry)
196 DBusMessageIter value, iter;
197 const char *key = "Networks";
199 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
201 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
202 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
205 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
206 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
207 __connman_element_list((struct connman_element *) device,
208 CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
209 dbus_message_iter_close_container(&value, &iter);
211 dbus_message_iter_close_container(entry, &value);
214 static DBusMessage *get_properties(DBusConnection *conn,
215 DBusMessage *msg, void *data)
217 struct connman_device *device = data;
219 DBusMessageIter array, dict, entry;
222 DBG("conn %p", conn);
224 reply = dbus_message_new_method_return(msg);
228 dbus_message_iter_init_append(reply, &array);
230 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
231 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
232 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
233 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
235 str = type2description(device->type);
236 if (str != NULL && device->interface != NULL) {
237 char *name = g_strdup_printf("%s (%s)", str, device->interface);
239 connman_dbus_dict_append_variant(&dict, "Name",
240 DBUS_TYPE_STRING, &name);
244 str = type2string(device->type);
246 connman_dbus_dict_append_variant(&dict, "Type",
247 DBUS_TYPE_STRING, &str);
249 if (device->interface != NULL)
250 connman_dbus_dict_append_variant(&dict, "Interface",
251 DBUS_TYPE_STRING, &device->interface);
253 str = policy2string(device->policy);
255 connman_dbus_dict_append_variant(&dict, "Policy",
256 DBUS_TYPE_STRING, &str);
258 connman_dbus_dict_append_variant(&dict, "Powered",
259 DBUS_TYPE_BOOLEAN, &device->powered);
261 if (device->driver && device->driver->scan)
262 connman_dbus_dict_append_variant(&dict, "Scanning",
263 DBUS_TYPE_BOOLEAN, &device->scanning);
265 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK) {
266 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
268 append_networks(device, &entry);
269 dbus_message_iter_close_container(&dict, &entry);
272 dbus_message_iter_close_container(&array, &dict);
277 static DBusMessage *set_property(DBusConnection *conn,
278 DBusMessage *msg, void *data)
280 struct connman_device *device = data;
281 DBusMessageIter iter, value;
284 DBG("conn %p", conn);
286 if (dbus_message_iter_init(msg, &iter) == FALSE)
287 return __connman_error_invalid_arguments(msg);
289 dbus_message_iter_get_basic(&iter, &name);
290 dbus_message_iter_next(&iter);
291 dbus_message_iter_recurse(&iter, &value);
293 if (__connman_security_check_privileges(msg) < 0)
294 return __connman_error_permission_denied(msg);
296 if (g_str_equal(name, "Powered") == TRUE) {
300 dbus_message_iter_get_basic(&value, &powered);
302 if (device->powered == powered)
303 return __connman_error_invalid_arguments(msg);
305 err = set_powered(device, powered);
306 if (err < 0 && err != -EINPROGRESS)
307 return __connman_error_failed(msg);
308 } else if (g_str_equal(name, "Policy") == TRUE) {
309 enum connman_device_policy policy;
313 dbus_message_iter_get_basic(&value, &str);
314 policy = string2policy(str);
315 if (policy == CONNMAN_DEVICE_POLICY_UNKNOWN)
316 return __connman_error_invalid_arguments(msg);
318 err = set_policy(conn, device, policy);
320 return __connman_error_failed(msg);
323 __connman_element_store(&device->element);
325 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
328 static DBusMessage *create_network(DBusConnection *conn,
329 DBusMessage *msg, void *data)
331 DBG("conn %p", conn);
333 if (__connman_security_check_privileges(msg) < 0)
334 return __connman_error_permission_denied(msg);
336 return __connman_error_invalid_arguments(msg);
339 static DBusMessage *remove_network(DBusConnection *conn,
340 DBusMessage *msg, void *data)
342 DBG("conn %p", conn);
344 if (__connman_security_check_privileges(msg) < 0)
345 return __connman_error_permission_denied(msg);
347 return __connman_error_invalid_arguments(msg);
350 static DBusMessage *propose_scan(DBusConnection *conn,
351 DBusMessage *msg, void *data)
353 struct connman_device *device = data;
356 DBG("conn %p", conn);
358 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
359 return __connman_error_not_supported(msg);
361 if (!device->driver || !device->driver->scan)
362 return __connman_error_not_supported(msg);
364 err = device->driver->scan(device);
366 return __connman_error_failed(msg);
368 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
371 static GDBusMethodTable device_methods[] = {
372 { "GetProperties", "", "a{sv}", get_properties },
373 { "SetProperty", "sv", "", set_property },
374 { "CreateNetwork", "a{sv}", "o", create_network },
375 { "RemoveNetwork", "o", "", remove_network },
376 { "ProposeScan", "", "", propose_scan },
380 static GDBusSignalTable device_signals[] = {
381 { "PropertyChanged", "sv" },
385 static DBusConnection *connection;
387 static void append_devices(DBusMessageIter *entry)
389 DBusMessageIter value, iter;
390 const char *key = "Devices";
392 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
394 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
395 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
398 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
399 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
400 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
401 dbus_message_iter_close_container(&value, &iter);
403 dbus_message_iter_close_container(entry, &value);
406 static void emit_devices_signal(void)
409 DBusMessageIter entry;
411 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
412 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
416 dbus_message_iter_init_append(signal, &entry);
418 append_devices(&entry);
420 g_dbus_send_message(connection, signal);
423 static int register_interface(struct connman_element *element)
425 struct connman_device *device = element->device;
427 if (g_dbus_register_interface(connection, element->path,
428 CONNMAN_DEVICE_INTERFACE,
429 device_methods, device_signals,
430 NULL, device, NULL) == FALSE) {
431 connman_error("Failed to register %s device", element->path);
435 emit_devices_signal();
440 static void unregister_interface(struct connman_element *element)
442 emit_devices_signal();
444 g_dbus_unregister_interface(connection, element->path,
445 CONNMAN_DEVICE_INTERFACE);
448 static GSList *driver_list = NULL;
450 static gint compare_priority(gconstpointer a, gconstpointer b)
452 const struct connman_device_driver *driver1 = a;
453 const struct connman_device_driver *driver2 = b;
455 return driver2->priority - driver1->priority;
459 * connman_device_driver_register:
460 * @driver: device driver definition
462 * Register a new device driver
464 * Returns: %0 on success
466 int connman_device_driver_register(struct connman_device_driver *driver)
468 DBG("driver %p name %s", driver, driver->name);
470 driver_list = g_slist_insert_sorted(driver_list, driver,
473 //__connman_driver_rescan(&device_driver);
479 * connman_device_driver_unregister:
480 * @driver: device driver definition
482 * Remove a previously registered device driver
484 void connman_device_driver_unregister(struct connman_device_driver *driver)
486 DBG("driver %p name %s", driver, driver->name);
488 driver_list = g_slist_remove(driver_list, driver);
491 static void unregister_network(gpointer data)
493 struct connman_network *network = data;
495 DBG("network %p", network);
497 connman_element_unregister((struct connman_element *) network);
499 connman_network_unref(network);
502 static void device_destruct(struct connman_element *element)
504 struct connman_device *device = element->device;
506 DBG("element %p name %s", element, element->name);
508 g_free(device->interface);
510 g_hash_table_destroy(device->networks);
514 * connman_device_create:
515 * @node: device node name (for example an address)
518 * Allocate a new device of given #type and assign the #node name to it.
520 * Returns: a newly-allocated #connman_device structure
522 struct connman_device *connman_device_create(const char *node,
523 enum connman_device_type type)
525 struct connman_device *device;
527 DBG("node %s type %d", node, type);
529 device = g_try_new0(struct connman_device, 1);
533 DBG("device %p", device);
535 device->element.refcount = 1;
537 device->element.name = g_strdup(node);
538 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
539 device->element.index = -1;
542 case CONNMAN_DEVICE_TYPE_ETHERNET:
543 device->element.subtype = CONNMAN_ELEMENT_SUBTYPE_ETHERNET;
546 device->element.subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
550 device->element.device = device;
551 device->element.destruct = device_destruct;
554 device->mode = CONNMAN_DEVICE_MODE_NO_NETWORK;
555 device->policy = CONNMAN_DEVICE_POLICY_AUTO;
557 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
558 g_free, unregister_network);
564 * connman_device_ref:
565 * @device: device structure
567 * Increase reference counter of device
569 struct connman_device *connman_device_ref(struct connman_device *device)
571 if (connman_element_ref(&device->element) == NULL)
578 * connman_device_unref:
579 * @device: device structure
581 * Decrease reference counter of device
583 void connman_device_unref(struct connman_device *device)
585 connman_element_unref(&device->element);
589 * connman_device_set_path:
590 * @device: device structure
593 * Set path name of device
595 void connman_device_set_path(struct connman_device *device, const char *path)
597 g_free(device->element.devpath);
598 device->element.devpath = g_strdup(path);
600 g_free(device->path);
601 device->path = g_strdup(path);
605 * connman_device_get_path:
606 * @device: device structure
608 * Get path name of device
610 const char *connman_device_get_path(struct connman_device *device)
616 * connman_device_set_index:
617 * @device: device structure
618 * @index: index number
620 * Set index number of device
622 void connman_device_set_index(struct connman_device *device, int index)
624 device->element.index = index;
628 * connman_device_get_index:
629 * @device: device structure
631 * Get index number of device
633 int connman_device_get_index(struct connman_device *device)
635 return device->element.index;
639 * connman_device_set_interface:
640 * @device: device structure
641 * @interface: interface name
643 * Set interface name of device
645 void connman_device_set_interface(struct connman_device *device,
646 const char *interface)
648 g_free(device->element.devname);
649 device->element.devname = g_strdup(interface);
651 g_free(device->interface);
652 device->interface = g_strdup(interface);
656 * connman_device_get_interface:
657 * @device: device structure
659 * Get interface name of device
661 const char *connman_device_get_interface(struct connman_device *device)
663 return device->interface;
667 * connman_device_set_policy:
668 * @device: device structure
669 * @policy: power and connection policy
671 * Change power and connection policy of device
673 void connman_device_set_policy(struct connman_device *device,
674 enum connman_device_policy policy)
676 device->policy = policy;
680 * connman_device_set_mode:
681 * @device: device structure
682 * @mode: network mode
684 * Change network mode of device
686 void connman_device_set_mode(struct connman_device *device,
687 enum connman_device_mode mode)
693 * connman_device_set_powered:
694 * @device: device structure
695 * @powered: powered state
697 * Change power state of device
699 int connman_device_set_powered(struct connman_device *device,
703 DBusMessageIter entry, value;
704 const char *key = "Powered";
706 DBG("driver %p powered %d", device, powered);
708 if (device->powered == powered)
711 device->powered = powered;
713 signal = dbus_message_new_signal(device->element.path,
714 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
718 dbus_message_iter_init_append(signal, &entry);
720 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
722 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
723 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
724 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
725 dbus_message_iter_close_container(&entry, &value);
727 g_dbus_send_message(connection, signal);
733 * connman_device_set_carrier:
734 * @device: device structure
735 * @carrier: carrier state
737 * Change carrier state of device (only for device without scanning)
739 int connman_device_set_carrier(struct connman_device *device,
742 DBG("driver %p carrier %d", device, carrier);
744 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK)
747 if (device->carrier == carrier)
750 device->carrier = carrier;
752 if (carrier == TRUE) {
753 struct connman_element *element;
755 element = connman_element_create(NULL);
756 if (element != NULL) {
757 element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
758 element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
759 element->index = device->element.index;
761 if (connman_element_register(element,
762 &device->element) < 0)
763 connman_element_unref(element);
766 connman_element_unregister_children(&device->element);
772 * connman_device_set_scanning:
773 * @device: device structure
774 * @scanning: scanning state
776 * Change scanning state of device
778 int connman_device_set_scanning(struct connman_device *device,
782 DBusMessageIter entry, value;
783 const char *key = "Scanning";
785 DBG("driver %p scanning %d", device, scanning);
787 if (!device->driver || !device->driver->scan)
790 if (device->scanning == scanning)
793 device->scanning = scanning;
795 signal = dbus_message_new_signal(device->element.path,
796 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
800 dbus_message_iter_init_append(signal, &entry);
802 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
804 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
805 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
806 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
807 dbus_message_iter_close_container(&entry, &value);
809 g_dbus_send_message(connection, signal);
815 * connman_device_add_network:
816 * @device: device structure
817 * @network: network structure
819 * Add new network to the device
821 int connman_device_add_network(struct connman_device *device,
822 struct connman_network *network)
824 const char *identifier = connman_network_get_identifier(network);
827 DBG("device %p network %p", device, network);
829 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
832 err = connman_element_register((struct connman_element *) network,
837 g_hash_table_insert(device->networks, g_strdup(identifier),
844 * connman_device_get_network:
845 * @device: device structure
846 * @identifier: network identifier
848 * Get network for given identifier
850 struct connman_network *connman_device_get_network(struct connman_device *device,
851 const char *identifier)
853 DBG("device %p identifier %s", device, identifier);
855 return g_hash_table_lookup(device->networks, identifier);
859 * connman_device_remove_network:
860 * @device: device structure
861 * @identifier: network identifier
863 * Remove network for given identifier
865 int connman_device_remove_network(struct connman_device *device,
866 const char *identifier)
868 DBG("device %p identifier %s", device, identifier);
870 g_hash_table_remove(device->networks, identifier);
876 * connman_device_register:
877 * @device: device structure
879 * Register device with the system
881 int connman_device_register(struct connman_device *device)
883 return connman_element_register(&device->element, NULL);
887 * connman_device_unregister:
888 * @device: device structure
890 * Unregister device with the system
892 void connman_device_unregister(struct connman_device *device)
894 connman_element_unregister(&device->element);
898 * connman_device_get_data:
899 * @device: device structure
901 * Get private device data pointer
903 void *connman_device_get_data(struct connman_device *device)
905 return device->driver_data;
909 * connman_device_set_data:
910 * @device: device structure
911 * @data: data pointer
913 * Set private device data pointer
915 void connman_device_set_data(struct connman_device *device, void *data)
917 device->driver_data = data;
920 static void device_enable(struct connman_device *device)
922 DBG("device %p", device);
924 if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE ||
925 device->policy == CONNMAN_DEVICE_POLICY_OFF)
928 if (device->powered == TRUE)
931 if (device->driver->enable)
932 device->driver->enable(device);
935 static void device_disable(struct connman_device *device)
937 DBG("device %p", device);
939 if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE)
942 if (device->powered == FALSE)
945 if (device->driver->disable)
946 device->driver->disable(device);
949 static gboolean match_driver(struct connman_device *device,
950 struct connman_device_driver *driver)
952 if (device->type == driver->type ||
953 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
959 static int device_probe(struct connman_element *element)
961 struct connman_device *device = element->device;
965 DBG("element %p name %s", element, element->name);
970 for (list = driver_list; list; list = list->next) {
971 struct connman_device_driver *driver = list->data;
973 if (match_driver(device, driver) == FALSE)
976 DBG("driver %p name %s", driver, driver->name);
978 if (driver->probe(device) == 0) {
979 device->driver = driver;
987 err = register_interface(element);
989 if (device->driver->remove)
990 device->driver->remove(device);
994 device_enable(device);
999 static void device_remove(struct connman_element *element)
1001 struct connman_device *device = element->device;
1003 DBG("element %p name %s", element, element->name);
1008 if (!device->driver)
1011 device_disable(device);
1013 unregister_interface(element);
1015 if (device->driver->remove)
1016 device->driver->remove(device);
1019 static struct connman_driver device_driver = {
1021 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
1022 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
1023 .probe = device_probe,
1024 .remove = device_remove,
1027 int __connman_device_init(void)
1031 connection = connman_dbus_get_connection();
1033 return connman_driver_register(&device_driver);
1036 void __connman_device_cleanup(void)
1040 connman_driver_unregister(&device_driver);
1042 dbus_connection_unref(connection);