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