Make use of connman_bool_t type
[connman] / src / device.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <gdbus.h>
28
29 #include "connman.h"
30
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;
36         gboolean powered;
37         gboolean carrier;
38         gboolean scanning;
39         char *path;
40         char *interface;
41
42         struct connman_device_driver *driver;
43         void *driver_data;
44
45         GHashTable *networks;
46 };
47
48 static const char *type2description(enum connman_device_type type)
49 {
50         switch (type) {
51         case CONNMAN_DEVICE_TYPE_ETHERNET:
52                 return "Ethernet";
53         case CONNMAN_DEVICE_TYPE_WIFI:
54                 return "Wireless";
55         case CONNMAN_DEVICE_TYPE_WIMAX:
56                 return "WiMAX";
57         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
58                 return "Bluetooth";
59         case CONNMAN_DEVICE_TYPE_HSO:
60                 return "Cellular";
61         default:
62                 return NULL;
63         }
64 }
65
66 static const char *type2string(enum connman_device_type type)
67 {
68         switch (type) {
69         case CONNMAN_DEVICE_TYPE_ETHERNET:
70                 return "ethernet";
71         case CONNMAN_DEVICE_TYPE_WIFI:
72                 return "wifi";
73         case CONNMAN_DEVICE_TYPE_WIMAX:
74                 return "wimax";
75         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
76                 return "bluetooth";
77         case CONNMAN_DEVICE_TYPE_HSO:
78                 return "cellular";
79         default:
80                 return NULL;
81         }
82 }
83
84 static const char *policy2string(enum connman_device_policy policy)
85 {
86         switch (policy) {
87         case CONNMAN_DEVICE_POLICY_IGNORE:
88                 return "ignore";
89         case CONNMAN_DEVICE_POLICY_OFF:
90                 return "off";
91         case CONNMAN_DEVICE_POLICY_AUTO:
92                 return "auto";
93         case CONNMAN_DEVICE_POLICY_MANUAL:
94                 return "manual";
95         default:
96                 return NULL;
97         }
98 }
99
100 static enum connman_device_policy string2policy(const char *policy)
101 {
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;
110         else
111                 return CONNMAN_DEVICE_POLICY_UNKNOWN;
112 }
113
114 static int set_powered(struct connman_device *device, gboolean powered)
115 {
116         struct connman_device_driver *driver = device->driver;
117         int err;
118
119         DBG("device %p powered %d", device, powered);
120
121         if (!driver)
122                 return -EINVAL;
123
124         if (powered == TRUE) {
125                 if (driver->enable)
126                         err = driver->enable(device);
127                 else
128                         err = -EINVAL;
129         } else {
130                 g_hash_table_remove_all(device->networks);
131
132                 if (driver->disable)
133                         err = driver->disable(device);
134                 else
135                         err = -EINVAL;
136         }
137
138         return err;
139 }
140
141 static int set_policy(DBusConnection *connection,
142                                 struct connman_device *device,
143                                         enum connman_device_policy policy)
144 {
145         DBusMessage *signal;
146         DBusMessageIter entry, value;
147         const char *str, *key = "Policy";
148         int err = 0;
149
150         DBG("device %p policy %d", device, policy);
151
152         if (device->policy == policy)
153                 return 0;
154
155         switch (policy) {
156         case CONNMAN_DEVICE_POLICY_OFF:
157                 if (device->powered == TRUE)
158                         err = set_powered(device, FALSE);
159                 break;
160         case CONNMAN_DEVICE_POLICY_AUTO:
161         case CONNMAN_DEVICE_POLICY_MANUAL:
162                 if (device->powered == FALSE)
163                         err = set_powered(device, TRUE);
164                 break;
165         default:
166                 break;
167         }
168
169         if (err < 0)
170                 return err;
171
172         device->policy = policy;
173
174         signal = dbus_message_new_signal(device->element.path,
175                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
176         if (signal == NULL)
177                 return 0;
178
179         dbus_message_iter_init_append(signal, &entry);
180
181         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
182
183         str = policy2string(policy);
184
185         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
186                                         DBUS_TYPE_STRING_AS_STRING, &value);
187         dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
188         dbus_message_iter_close_container(&entry, &value);
189
190         g_dbus_send_message(connection, signal);
191
192         return 0;
193 }
194
195 static void append_networks(struct connman_device *device,
196                                                 DBusMessageIter *entry)
197 {
198         DBusMessageIter value, iter;
199         const char *key = "Networks";
200
201         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
202
203         dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
204                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
205                                                                 &value);
206
207         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
208                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
209         __connman_element_list((struct connman_element *) device,
210                                         CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
211         dbus_message_iter_close_container(&value, &iter);
212
213         dbus_message_iter_close_container(entry, &value);
214 }
215
216 static DBusMessage *get_properties(DBusConnection *conn,
217                                         DBusMessage *msg, void *data)
218 {
219         struct connman_device *device = data;
220         DBusMessage *reply;
221         DBusMessageIter array, dict, entry;
222         const char *str;
223
224         DBG("conn %p", conn);
225
226         reply = dbus_message_new_method_return(msg);
227         if (reply == NULL)
228                 return NULL;
229
230         dbus_message_iter_init_append(reply, &array);
231
232         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
233                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
234                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
235                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
236
237         str = type2description(device->type);
238         if (str != NULL && device->interface != NULL) {
239                 char *name = g_strdup_printf("%s (%s)", str, device->interface);
240                 if (name != NULL)
241                         connman_dbus_dict_append_variant(&dict, "Name",
242                                                 DBUS_TYPE_STRING, &name);
243                 g_free(name);
244         }
245
246         str = type2string(device->type);
247         if (str != NULL)
248                 connman_dbus_dict_append_variant(&dict, "Type",
249                                                 DBUS_TYPE_STRING, &str);
250
251         if (device->interface != NULL)
252                 connman_dbus_dict_append_variant(&dict, "Interface",
253                                         DBUS_TYPE_STRING, &device->interface);
254
255         str = policy2string(device->policy);
256         if (str != NULL)
257                 connman_dbus_dict_append_variant(&dict, "Policy",
258                                                 DBUS_TYPE_STRING, &str);
259
260         connman_dbus_dict_append_variant(&dict, "Powered",
261                                         DBUS_TYPE_BOOLEAN, &device->powered);
262
263         if (device->driver && device->driver->scan)
264                 connman_dbus_dict_append_variant(&dict, "Scanning",
265                                         DBUS_TYPE_BOOLEAN, &device->scanning);
266
267         if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK) {
268                 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
269                                                                 NULL, &entry);
270                 append_networks(device, &entry);
271                 dbus_message_iter_close_container(&dict, &entry);
272         }
273
274         dbus_message_iter_close_container(&array, &dict);
275
276         return reply;
277 }
278
279 static DBusMessage *set_property(DBusConnection *conn,
280                                         DBusMessage *msg, void *data)
281 {
282         struct connman_device *device = data;
283         DBusMessageIter iter, value;
284         const char *name;
285
286         DBG("conn %p", conn);
287
288         if (dbus_message_iter_init(msg, &iter) == FALSE)
289                 return __connman_error_invalid_arguments(msg);
290
291         dbus_message_iter_get_basic(&iter, &name);
292         dbus_message_iter_next(&iter);
293         dbus_message_iter_recurse(&iter, &value);
294
295         if (__connman_security_check_privileges(msg) < 0)
296                 return __connman_error_permission_denied(msg);
297
298         if (g_str_equal(name, "Powered") == TRUE) {
299                 gboolean powered;
300                 int err;
301
302                 dbus_message_iter_get_basic(&value, &powered);
303
304                 if (device->powered == powered)
305                         return __connman_error_invalid_arguments(msg);
306
307                 err = set_powered(device, powered);
308                 if (err < 0 && err != -EINPROGRESS)
309                         return __connman_error_failed(msg);
310         } else if (g_str_equal(name, "Policy") == TRUE) {
311                 enum connman_device_policy policy;
312                 const char *str;
313                 int err;
314
315                 dbus_message_iter_get_basic(&value, &str);
316                 policy = string2policy(str);
317                 if (policy == CONNMAN_DEVICE_POLICY_UNKNOWN)
318                         return __connman_error_invalid_arguments(msg);
319
320                 err = set_policy(conn, device, policy);
321                 if (err < 0)
322                         return __connman_error_failed(msg);
323         }
324
325         __connman_element_store(&device->element);
326
327         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
328 }
329
330 static DBusMessage *create_network(DBusConnection *conn,
331                                         DBusMessage *msg, void *data)
332 {
333         DBG("conn %p", conn);
334
335         if (__connman_security_check_privileges(msg) < 0)
336                 return __connman_error_permission_denied(msg);
337
338         return __connman_error_invalid_arguments(msg);
339 }
340
341 static DBusMessage *remove_network(DBusConnection *conn,
342                                         DBusMessage *msg, void *data)
343 {
344         DBG("conn %p", conn);
345
346         if (__connman_security_check_privileges(msg) < 0)
347                 return __connman_error_permission_denied(msg);
348
349         return __connman_error_invalid_arguments(msg);
350 }
351
352 static DBusMessage *propose_scan(DBusConnection *conn,
353                                         DBusMessage *msg, void *data)
354 {
355         struct connman_device *device = data;
356         int err;
357
358         DBG("conn %p", conn);
359
360         if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
361                 return __connman_error_not_supported(msg);
362
363         if (!device->driver || !device->driver->scan)
364                 return __connman_error_not_supported(msg);
365
366         err = device->driver->scan(device);
367         if (err < 0)
368                 return __connman_error_failed(msg);
369
370         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
371 }
372
373 static GDBusMethodTable device_methods[] = {
374         { "GetProperties", "",      "a{sv}", get_properties },
375         { "SetProperty",   "sv",    "",      set_property   },
376         { "CreateNetwork", "a{sv}", "o",     create_network },
377         { "RemoveNetwork", "o",     "",      remove_network },
378         { "ProposeScan",   "",      "",      propose_scan   },
379         { },
380 };
381
382 static GDBusSignalTable device_signals[] = {
383         { "PropertyChanged", "sv" },
384         { },
385 };
386
387 static DBusConnection *connection;
388
389 static void append_devices(DBusMessageIter *entry)
390 {
391         DBusMessageIter value, iter;
392         const char *key = "Devices";
393
394         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
395
396         dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
397                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
398                                                                 &value);
399
400         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
401                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
402         __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
403         dbus_message_iter_close_container(&value, &iter);
404
405         dbus_message_iter_close_container(entry, &value);
406 }
407
408 static void emit_devices_signal(void)
409 {
410         DBusMessage *signal;
411         DBusMessageIter entry;
412
413         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
414                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
415         if (signal == NULL)
416                 return;
417
418         dbus_message_iter_init_append(signal, &entry);
419
420         append_devices(&entry);
421
422         g_dbus_send_message(connection, signal);
423 }
424
425 static int register_interface(struct connman_element *element)
426 {
427         struct connman_device *device = element->device;
428
429         if (g_dbus_register_interface(connection, element->path,
430                                         CONNMAN_DEVICE_INTERFACE,
431                                         device_methods, device_signals,
432                                         NULL, device, NULL) == FALSE) {
433                 connman_error("Failed to register %s device", element->path);
434                 return -EIO;
435         }
436
437         emit_devices_signal();
438
439         return 0;
440 }
441
442 static void unregister_interface(struct connman_element *element)
443 {
444         emit_devices_signal();
445
446         g_dbus_unregister_interface(connection, element->path,
447                                                 CONNMAN_DEVICE_INTERFACE);
448 }
449
450 static GSList *driver_list = NULL;
451
452 static gint compare_priority(gconstpointer a, gconstpointer b)
453 {
454         const struct connman_device_driver *driver1 = a;
455         const struct connman_device_driver *driver2 = b;
456
457         return driver2->priority - driver1->priority;
458 }
459
460 /**
461  * connman_device_driver_register:
462  * @driver: device driver definition
463  *
464  * Register a new device driver
465  *
466  * Returns: %0 on success
467  */
468 int connman_device_driver_register(struct connman_device_driver *driver)
469 {
470         DBG("driver %p name %s", driver, driver->name);
471
472         driver_list = g_slist_insert_sorted(driver_list, driver,
473                                                         compare_priority);
474
475         //__connman_driver_rescan(&device_driver);
476
477         return 0;
478 }
479
480 /**
481  * connman_device_driver_unregister:
482  * @driver: device driver definition
483  *
484  * Remove a previously registered device driver
485  */
486 void connman_device_driver_unregister(struct connman_device_driver *driver)
487 {
488         DBG("driver %p name %s", driver, driver->name);
489
490         driver_list = g_slist_remove(driver_list, driver);
491 }
492
493 static void unregister_network(gpointer data)
494 {
495         struct connman_network *network = data;
496
497         DBG("network %p", network);
498
499         connman_element_unregister((struct connman_element *) network);
500
501         connman_network_unref(network);
502 }
503
504 static void device_destruct(struct connman_element *element)
505 {
506         struct connman_device *device = element->device;
507
508         DBG("element %p name %s", element, element->name);
509
510         g_free(device->interface);
511
512         g_hash_table_destroy(device->networks);
513 }
514
515 /**
516  * connman_device_create:
517  * @node: device node name (for example an address)
518  * @type: device type
519  *
520  * Allocate a new device of given #type and assign the #node name to it.
521  *
522  * Returns: a newly-allocated #connman_device structure
523  */
524 struct connman_device *connman_device_create(const char *node,
525                                                 enum connman_device_type type)
526 {
527         struct connman_device *device;
528
529         DBG("node %s type %d", node, type);
530
531         device = g_try_new0(struct connman_device, 1);
532         if (device == NULL)
533                 return NULL;
534
535         DBG("device %p", device);
536
537         device->element.refcount = 1;
538
539         device->element.name = g_strdup(node);
540         device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
541         device->element.index = -1;
542
543         switch (type) {
544         case CONNMAN_DEVICE_TYPE_ETHERNET:
545                 device->element.subtype = CONNMAN_ELEMENT_SUBTYPE_ETHERNET;
546                 break;
547         default:
548                 device->element.subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
549                 break;
550         }
551
552         device->element.device = device;
553         device->element.destruct = device_destruct;
554
555         device->type = type;
556         device->mode = CONNMAN_DEVICE_MODE_NO_NETWORK;
557         device->policy = CONNMAN_DEVICE_POLICY_AUTO;
558
559         device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
560                                                 g_free, unregister_network);
561
562         return device;
563 }
564
565 /**
566  * connman_device_ref:
567  * @device: device structure
568  *
569  * Increase reference counter of device
570  */
571 struct connman_device *connman_device_ref(struct connman_device *device)
572 {
573         if (connman_element_ref(&device->element) == NULL)
574                 return NULL;
575
576         return device;
577 }
578
579 /**
580  * connman_device_unref:
581  * @device: device structure
582  *
583  * Decrease reference counter of device
584  */
585 void connman_device_unref(struct connman_device *device)
586 {
587         connman_element_unref(&device->element);
588 }
589
590 /**
591  * connman_device_set_path:
592  * @device: device structure
593  * @path: path name
594  *
595  * Set path name of device
596  */
597 void connman_device_set_path(struct connman_device *device, const char *path)
598 {
599         g_free(device->element.devpath);
600         device->element.devpath = g_strdup(path);
601
602         g_free(device->path);
603         device->path = g_strdup(path);
604 }
605
606 /**
607  * connman_device_get_path:
608  * @device: device structure
609  *
610  * Get path name of device
611  */
612 const char *connman_device_get_path(struct connman_device *device)
613 {
614         return device->path;
615 }
616
617 /**
618  * connman_device_set_index:
619  * @device: device structure
620  * @index: index number
621  *
622  * Set index number of device
623  */
624 void connman_device_set_index(struct connman_device *device, int index)
625 {
626         device->element.index = index;
627 }
628
629 /**
630  * connman_device_get_index:
631  * @device: device structure
632  *
633  * Get index number of device
634  */
635 int connman_device_get_index(struct connman_device *device)
636 {
637         return device->element.index;
638 }
639
640 /**
641  * connman_device_set_interface:
642  * @device: device structure
643  * @interface: interface name
644  *
645  * Set interface name of device
646  */
647 void connman_device_set_interface(struct connman_device *device,
648                                                         const char *interface)
649 {
650         g_free(device->element.devname);
651         device->element.devname = g_strdup(interface);
652
653         g_free(device->interface);
654         device->interface = g_strdup(interface);
655 }
656
657 /**
658  * connman_device_get_interface:
659  * @device: device structure
660  *
661  * Get interface name of device
662  */
663 const char *connman_device_get_interface(struct connman_device *device)
664 {
665         return device->interface;
666 }
667
668 /**
669  * connman_device_set_policy:
670  * @device: device structure
671  * @policy: power and connection policy
672  *
673  * Change power and connection policy of device
674  */
675 void connman_device_set_policy(struct connman_device *device,
676                                         enum connman_device_policy policy)
677 {
678         device->policy = policy;
679 }
680
681 /**
682  * connman_device_set_mode:
683  * @device: device structure
684  * @mode: network mode
685  *
686  * Change network mode of device
687  */
688 void connman_device_set_mode(struct connman_device *device,
689                                                 enum connman_device_mode mode)
690 {
691         device->mode = mode;
692 }
693
694 /**
695  * connman_device_set_powered:
696  * @device: device structure
697  * @powered: powered state
698  *
699  * Change power state of device
700  */
701 int connman_device_set_powered(struct connman_device *device,
702                                                 connman_bool_t powered)
703 {
704         DBusMessage *signal;
705         DBusMessageIter entry, value;
706         const char *key = "Powered";
707
708         DBG("driver %p powered %d", device, powered);
709
710         if (device->powered == powered)
711                 return -EALREADY;
712
713         device->powered = powered;
714
715         signal = dbus_message_new_signal(device->element.path,
716                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
717         if (signal == NULL)
718                 return 0;
719
720         dbus_message_iter_init_append(signal, &entry);
721
722         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
723
724         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
725                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
726         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
727         dbus_message_iter_close_container(&entry, &value);
728
729         g_dbus_send_message(connection, signal);
730
731         return 0;
732 }
733
734 /**
735  * connman_device_set_carrier:
736  * @device: device structure
737  * @carrier: carrier state
738  *
739  * Change carrier state of device (only for device without scanning)
740  */
741 int connman_device_set_carrier(struct connman_device *device,
742                                                 connman_bool_t carrier)
743 {
744         DBG("driver %p carrier %d", device, carrier);
745
746         if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK)
747                 return -EINVAL;
748
749         if (device->carrier == carrier)
750                 return -EALREADY;
751
752         device->carrier = carrier;
753
754         if (carrier == TRUE) {
755                 struct connman_element *element;
756
757                 element = connman_element_create(NULL);
758                 if (element != NULL) {
759                         element->type    = CONNMAN_ELEMENT_TYPE_DEVICE;
760                         element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
761                         element->index   = device->element.index;
762
763                         if (connman_element_register(element,
764                                                         &device->element) < 0)
765                                 connman_element_unref(element);
766                 }
767         } else
768                 connman_element_unregister_children(&device->element);
769
770         return 0;
771 }
772
773 /**
774  * connman_device_set_scanning:
775  * @device: device structure
776  * @scanning: scanning state
777  *
778  * Change scanning state of device
779  */
780 int connman_device_set_scanning(struct connman_device *device,
781                                                 connman_bool_t scanning)
782 {
783         DBusMessage *signal;
784         DBusMessageIter entry, value;
785         const char *key = "Scanning";
786
787         DBG("driver %p scanning %d", device, scanning);
788
789         if (!device->driver || !device->driver->scan)
790                 return -EINVAL;
791
792         if (device->scanning == scanning)
793                 return -EALREADY;
794
795         device->scanning = scanning;
796
797         signal = dbus_message_new_signal(device->element.path,
798                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
799         if (signal == NULL)
800                 return 0;
801
802         dbus_message_iter_init_append(signal, &entry);
803
804         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
805
806         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
807                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
808         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
809         dbus_message_iter_close_container(&entry, &value);
810
811         g_dbus_send_message(connection, signal);
812
813         return 0;
814 }
815
816 /**
817  * connman_device_add_network:
818  * @device: device structure
819  * @network: network structure
820  *
821  * Add new network to the device
822  */
823 int connman_device_add_network(struct connman_device *device,
824                                         struct connman_network *network)
825 {
826         const char *identifier = connman_network_get_identifier(network);
827         int err;
828
829         DBG("device %p network %p", device, network);
830
831         if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK)
832                 return -EINVAL;
833
834         err = connman_element_register((struct connman_element *) network,
835                                                         &device->element);
836         if (err < 0)
837                 return err;
838
839         g_hash_table_insert(device->networks, g_strdup(identifier),
840                                                                 network);
841
842         return 0;
843 }
844
845 /**
846  * connman_device_get_network:
847  * @device: device structure
848  * @identifier: network identifier
849  *
850  * Get network for given identifier
851  */
852 struct connman_network *connman_device_get_network(struct connman_device *device,
853                                                         const char *identifier)
854 {
855         DBG("device %p identifier %s", device, identifier);
856
857         return g_hash_table_lookup(device->networks, identifier);
858 }
859
860 /**
861  * connman_device_remove_network:
862  * @device: device structure
863  * @identifier: network identifier
864  *
865  * Remove network for given identifier
866  */
867 int connman_device_remove_network(struct connman_device *device,
868                                                         const char *identifier)
869 {
870         DBG("device %p identifier %s", device, identifier);
871
872         g_hash_table_remove(device->networks, identifier);
873
874         return 0;
875 }
876
877 /**
878  * connman_device_register:
879  * @device: device structure
880  *
881  * Register device with the system
882  */
883 int connman_device_register(struct connman_device *device)
884 {
885         return connman_element_register(&device->element, NULL);
886 }
887
888 /**
889  * connman_device_unregister:
890  * @device: device structure
891  *
892  * Unregister device with the system
893  */
894 void connman_device_unregister(struct connman_device *device)
895 {
896         connman_element_unregister(&device->element);
897 }
898
899 /**
900  * connman_device_get_data:
901  * @device: device structure
902  *
903  * Get private device data pointer
904  */
905 void *connman_device_get_data(struct connman_device *device)
906 {
907         return device->driver_data;
908 }
909
910 /**
911  * connman_device_set_data:
912  * @device: device structure
913  * @data: data pointer
914  *
915  * Set private device data pointer
916  */
917 void connman_device_set_data(struct connman_device *device, void *data)
918 {
919         device->driver_data = data;
920 }
921
922 static void device_enable(struct connman_device *device)
923 {
924         DBG("device %p", device);
925
926         if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE ||
927                                 device->policy == CONNMAN_DEVICE_POLICY_OFF)
928                 return;
929
930         if (device->powered == TRUE)
931                 return;
932
933         if (device->driver->enable)
934                 device->driver->enable(device);
935 }
936
937 static void device_disable(struct connman_device *device)
938 {
939         DBG("device %p", device);
940
941         if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE)
942                 return;
943
944         if (device->powered == FALSE)
945                 return;
946
947         g_hash_table_remove_all(device->networks);
948
949         if (device->driver->disable)
950                 device->driver->disable(device);
951 }
952
953 static gboolean match_driver(struct connman_device *device,
954                                         struct connman_device_driver *driver)
955 {
956         if (device->type == driver->type ||
957                         driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
958                 return TRUE;
959
960         return FALSE;
961 }
962
963 static int device_probe(struct connman_element *element)
964 {
965         struct connman_device *device = element->device;
966         GSList *list;
967         int err;
968
969         DBG("element %p name %s", element, element->name);
970
971         if (device == NULL)
972                 return -ENODEV;
973
974         for (list = driver_list; list; list = list->next) {
975                 struct connman_device_driver *driver = list->data;
976
977                 if (match_driver(device, driver) == FALSE)
978                         continue;
979
980                 DBG("driver %p name %s", driver, driver->name);
981
982                 if (driver->probe(device) == 0) {
983                         device->driver = driver;
984                         break;
985                 }
986         }
987
988         if (!device->driver)
989                 return -ENODEV;
990
991         err = register_interface(element);
992         if (err < 0) {
993                 if (device->driver->remove)
994                         device->driver->remove(device);
995                 return err;
996         }
997
998         device_enable(device);
999
1000         return 0;
1001 }
1002
1003 static void device_remove(struct connman_element *element)
1004 {
1005         struct connman_device *device = element->device;
1006
1007         DBG("element %p name %s", element, element->name);
1008
1009         if (device == NULL)
1010                 return;
1011
1012         if (!device->driver)
1013                 return;
1014
1015         device_disable(device);
1016
1017         unregister_interface(element);
1018
1019         if (device->driver->remove)
1020                 device->driver->remove(device);
1021 }
1022
1023 static struct connman_driver device_driver = {
1024         .name           = "device",
1025         .type           = CONNMAN_ELEMENT_TYPE_DEVICE,
1026         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
1027         .probe          = device_probe,
1028         .remove         = device_remove,
1029 };
1030
1031 int __connman_device_init(void)
1032 {
1033         DBG("");
1034
1035         connection = connman_dbus_get_connection();
1036
1037         return connman_driver_register(&device_driver);
1038 }
1039
1040 void __connman_device_cleanup(void)
1041 {
1042         DBG("");
1043
1044         connman_driver_unregister(&device_driver);
1045
1046         dbus_connection_unref(connection);
1047 }