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_MODEM:
77 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
79 case CONNMAN_DEVICE_TYPE_HSO:
86 static const char *policy2string(enum connman_device_policy policy)
89 case CONNMAN_DEVICE_POLICY_IGNORE:
91 case CONNMAN_DEVICE_POLICY_AUTO:
93 case CONNMAN_DEVICE_POLICY_OFF:
100 static int set_powered(struct connman_device *device, gboolean powered)
102 struct connman_device_driver *driver = device->driver;
105 DBG("device %p powered %d", device, powered);
110 if (powered == TRUE) {
112 err = driver->enable(device);
117 err = driver->disable(device);
125 static void append_networks(struct connman_device *device,
126 DBusMessageIter *entry)
128 DBusMessageIter value, iter;
129 const char *key = "Networks";
131 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
133 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
134 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
137 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
138 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
139 __connman_element_list((struct connman_element *) device,
140 CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
141 dbus_message_iter_close_container(&value, &iter);
143 dbus_message_iter_close_container(entry, &value);
146 static DBusMessage *get_properties(DBusConnection *conn,
147 DBusMessage *msg, void *data)
149 struct connman_device *device = data;
151 DBusMessageIter array, dict, entry;
154 DBG("conn %p", conn);
156 reply = dbus_message_new_method_return(msg);
160 dbus_message_iter_init_append(reply, &array);
162 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
163 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
164 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
165 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
167 str = type2description(device->type);
168 if (str != NULL && device->interface != NULL) {
169 char *name = g_strdup_printf("%s (%s)", str, device->interface);
171 connman_dbus_dict_append_variant(&dict, "Name",
172 DBUS_TYPE_STRING, &name);
176 str = type2string(device->type);
178 connman_dbus_dict_append_variant(&dict, "Type",
179 DBUS_TYPE_STRING, &str);
181 if (device->interface != NULL)
182 connman_dbus_dict_append_variant(&dict, "Interface",
183 DBUS_TYPE_STRING, &device->interface);
185 str = policy2string(device->policy);
187 connman_dbus_dict_append_variant(&dict, "Policy",
188 DBUS_TYPE_STRING, &str);
190 connman_dbus_dict_append_variant(&dict, "Powered",
191 DBUS_TYPE_BOOLEAN, &device->powered);
193 if (device->driver && device->driver->scan)
194 connman_dbus_dict_append_variant(&dict, "Scanning",
195 DBUS_TYPE_BOOLEAN, &device->scanning);
197 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK) {
198 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
200 append_networks(device, &entry);
201 dbus_message_iter_close_container(&dict, &entry);
204 dbus_message_iter_close_container(&array, &dict);
209 static DBusMessage *set_property(DBusConnection *conn,
210 DBusMessage *msg, void *data)
212 struct connman_device *device = data;
213 DBusMessageIter iter, value;
216 DBG("conn %p", conn);
218 if (dbus_message_iter_init(msg, &iter) == FALSE)
219 return __connman_error_invalid_arguments(msg);
221 dbus_message_iter_get_basic(&iter, &name);
222 dbus_message_iter_next(&iter);
223 dbus_message_iter_recurse(&iter, &value);
225 if (__connman_security_check_privileges(msg) < 0)
226 return __connman_error_permission_denied(msg);
228 if (g_str_equal(name, "Powered") == TRUE) {
232 dbus_message_iter_get_basic(&value, &powered);
234 if (device->powered == powered)
235 return __connman_error_invalid_arguments(msg);
237 err = set_powered(device, powered);
238 if (err < 0 && err != -EINPROGRESS)
239 return __connman_error_failed(msg);
242 __connman_element_store(&device->element);
244 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
247 static DBusMessage *create_network(DBusConnection *conn,
248 DBusMessage *msg, void *data)
250 DBG("conn %p", conn);
252 if (__connman_security_check_privileges(msg) < 0)
253 return __connman_error_permission_denied(msg);
255 return __connman_error_invalid_arguments(msg);
258 static DBusMessage *remove_network(DBusConnection *conn,
259 DBusMessage *msg, void *data)
261 DBG("conn %p", conn);
263 if (__connman_security_check_privileges(msg) < 0)
264 return __connman_error_permission_denied(msg);
266 return __connman_error_invalid_arguments(msg);
269 static DBusMessage *propose_scan(DBusConnection *conn,
270 DBusMessage *msg, void *data)
272 struct connman_device *device = data;
275 DBG("conn %p", conn);
277 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
278 return __connman_error_not_supported(msg);
280 if (!device->driver || !device->driver->scan)
281 return __connman_error_not_supported(msg);
283 err = device->driver->scan(device);
285 return __connman_error_failed(msg);
287 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
290 static GDBusMethodTable device_methods[] = {
291 { "GetProperties", "", "a{sv}", get_properties },
292 { "SetProperty", "sv", "", set_property },
293 { "CreateNetwork", "a{sv}", "o", create_network },
294 { "RemoveNetwork", "o", "", remove_network },
295 { "ProposeScan", "", "", propose_scan },
299 static GDBusSignalTable device_signals[] = {
300 { "PropertyChanged", "sv" },
304 static DBusConnection *connection;
306 static void append_devices(DBusMessageIter *entry)
308 DBusMessageIter value, iter;
309 const char *key = "Devices";
311 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
313 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
314 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
317 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
318 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
319 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
320 dbus_message_iter_close_container(&value, &iter);
322 dbus_message_iter_close_container(entry, &value);
325 static void emit_devices_signal(void)
328 DBusMessageIter entry;
330 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
331 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
335 dbus_message_iter_init_append(signal, &entry);
337 append_devices(&entry);
339 g_dbus_send_message(connection, signal);
342 static int register_interface(struct connman_element *element)
344 struct connman_device *device = element->device;
346 if (g_dbus_register_interface(connection, element->path,
347 CONNMAN_DEVICE_INTERFACE,
348 device_methods, device_signals,
349 NULL, device, NULL) == FALSE) {
350 connman_error("Failed to register %s device", element->path);
354 emit_devices_signal();
359 static void unregister_interface(struct connman_element *element)
361 emit_devices_signal();
363 g_dbus_unregister_interface(connection, element->path,
364 CONNMAN_DEVICE_INTERFACE);
367 static GSList *driver_list = NULL;
369 static gint compare_priority(gconstpointer a, gconstpointer b)
371 const struct connman_device_driver *driver1 = a;
372 const struct connman_device_driver *driver2 = b;
374 return driver2->priority - driver1->priority;
378 * connman_device_driver_register:
379 * @driver: device driver definition
381 * Register a new device driver
383 * Returns: %0 on success
385 int connman_device_driver_register(struct connman_device_driver *driver)
387 DBG("driver %p name %s", driver, driver->name);
389 driver_list = g_slist_insert_sorted(driver_list, driver,
392 //__connman_driver_rescan(&device_driver);
398 * connman_device_driver_unregister:
399 * @driver: device driver definition
401 * Remove a previously registered device driver
403 void connman_device_driver_unregister(struct connman_device_driver *driver)
405 DBG("driver %p name %s", driver, driver->name);
407 driver_list = g_slist_remove(driver_list, driver);
410 static void unregister_network(gpointer data)
412 struct connman_network *network = data;
414 DBG("network %p", network);
416 connman_element_unregister((struct connman_element *) network);
418 connman_network_unref(network);
421 static void device_destruct(struct connman_element *element)
423 struct connman_device *device = element->device;
425 DBG("element %p name %s", element, element->name);
427 g_free(device->interface);
429 g_hash_table_destroy(device->networks);
433 * connman_device_create:
434 * @node: device node name (for example an address)
437 * Allocate a new device of given #type and assign the #node name to it.
439 * Returns: a newly-allocated #connman_device structure
441 struct connman_device *connman_device_create(const char *node,
442 enum connman_device_type type)
444 struct connman_device *device;
446 DBG("node %s type %d", node, type);
448 device = g_try_new0(struct connman_device, 1);
452 DBG("device %p", device);
454 device->element.refcount = 1;
456 device->element.name = g_strdup(node);
457 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
458 device->element.index = -1;
460 device->element.device = device;
461 device->element.destruct = device_destruct;
464 device->mode = CONNMAN_DEVICE_MODE_NO_NETWORK;
465 device->policy = CONNMAN_DEVICE_POLICY_AUTO;
467 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
468 g_free, unregister_network);
474 * connman_device_ref:
475 * @device: device structure
477 * Increase reference counter of device
479 struct connman_device *connman_device_ref(struct connman_device *device)
481 if (connman_element_ref(&device->element) == NULL)
488 * connman_device_unref:
489 * @device: device structure
491 * Decrease reference counter of device
493 void connman_device_unref(struct connman_device *device)
495 connman_element_unref(&device->element);
499 * connman_device_set_path:
500 * @device: device structure
503 * Set path name of device
505 void connman_device_set_path(struct connman_device *device, const char *path)
507 g_free(device->element.devpath);
508 device->element.devpath = g_strdup(path);
510 g_free(device->path);
511 device->path = g_strdup(path);
515 * connman_device_get_path:
516 * @device: device structure
518 * Get path name of device
520 const char *connman_device_get_path(struct connman_device *device)
526 * connman_device_set_index:
527 * @device: device structure
528 * @index: index number
530 * Set index number of device
532 void connman_device_set_index(struct connman_device *device, int index)
534 device->element.index = index;
538 * connman_device_get_index:
539 * @device: device structure
541 * Get index number of device
543 int connman_device_get_index(struct connman_device *device)
545 return device->element.index;
549 * connman_device_set_interface:
550 * @device: device structure
551 * @interface: interface name
553 * Set interface name of device
555 void connman_device_set_interface(struct connman_device *device,
556 const char *interface)
558 g_free(device->element.devname);
559 device->element.devname = g_strdup(interface);
561 g_free(device->interface);
562 device->interface = g_strdup(interface);
566 * connman_device_get_interface:
567 * @device: device structure
569 * Get interface name of device
571 const char *connman_device_get_interface(struct connman_device *device)
573 return device->interface;
577 * connman_device_set_mode:
578 * @device: device structure
579 * @mode: network mode
581 * Change network mode of device
583 void connman_device_set_mode(struct connman_device *device,
584 enum connman_device_mode mode)
590 * connman_device_set_powered:
591 * @device: device structure
592 * @powered: powered state
594 * Change power state of device
596 int connman_device_set_powered(struct connman_device *device,
600 DBusMessageIter entry, value;
601 const char *key = "Powered";
603 DBG("driver %p powered %d", device, powered);
605 if (device->powered == powered)
608 device->powered = powered;
610 signal = dbus_message_new_signal(device->element.path,
611 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
615 dbus_message_iter_init_append(signal, &entry);
617 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
619 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
620 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
621 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
622 dbus_message_iter_close_container(&entry, &value);
624 g_dbus_send_message(connection, signal);
630 * connman_device_set_carrier:
631 * @device: device structure
632 * @carrier: carrier state
634 * Change carrier state of device (only for device without scanning)
636 int connman_device_set_carrier(struct connman_device *device,
639 DBG("driver %p carrier %d", device, carrier);
641 if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK)
644 if (device->carrier == carrier)
647 device->carrier = carrier;
649 if (carrier == TRUE) {
650 struct connman_element *element;
652 element = connman_element_create(NULL);
653 if (element != NULL) {
654 element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
655 element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
656 element->index = device->element.index;
658 if (connman_element_register(element,
659 &device->element) < 0)
660 connman_element_unref(element);
663 connman_element_unregister_children(&device->element);
669 * connman_device_set_scanning:
670 * @device: device structure
671 * @scanning: scanning state
673 * Change scanning state of device
675 int connman_device_set_scanning(struct connman_device *device,
679 DBusMessageIter entry, value;
680 const char *key = "Scanning";
682 DBG("driver %p scanning %d", device, scanning);
684 if (!device->driver || !device->driver->scan)
687 if (device->scanning == scanning)
690 device->scanning = scanning;
692 signal = dbus_message_new_signal(device->element.path,
693 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
697 dbus_message_iter_init_append(signal, &entry);
699 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
701 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
702 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
703 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
704 dbus_message_iter_close_container(&entry, &value);
706 g_dbus_send_message(connection, signal);
712 * connman_device_add_network:
713 * @device: device structure
714 * @network: network structure
716 * Add new network to the device
718 int connman_device_add_network(struct connman_device *device,
719 struct connman_network *network)
721 const char *identifier = connman_network_get_identifier(network);
724 DBG("device %p network %p", device, network);
726 if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
729 err = connman_element_register((struct connman_element *) network,
734 g_hash_table_insert(device->networks, g_strdup(identifier),
741 * connman_device_get_network:
742 * @device: device structure
743 * @identifier: network identifier
745 * Get network for given identifier
747 struct connman_network *connman_device_get_network(struct connman_device *device,
748 const char *identifier)
750 DBG("device %p identifier %s", device, identifier);
752 return g_hash_table_lookup(device->networks, identifier);
756 * connman_device_remove_network:
757 * @device: device structure
758 * @identifier: network identifier
760 * Remove network for given identifier
762 int connman_device_remove_network(struct connman_device *device,
763 const char *identifier)
765 DBG("device %p identifier %s", device, identifier);
767 g_hash_table_remove(device->networks, identifier);
773 * connman_device_register:
774 * @device: device structure
776 * Register device with the system
778 int connman_device_register(struct connman_device *device)
780 return connman_element_register(&device->element, NULL);
784 * connman_device_unregister:
785 * @device: device structure
787 * Unregister device with the system
789 void connman_device_unregister(struct connman_device *device)
791 connman_element_unregister(&device->element);
795 * connman_device_get_data:
796 * @device: device structure
798 * Get private device data pointer
800 void *connman_device_get_data(struct connman_device *device)
802 return device->driver_data;
806 * connman_device_set_data:
807 * @device: device structure
808 * @data: data pointer
810 * Set private device data pointer
812 void connman_device_set_data(struct connman_device *device, void *data)
814 device->driver_data = data;
817 static void device_enable(struct connman_device *device)
819 DBG("device %p", device);
821 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
824 if (device->powered == TRUE)
827 if (device->driver->enable)
828 device->driver->enable(device);
831 static void device_disable(struct connman_device *device)
833 DBG("device %p", device);
835 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
838 if (device->powered == FALSE)
841 if (device->driver->disable)
842 device->driver->disable(device);
845 static gboolean match_driver(struct connman_device *device,
846 struct connman_device_driver *driver)
848 if (device->type == driver->type ||
849 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
855 static int device_probe(struct connman_element *element)
857 struct connman_device *device = element->device;
861 DBG("element %p name %s", element, element->name);
866 for (list = driver_list; list; list = list->next) {
867 struct connman_device_driver *driver = list->data;
869 if (match_driver(device, driver) == FALSE)
872 DBG("driver %p name %s", driver, driver->name);
874 if (driver->probe(device) == 0) {
875 device->driver = driver;
883 err = register_interface(element);
885 if (device->driver->remove)
886 device->driver->remove(device);
890 device_enable(device);
895 static void device_remove(struct connman_element *element)
897 struct connman_device *device = element->device;
899 DBG("element %p name %s", element, element->name);
907 device_disable(device);
909 unregister_interface(element);
911 if (device->driver->remove)
912 device->driver->remove(device);
915 static struct connman_driver device_driver = {
917 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
918 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
919 .probe = device_probe,
920 .remove = device_remove,
923 int __connman_device_init(void)
927 connection = connman_dbus_get_connection();
929 return connman_driver_register(&device_driver);
932 void __connman_device_cleanup(void)
936 connman_driver_unregister(&device_driver);
938 dbus_connection_unref(connection);