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;
541 device->element.device = device;
542 device->element.destruct = device_destruct;
545 device->mode = CONNMAN_DEVICE_MODE_NO_NETWORK;
546 device->policy = CONNMAN_DEVICE_POLICY_AUTO;
548 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
549 g_free, unregister_network);
555 * connman_device_ref:
556 * @device: device structure
558 * Increase reference counter of device
560 struct connman_device *connman_device_ref(struct connman_device *device)
562 if (connman_element_ref(&device->element) == NULL)
569 * connman_device_unref:
570 * @device: device structure
572 * Decrease reference counter of device
574 void connman_device_unref(struct connman_device *device)
576 connman_element_unref(&device->element);
580 * connman_device_set_path:
581 * @device: device structure
584 * Set path name of device
586 void connman_device_set_path(struct connman_device *device, const char *path)
588 g_free(device->element.devpath);
589 device->element.devpath = g_strdup(path);
591 g_free(device->path);
592 device->path = g_strdup(path);
596 * connman_device_get_path:
597 * @device: device structure
599 * Get path name of device
601 const char *connman_device_get_path(struct connman_device *device)
607 * connman_device_set_index:
608 * @device: device structure
609 * @index: index number
611 * Set index number of device
613 void connman_device_set_index(struct connman_device *device, int index)
615 device->element.index = index;
619 * connman_device_get_index:
620 * @device: device structure
622 * Get index number of device
624 int connman_device_get_index(struct connman_device *device)
626 return device->element.index;
630 * connman_device_set_interface:
631 * @device: device structure
632 * @interface: interface name
634 * Set interface name of device
636 void connman_device_set_interface(struct connman_device *device,
637 const char *interface)
639 g_free(device->element.devname);
640 device->element.devname = g_strdup(interface);
642 g_free(device->interface);
643 device->interface = g_strdup(interface);
647 * connman_device_get_interface:
648 * @device: device structure
650 * Get interface name of device
652 const char *connman_device_get_interface(struct connman_device *device)
654 return device->interface;
658 * connman_device_set_policy:
659 * @device: device structure
660 * @policy: power and connection policy
662 * Change power and connection policy of device
664 void connman_device_set_policy(struct connman_device *device,
665 enum connman_device_policy policy)
667 device->policy = policy;
671 * connman_device_set_mode:
672 * @device: device structure
673 * @mode: network mode
675 * Change network mode of device
677 void connman_device_set_mode(struct connman_device *device,
678 enum connman_device_mode mode)
684 * connman_device_set_powered:
685 * @device: device structure
686 * @powered: powered state
688 * Change power state of device
690 int connman_device_set_powered(struct connman_device *device,
694 DBusMessageIter entry, value;
695 const char *key = "Powered";
697 DBG("driver %p powered %d", device, powered);
699 if (device->powered == powered)
702 device->powered = powered;
704 signal = dbus_message_new_signal(device->element.path,
705 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
709 dbus_message_iter_init_append(signal, &entry);
711 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
713 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
714 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
715 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
716 dbus_message_iter_close_container(&entry, &value);
718 g_dbus_send_message(connection, signal);
724 * connman_device_set_carrier:
725 * @device: device structure
726 * @carrier: carrier state
728 * Change carrier state of device (only for device without scanning)
730 int connman_device_set_carrier(struct connman_device *device,
733 DBG("driver %p carrier %d", device, carrier);
735 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK)
738 if (device->carrier == carrier)
741 device->carrier = carrier;
743 if (carrier == TRUE) {
744 struct connman_element *element;
746 element = connman_element_create(NULL);
747 if (element != NULL) {
748 element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
749 element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
750 element->index = device->element.index;
752 if (connman_element_register(element,
753 &device->element) < 0)
754 connman_element_unref(element);
757 connman_element_unregister_children(&device->element);
763 * connman_device_set_scanning:
764 * @device: device structure
765 * @scanning: scanning state
767 * Change scanning state of device
769 int connman_device_set_scanning(struct connman_device *device,
773 DBusMessageIter entry, value;
774 const char *key = "Scanning";
776 DBG("driver %p scanning %d", device, scanning);
778 if (!device->driver || !device->driver->scan)
781 if (device->scanning == scanning)
784 device->scanning = scanning;
786 signal = dbus_message_new_signal(device->element.path,
787 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
791 dbus_message_iter_init_append(signal, &entry);
793 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
795 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
796 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
797 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
798 dbus_message_iter_close_container(&entry, &value);
800 g_dbus_send_message(connection, signal);
806 * connman_device_add_network:
807 * @device: device structure
808 * @network: network structure
810 * Add new network to the device
812 int connman_device_add_network(struct connman_device *device,
813 struct connman_network *network)
815 const char *identifier = connman_network_get_identifier(network);
818 DBG("device %p network %p", device, network);
820 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
823 err = connman_element_register((struct connman_element *) network,
828 g_hash_table_insert(device->networks, g_strdup(identifier),
835 * connman_device_get_network:
836 * @device: device structure
837 * @identifier: network identifier
839 * Get network for given identifier
841 struct connman_network *connman_device_get_network(struct connman_device *device,
842 const char *identifier)
844 DBG("device %p identifier %s", device, identifier);
846 return g_hash_table_lookup(device->networks, identifier);
850 * connman_device_remove_network:
851 * @device: device structure
852 * @identifier: network identifier
854 * Remove network for given identifier
856 int connman_device_remove_network(struct connman_device *device,
857 const char *identifier)
859 DBG("device %p identifier %s", device, identifier);
861 g_hash_table_remove(device->networks, identifier);
867 * connman_device_register:
868 * @device: device structure
870 * Register device with the system
872 int connman_device_register(struct connman_device *device)
874 return connman_element_register(&device->element, NULL);
878 * connman_device_unregister:
879 * @device: device structure
881 * Unregister device with the system
883 void connman_device_unregister(struct connman_device *device)
885 connman_element_unregister(&device->element);
889 * connman_device_get_data:
890 * @device: device structure
892 * Get private device data pointer
894 void *connman_device_get_data(struct connman_device *device)
896 return device->driver_data;
900 * connman_device_set_data:
901 * @device: device structure
902 * @data: data pointer
904 * Set private device data pointer
906 void connman_device_set_data(struct connman_device *device, void *data)
908 device->driver_data = data;
911 static void device_enable(struct connman_device *device)
913 DBG("device %p", device);
915 if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE ||
916 device->policy == CONNMAN_DEVICE_POLICY_OFF)
919 if (device->powered == TRUE)
922 if (device->driver->enable)
923 device->driver->enable(device);
926 static void device_disable(struct connman_device *device)
928 DBG("device %p", device);
930 if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE)
933 if (device->powered == FALSE)
936 if (device->driver->disable)
937 device->driver->disable(device);
940 static gboolean match_driver(struct connman_device *device,
941 struct connman_device_driver *driver)
943 if (device->type == driver->type ||
944 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
950 static int device_probe(struct connman_element *element)
952 struct connman_device *device = element->device;
956 DBG("element %p name %s", element, element->name);
961 for (list = driver_list; list; list = list->next) {
962 struct connman_device_driver *driver = list->data;
964 if (match_driver(device, driver) == FALSE)
967 DBG("driver %p name %s", driver, driver->name);
969 if (driver->probe(device) == 0) {
970 device->driver = driver;
978 err = register_interface(element);
980 if (device->driver->remove)
981 device->driver->remove(device);
985 device_enable(device);
990 static void device_remove(struct connman_element *element)
992 struct connman_device *device = element->device;
994 DBG("element %p name %s", element, element->name);
1002 device_disable(device);
1004 unregister_interface(element);
1006 if (device->driver->remove)
1007 device->driver->remove(device);
1010 static struct connman_driver device_driver = {
1012 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
1013 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
1014 .probe = device_probe,
1015 .remove = device_remove,
1018 int __connman_device_init(void)
1022 connection = connman_dbus_get_connection();
1024 return connman_driver_register(&device_driver);
1027 void __connman_device_cleanup(void)
1031 connman_driver_unregister(&device_driver);
1033 dbus_connection_unref(connection);