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