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 __connman_element_list((struct connman_element *) device,
136 CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
137 dbus_message_iter_close_container(&value, &iter);
139 dbus_message_iter_close_container(entry, &value);
142 static DBusMessage *get_properties(DBusConnection *conn,
143 DBusMessage *msg, void *data)
145 struct connman_device *device = data;
147 DBusMessageIter array, dict, entry;
150 DBG("conn %p", conn);
152 reply = dbus_message_new_method_return(msg);
156 dbus_message_iter_init_append(reply, &array);
158 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
159 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
160 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
161 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
163 str = type2description(device->type);
164 if (str != NULL && device->interface != NULL) {
165 char *name = g_strdup_printf("%s (%s)", str, device->interface);
167 connman_dbus_dict_append_variant(&dict, "Name",
168 DBUS_TYPE_STRING, &name);
172 str = type2string(device->type);
174 connman_dbus_dict_append_variant(&dict, "Type",
175 DBUS_TYPE_STRING, &str);
177 if (device->interface != NULL)
178 connman_dbus_dict_append_variant(&dict, "Interface",
179 DBUS_TYPE_STRING, &device->interface);
181 str = policy2string(device->policy);
183 connman_dbus_dict_append_variant(&dict, "Policy",
184 DBUS_TYPE_STRING, &str);
186 connman_dbus_dict_append_variant(&dict, "Powered",
187 DBUS_TYPE_BOOLEAN, &device->powered);
189 if (device->driver && device->driver->scan)
190 connman_dbus_dict_append_variant(&dict, "Scanning",
191 DBUS_TYPE_BOOLEAN, &device->scanning);
193 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK) {
194 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
196 append_networks(device, &entry);
197 dbus_message_iter_close_container(&dict, &entry);
200 dbus_message_iter_close_container(&array, &dict);
205 static DBusMessage *set_property(DBusConnection *conn,
206 DBusMessage *msg, void *data)
208 struct connman_device *device = data;
209 DBusMessageIter iter, value;
212 DBG("conn %p", conn);
214 if (dbus_message_iter_init(msg, &iter) == FALSE)
215 return __connman_error_invalid_arguments(msg);
217 dbus_message_iter_get_basic(&iter, &name);
218 dbus_message_iter_next(&iter);
219 dbus_message_iter_recurse(&iter, &value);
221 if (__connman_security_check_privileges(msg) < 0)
222 return __connman_error_permission_denied(msg);
224 if (g_str_equal(name, "Powered") == TRUE) {
228 dbus_message_iter_get_basic(&value, &powered);
230 if (device->powered == powered)
231 return __connman_error_invalid_arguments(msg);
233 err = set_powered(device, powered);
234 if (err < 0 && err != -EINPROGRESS)
235 return __connman_error_failed(msg);
238 __connman_element_store(&device->element);
240 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
243 static DBusMessage *create_network(DBusConnection *conn,
244 DBusMessage *msg, void *data)
246 DBG("conn %p", conn);
248 if (__connman_security_check_privileges(msg) < 0)
249 return __connman_error_permission_denied(msg);
251 return __connman_error_invalid_arguments(msg);
254 static DBusMessage *remove_network(DBusConnection *conn,
255 DBusMessage *msg, void *data)
257 DBG("conn %p", conn);
259 if (__connman_security_check_privileges(msg) < 0)
260 return __connman_error_permission_denied(msg);
262 return __connman_error_invalid_arguments(msg);
265 static DBusMessage *propose_scan(DBusConnection *conn,
266 DBusMessage *msg, void *data)
268 struct connman_device *device = data;
271 DBG("conn %p", conn);
273 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
274 return __connman_error_not_supported(msg);
276 if (!device->driver || !device->driver->scan)
277 return __connman_error_not_supported(msg);
279 err = device->driver->scan(device);
281 return __connman_error_failed(msg);
283 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
286 static GDBusMethodTable device_methods[] = {
287 { "GetProperties", "", "a{sv}", get_properties },
288 { "SetProperty", "sv", "", set_property },
289 { "CreateNetwork", "a{sv}", "o", create_network },
290 { "RemoveNetwork", "o", "", remove_network },
291 { "ProposeScan", "", "", propose_scan },
295 static GDBusSignalTable device_signals[] = {
296 { "PropertyChanged", "sv" },
300 static DBusConnection *connection;
302 static void append_devices(DBusMessageIter *entry)
304 DBusMessageIter value, iter;
305 const char *key = "Devices";
307 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
309 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
310 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
313 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
314 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
315 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
316 dbus_message_iter_close_container(&value, &iter);
318 dbus_message_iter_close_container(entry, &value);
321 static void emit_devices_signal(void)
324 DBusMessageIter entry;
326 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
327 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
331 dbus_message_iter_init_append(signal, &entry);
333 append_devices(&entry);
335 g_dbus_send_message(connection, signal);
338 static int register_interface(struct connman_element *element)
340 struct connman_device *device = element->device;
342 if (g_dbus_register_interface(connection, element->path,
343 CONNMAN_DEVICE_INTERFACE,
344 device_methods, device_signals,
345 NULL, device, NULL) == FALSE) {
346 connman_error("Failed to register %s device", element->path);
350 emit_devices_signal();
355 static void unregister_interface(struct connman_element *element)
357 emit_devices_signal();
359 g_dbus_unregister_interface(connection, element->path,
360 CONNMAN_DEVICE_INTERFACE);
363 static GSList *driver_list = NULL;
365 static gint compare_priority(gconstpointer a, gconstpointer b)
367 const struct connman_device_driver *driver1 = a;
368 const struct connman_device_driver *driver2 = b;
370 return driver2->priority - driver1->priority;
374 * connman_device_driver_register:
375 * @driver: device driver definition
377 * Register a new device driver
379 * Returns: %0 on success
381 int connman_device_driver_register(struct connman_device_driver *driver)
383 DBG("driver %p name %s", driver, driver->name);
385 driver_list = g_slist_insert_sorted(driver_list, driver,
388 //__connman_driver_rescan(&device_driver);
394 * connman_device_driver_unregister:
395 * @driver: device driver definition
397 * Remove a previously registered device driver
399 void connman_device_driver_unregister(struct connman_device_driver *driver)
401 DBG("driver %p name %s", driver, driver->name);
403 driver_list = g_slist_remove(driver_list, driver);
406 static void unregister_network(gpointer data)
408 struct connman_network *network = data;
410 DBG("network %p", network);
412 connman_element_unregister((struct connman_element *) network);
414 connman_network_unref(network);
417 static void device_destruct(struct connman_element *element)
419 struct connman_device *device = element->device;
421 DBG("element %p name %s", element, element->name);
423 g_free(device->interface);
425 g_hash_table_destroy(device->networks);
429 * connman_device_create:
430 * @node: device node name (for example an address)
433 * Allocate a new device of given #type and assign the #node name to it.
435 * Returns: a newly-allocated #connman_device structure
437 struct connman_device *connman_device_create(const char *node,
438 enum connman_device_type type)
440 struct connman_device *device;
442 DBG("node %s type %d", node, type);
444 device = g_try_new0(struct connman_device, 1);
448 DBG("device %p", device);
450 device->element.refcount = 1;
452 device->element.name = g_strdup(node);
453 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
454 device->element.index = -1;
456 device->element.device = device;
457 device->element.destruct = device_destruct;
460 device->mode = CONNMAN_DEVICE_MODE_NO_NETWORK;
461 device->policy = CONNMAN_DEVICE_POLICY_AUTO;
463 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
464 g_free, unregister_network);
470 * connman_device_ref:
471 * @device: device structure
473 * Increase reference counter of device
475 struct connman_device *connman_device_ref(struct connman_device *device)
477 if (connman_element_ref(&device->element) == NULL)
484 * connman_device_unref:
485 * @device: device structure
487 * Decrease reference counter of device
489 void connman_device_unref(struct connman_device *device)
491 connman_element_unref(&device->element);
495 * connman_device_set_path:
496 * @device: device structure
499 * Set path name of device
501 void connman_device_set_path(struct connman_device *device, const char *path)
503 g_free(device->element.devpath);
504 device->element.devpath = g_strdup(path);
506 g_free(device->path);
507 device->path = g_strdup(path);
511 * connman_device_get_path:
512 * @device: device structure
514 * Get path name of device
516 const char *connman_device_get_path(struct connman_device *device)
522 * connman_device_set_index:
523 * @device: device structure
524 * @index: index number
526 * Set index number of device
528 void connman_device_set_index(struct connman_device *device, int index)
530 device->element.index = index;
534 * connman_device_get_index:
535 * @device: device structure
537 * Get index number of device
539 int connman_device_get_index(struct connman_device *device)
541 return device->element.index;
545 * connman_device_set_interface:
546 * @device: device structure
547 * @interface: interface name
549 * Set interface name of device
551 void connman_device_set_interface(struct connman_device *device,
552 const char *interface)
554 g_free(device->element.devname);
555 device->element.devname = g_strdup(interface);
557 g_free(device->interface);
558 device->interface = g_strdup(interface);
562 * connman_device_get_interface:
563 * @device: device structure
565 * Get interface name of device
567 const char *connman_device_get_interface(struct connman_device *device)
569 return device->interface;
573 * connman_device_set_mode:
574 * @device: device structure
575 * @mode: network mode
577 * Change network mode of device
579 void connman_device_set_mode(struct connman_device *device,
580 enum connman_device_mode mode)
586 * connman_device_set_powered:
587 * @device: device structure
588 * @powered: powered state
590 * Change power state of device
592 int connman_device_set_powered(struct connman_device *device,
596 DBusMessageIter entry, value;
597 const char *key = "Powered";
599 DBG("driver %p powered %d", device, powered);
601 if (device->powered == powered)
604 device->powered = powered;
606 signal = dbus_message_new_signal(device->element.path,
607 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
611 dbus_message_iter_init_append(signal, &entry);
613 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
615 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
616 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
617 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
618 dbus_message_iter_close_container(&entry, &value);
620 g_dbus_send_message(connection, signal);
626 * connman_device_set_carrier:
627 * @device: device structure
628 * @carrier: carrier state
630 * Change carrier state of device (only for device without scanning)
632 int connman_device_set_carrier(struct connman_device *device,
635 DBG("driver %p carrier %d", device, carrier);
637 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK)
640 if (device->carrier == carrier)
643 device->carrier = carrier;
645 if (carrier == TRUE) {
646 struct connman_element *element;
648 element = connman_element_create(NULL);
649 if (element != NULL) {
650 element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
651 element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
652 element->index = device->element.index;
654 if (connman_element_register(element,
655 &device->element) < 0)
656 connman_element_unref(element);
659 connman_element_unregister_children(&device->element);
665 * connman_device_set_scanning:
666 * @device: device structure
667 * @scanning: scanning state
669 * Change scanning state of device
671 int connman_device_set_scanning(struct connman_device *device,
675 DBusMessageIter entry, value;
676 const char *key = "Scanning";
678 DBG("driver %p scanning %d", device, scanning);
680 if (!device->driver || !device->driver->scan)
683 if (device->scanning == scanning)
686 device->scanning = scanning;
688 signal = dbus_message_new_signal(device->element.path,
689 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
693 dbus_message_iter_init_append(signal, &entry);
695 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
697 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
698 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
699 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
700 dbus_message_iter_close_container(&entry, &value);
702 g_dbus_send_message(connection, signal);
708 * connman_device_add_network:
709 * @device: device structure
710 * @network: network structure
712 * Add new network to the device
714 int connman_device_add_network(struct connman_device *device,
715 struct connman_network *network)
717 const char *identifier = connman_network_get_identifier(network);
720 DBG("device %p network %p", device, network);
722 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
725 err = connman_element_register((struct connman_element *) network,
730 g_hash_table_insert(device->networks, g_strdup(identifier),
737 * connman_device_get_network:
738 * @device: device structure
739 * @identifier: network identifier
741 * Get network for given identifier
743 struct connman_network *connman_device_get_network(struct connman_device *device,
744 const char *identifier)
746 DBG("device %p identifier %s", device, identifier);
748 return g_hash_table_lookup(device->networks, identifier);
752 * connman_device_remove_network:
753 * @device: device structure
754 * @identifier: network identifier
756 * Remove network for given identifier
758 int connman_device_remove_network(struct connman_device *device,
759 const char *identifier)
761 DBG("device %p identifier %s", device, identifier);
763 g_hash_table_remove(device->networks, identifier);
769 * connman_device_register:
770 * @device: device structure
772 * Register device with the system
774 int connman_device_register(struct connman_device *device)
776 return connman_element_register(&device->element, NULL);
780 * connman_device_unregister:
781 * @device: device structure
783 * Unregister device with the system
785 void connman_device_unregister(struct connman_device *device)
787 connman_element_unregister(&device->element);
791 * connman_device_get_data:
792 * @device: device structure
794 * Get private device data pointer
796 void *connman_device_get_data(struct connman_device *device)
798 return device->driver_data;
802 * connman_device_set_data:
803 * @device: device structure
804 * @data: data pointer
806 * Set private device data pointer
808 void connman_device_set_data(struct connman_device *device, void *data)
810 device->driver_data = data;
813 static void device_enable(struct connman_device *device)
815 DBG("device %p", device);
817 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
820 if (device->powered == TRUE)
823 if (device->driver->enable)
824 device->driver->enable(device);
827 static void device_disable(struct connman_device *device)
829 DBG("device %p", device);
831 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
834 if (device->powered == FALSE)
837 if (device->driver->disable)
838 device->driver->disable(device);
841 static gboolean match_driver(struct connman_device *device,
842 struct connman_device_driver *driver)
844 if (device->type == driver->type ||
845 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
851 static int device_probe(struct connman_element *element)
853 struct connman_device *device = element->device;
857 DBG("element %p name %s", element, element->name);
862 for (list = driver_list; list; list = list->next) {
863 struct connman_device_driver *driver = list->data;
865 if (match_driver(device, driver) == FALSE)
868 DBG("driver %p name %s", driver, driver->name);
870 if (driver->probe(device) == 0) {
871 device->driver = driver;
879 err = register_interface(element);
881 if (device->driver->remove)
882 device->driver->remove(device);
886 device_enable(device);
891 static void device_remove(struct connman_element *element)
893 struct connman_device *device = element->device;
895 DBG("element %p name %s", element, element->name);
903 device_disable(device);
905 unregister_interface(element);
907 if (device->driver->remove)
908 device->driver->remove(device);
911 static struct connman_driver device_driver = {
913 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
914 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
915 .probe = device_probe,
916 .remove = device_remove,
919 int __connman_device_init(void)
923 connection = connman_dbus_get_connection();
925 return connman_driver_register(&device_driver);
928 void __connman_device_cleanup(void)
932 connman_driver_unregister(&device_driver);
934 dbus_connection_unref(connection);