Add device type CONNMAN_DEVICE_TYPE_CELLULAR
[framework/connectivity/connman.git] / src / device.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  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 <string.h>
28
29 #include <gdbus.h>
30
31 #include "connman.h"
32
33 static DBusConnection *connection = NULL;
34
35 struct connman_device {
36         struct connman_element element;
37         enum connman_device_type type;
38         enum connman_device_mode mode;
39         connman_bool_t secondary;
40         connman_bool_t offlinemode;
41         connman_bool_t blocked;
42         connman_bool_t powered;
43         connman_bool_t powered_pending;
44         connman_bool_t powered_persistent;
45         connman_bool_t carrier;
46         connman_bool_t scanning;
47         connman_bool_t disconnected;
48         connman_bool_t reconnect;
49         connman_uint16_t scan_interval;
50         char *name;
51         char *node;
52         char *address;
53         char *interface;
54         char *control;
55         char *ident;
56         int phyindex;
57         unsigned int connections;
58         guint scan_timeout;
59         struct connman_ipconfig *ipconfig;
60
61         struct connman_device_driver *driver;
62         void *driver_data;
63
64         connman_bool_t registered;
65
66         char *last_network;
67         struct connman_network *network;
68         GHashTable *networks;
69
70         DBusMessage *pending;
71         guint timeout;
72 };
73
74 static gboolean device_scan_trigger(gpointer user_data)
75 {
76         struct connman_device *device = user_data;
77
78         DBG("device %p", device);
79
80         if (device->driver == NULL) {
81                 device->scan_timeout = 0;
82                 return FALSE;
83         }
84
85         if (device->driver->scan)
86                 device->driver->scan(device);
87
88         return TRUE;
89 }
90
91 static void clear_scan_trigger(struct connman_device *device)
92 {
93         if (device->scan_timeout > 0) {
94                 g_source_remove(device->scan_timeout);
95                 device->scan_timeout = 0;
96         }
97 }
98
99 static void reset_scan_trigger(struct connman_device *device)
100 {
101         clear_scan_trigger(device);
102
103         if (device->scan_interval > 0) {
104                 guint interval = device->scan_interval;
105                 device->scan_timeout = g_timeout_add_seconds(interval,
106                                         device_scan_trigger, device);
107         }
108 }
109
110 static void force_scan_trigger(struct connman_device *device)
111 {
112         clear_scan_trigger(device);
113
114         device->scan_timeout = g_timeout_add_seconds(5,
115                                         device_scan_trigger, device);
116 }
117
118 static const char *type2description(enum connman_device_type type)
119 {
120         switch (type) {
121         case CONNMAN_DEVICE_TYPE_UNKNOWN:
122         case CONNMAN_DEVICE_TYPE_VENDOR:
123                 break;
124         case CONNMAN_DEVICE_TYPE_ETHERNET:
125                 return "Ethernet";
126         case CONNMAN_DEVICE_TYPE_WIFI:
127                 return "Wireless";
128         case CONNMAN_DEVICE_TYPE_WIMAX:
129                 return "WiMAX";
130         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
131                 return "Bluetooth";
132         case CONNMAN_DEVICE_TYPE_GPS:
133                 return "GPS";
134         case CONNMAN_DEVICE_TYPE_MBM:
135         case CONNMAN_DEVICE_TYPE_CELLULAR:
136         case CONNMAN_DEVICE_TYPE_HSO:
137         case CONNMAN_DEVICE_TYPE_NOZOMI:
138         case CONNMAN_DEVICE_TYPE_HUAWEI:
139         case CONNMAN_DEVICE_TYPE_NOVATEL:
140                 return "Cellular";
141         }
142
143         return NULL;
144 }
145
146 static const char *type2string(enum connman_device_type type)
147 {
148         switch (type) {
149         case CONNMAN_DEVICE_TYPE_UNKNOWN:
150         case CONNMAN_DEVICE_TYPE_VENDOR:
151                 break;
152         case CONNMAN_DEVICE_TYPE_ETHERNET:
153                 return "ethernet";
154         case CONNMAN_DEVICE_TYPE_WIFI:
155                 return "wifi";
156         case CONNMAN_DEVICE_TYPE_WIMAX:
157                 return "wimax";
158         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
159                 return "bluetooth";
160         case CONNMAN_DEVICE_TYPE_GPS:
161                 return "gps";
162         case CONNMAN_DEVICE_TYPE_MBM:
163         case CONNMAN_DEVICE_TYPE_CELLULAR:
164         case CONNMAN_DEVICE_TYPE_HSO:
165         case CONNMAN_DEVICE_TYPE_HUAWEI:
166         case CONNMAN_DEVICE_TYPE_NOZOMI:
167         case CONNMAN_DEVICE_TYPE_NOVATEL:
168                 return "cellular";
169         }
170
171         return NULL;
172 }
173
174 enum connman_service_type __connman_device_get_service_type(struct connman_device *device)
175 {
176         enum connman_device_type type = connman_device_get_type(device);
177
178         switch (type) {
179         case CONNMAN_DEVICE_TYPE_UNKNOWN:
180         case CONNMAN_DEVICE_TYPE_VENDOR:
181         case CONNMAN_DEVICE_TYPE_GPS:
182         case CONNMAN_DEVICE_TYPE_NOZOMI:
183         case CONNMAN_DEVICE_TYPE_HUAWEI:
184         case CONNMAN_DEVICE_TYPE_NOVATEL:
185                 break;
186         case CONNMAN_DEVICE_TYPE_ETHERNET:
187                 return CONNMAN_SERVICE_TYPE_ETHERNET;
188         case CONNMAN_DEVICE_TYPE_WIFI:
189                 return CONNMAN_SERVICE_TYPE_WIFI;
190         case CONNMAN_DEVICE_TYPE_WIMAX:
191                 return CONNMAN_SERVICE_TYPE_WIMAX;
192         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
193                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
194         case CONNMAN_DEVICE_TYPE_MBM:
195         case CONNMAN_DEVICE_TYPE_CELLULAR:
196         case CONNMAN_DEVICE_TYPE_HSO:
197                 return CONNMAN_SERVICE_TYPE_CELLULAR;
198         }
199
200         return CONNMAN_SERVICE_TYPE_UNKNOWN;
201 }
202
203 static int set_connected(struct connman_device *device,
204                                                 connman_bool_t connected)
205 {
206         if (connected == TRUE) {
207                 enum connman_element_type type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
208                 struct connman_element *element;
209
210                 device->disconnected = TRUE;
211
212                 switch (device->element.ipv4.method) {
213                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
214                 case CONNMAN_IPCONFIG_METHOD_IGNORE:
215                         return 0;
216                 case CONNMAN_IPCONFIG_METHOD_STATIC:
217                         type = CONNMAN_ELEMENT_TYPE_IPV4;
218                         break;
219                 case CONNMAN_IPCONFIG_METHOD_DHCP:
220                         type = CONNMAN_ELEMENT_TYPE_DHCP;
221                         break;
222                 }
223
224                 element = connman_element_create(NULL);
225                 if (element != NULL) {
226                         struct connman_service *service;
227
228                         element->type  = type;
229                         element->index = device->element.index;
230
231                         if (connman_element_register(element,
232                                                         &device->element) < 0)
233                                 connman_element_unref(element);
234
235                         device->disconnected = FALSE;
236
237                         service = __connman_service_lookup_from_device(device);
238                         __connman_service_indicate_state(service,
239                                         CONNMAN_SERVICE_STATE_CONFIGURATION);
240                 }
241         } else {
242                 struct connman_service *service;
243
244                 connman_element_unregister_children(&device->element);
245
246                 device->disconnected = TRUE;
247
248                 service = __connman_service_lookup_from_device(device);
249                 __connman_service_indicate_state(service,
250                                         CONNMAN_SERVICE_STATE_IDLE);
251         }
252
253         if (connected == TRUE) {
254                 enum connman_service_type type;
255
256                 type = __connman_device_get_service_type(device);
257                 __connman_notifier_connect(type);
258         } else {
259                 enum connman_service_type type;
260
261                 type = __connman_device_get_service_type(device);
262                 __connman_notifier_disconnect(type);
263         }
264
265         return 0;
266 }
267
268 static int set_carrier(struct connman_device *device, connman_bool_t carrier)
269 {
270         if (carrier == TRUE)
271                 __connman_profile_add_device(device);
272         else
273                 __connman_profile_remove_device(device);
274
275         return set_connected(device, carrier);
276 }
277
278 static int powered_changed(struct connman_device *device)
279 {
280         DBusMessage *signal;
281         DBusMessageIter entry, value;
282         const char *key = "Powered";
283
284         signal = dbus_message_new_signal(device->element.path,
285                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
286         if (signal == NULL)
287                 return -ENOMEM;
288
289         dbus_message_iter_init_append(signal, &entry);
290
291         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
292
293         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
294                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
295         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
296                                                         &device->powered);
297         dbus_message_iter_close_container(&entry, &value);
298
299         g_dbus_send_message(connection, signal);
300
301         return 0;
302 }
303
304 static int set_powered(struct connman_device *device, connman_bool_t powered)
305 {
306         struct connman_device_driver *driver = device->driver;
307         enum connman_service_type type;
308         int err;
309
310         DBG("device %p powered %d", device, powered);
311
312         if (device->powered_pending == powered)
313                 return -EALREADY;
314
315         if (!driver)
316                 return -EINVAL;
317
318         type = __connman_device_get_service_type(device);
319
320         if (powered == TRUE) {
321                 if (driver->enable) {
322                         device->powered_pending = powered;
323
324                         err = driver->enable(device);
325                         if (err == 0)
326                                 __connman_notifier_enable(type);
327                 } else
328                         err = -EINVAL;
329         } else {
330                 device->powered_pending = powered;
331
332                 device->reconnect = FALSE;
333
334                 clear_scan_trigger(device);
335
336                 g_hash_table_remove_all(device->networks);
337
338                 set_carrier(device, FALSE);
339
340                 if (driver->disable) {
341                         err = driver->disable(device);
342                         if (err == 0)
343                                 __connman_notifier_disable(type);
344                 } else
345                         err = -EINVAL;
346         }
347
348         if (err == 0) {
349                 device->powered = powered;
350
351                 if (device->registered == TRUE)
352                         powered_changed(device);
353         }
354
355         return err;
356 }
357
358 static void append_path(gpointer key, gpointer value, gpointer user_data)
359 {
360         struct connman_element *element = value;
361         DBusMessageIter *iter = user_data;
362
363         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
364                                                         &element->path);
365 }
366
367 static void append_networks(struct connman_device *device,
368                                                 DBusMessageIter *entry)
369 {
370         DBusMessageIter value, iter;
371         const char *key = "Networks";
372
373         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
374
375         dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
376                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
377                                                                 &value);
378
379         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
380                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
381         g_hash_table_foreach(device->networks, append_path, &iter);
382         dbus_message_iter_close_container(&value, &iter);
383
384         dbus_message_iter_close_container(entry, &value);
385 }
386
387 static DBusMessage *get_properties(DBusConnection *conn,
388                                         DBusMessage *msg, void *data)
389 {
390         struct connman_device *device = data;
391         DBusMessage *reply;
392         DBusMessageIter array, dict, entry;
393         const char *str;
394
395         DBG("conn %p", conn);
396
397         if (__connman_security_check_privilege(msg,
398                                         CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
399                 return __connman_error_permission_denied(msg);
400
401         reply = dbus_message_new_method_return(msg);
402         if (reply == NULL)
403                 return NULL;
404
405         dbus_message_iter_init_append(reply, &array);
406
407         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
408                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
409                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
410                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
411
412         if (device->name != NULL)
413                 connman_dbus_dict_append_variant(&dict, "Name",
414                                         DBUS_TYPE_STRING, &device->name);
415
416         str = type2string(device->type);
417         if (str != NULL)
418                 connman_dbus_dict_append_variant(&dict, "Type",
419                                                 DBUS_TYPE_STRING, &str);
420
421         if (device->address != NULL)
422                 connman_dbus_dict_append_variant(&dict, "Address",
423                                         DBUS_TYPE_STRING, &device->address);
424
425         if (device->interface != NULL)
426                 connman_dbus_dict_append_variant(&dict, "Interface",
427                                         DBUS_TYPE_STRING, &device->interface);
428
429         connman_dbus_dict_append_variant(&dict, "Powered",
430                                         DBUS_TYPE_BOOLEAN, &device->powered);
431
432         if (device->driver && device->driver->scan)
433                 connman_dbus_dict_append_variant(&dict, "Scanning",
434                                         DBUS_TYPE_BOOLEAN, &device->scanning);
435
436         switch (device->mode) {
437         case CONNMAN_DEVICE_MODE_UNKNOWN:
438                 break;
439         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
440                 __connman_element_append_ipv4(&device->element, &dict);
441                 break;
442         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
443         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
444                 if (device->scan_interval > 0)
445                         connman_dbus_dict_append_variant(&dict, "ScanInterval",
446                                 DBUS_TYPE_UINT16, &device->scan_interval);
447
448                 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
449                                                                 NULL, &entry);
450                 append_networks(device, &entry);
451                 dbus_message_iter_close_container(&dict, &entry);
452                 break;
453         }
454
455         dbus_message_iter_close_container(&array, &dict);
456
457         return reply;
458 }
459
460 static gboolean powered_timeout(gpointer user_data)
461 {
462         struct connman_device *device = user_data;
463
464         DBG("device %p", device);
465
466         device->timeout = 0;
467
468         if (device->pending != NULL) {
469                 DBusMessage *reply;
470
471                 reply = __connman_error_operation_timeout(device->pending);
472                 if (reply != NULL)
473                         g_dbus_send_message(connection, reply);
474
475                 dbus_message_unref(device->pending);
476                 device->pending = NULL;
477         }
478
479         return FALSE;
480 }
481
482 static DBusMessage *set_property(DBusConnection *conn,
483                                         DBusMessage *msg, void *data)
484 {
485         struct connman_device *device = data;
486         DBusMessageIter iter, value;
487         const char *name;
488         int type;
489
490         DBG("conn %p", conn);
491
492         if (dbus_message_iter_init(msg, &iter) == FALSE)
493                 return __connman_error_invalid_arguments(msg);
494
495         dbus_message_iter_get_basic(&iter, &name);
496         dbus_message_iter_next(&iter);
497         dbus_message_iter_recurse(&iter, &value);
498
499         if (__connman_security_check_privilege(msg,
500                                         CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
501                 return __connman_error_permission_denied(msg);
502
503         type = dbus_message_iter_get_arg_type(&value);
504
505         if (g_str_equal(name, "Powered") == TRUE) {
506                 connman_bool_t powered;
507                 int err;
508
509                 if (type != DBUS_TYPE_BOOLEAN)
510                         return __connman_error_invalid_arguments(msg);
511
512                 dbus_message_iter_get_basic(&value, &powered);
513
514                 device->powered_persistent = powered;
515
516                 __connman_storage_save_device(device);
517
518                 if (device->powered == powered)
519                         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
520
521                 if (device->pending != NULL)
522                         return __connman_error_in_progress(msg);
523
524                 err = set_powered(device, powered);
525                 if (err < 0) {
526                         if (err != -EINPROGRESS)
527                                 return __connman_error_failed(msg, -err);
528
529                         device->pending = dbus_message_ref(msg);
530
531                         device->timeout = g_timeout_add_seconds(15,
532                                                 powered_timeout, device);
533
534                         return NULL;
535                 }
536         } else if (g_str_equal(name, "ScanInterval") == TRUE) {
537                 connman_uint16_t interval;
538
539                 switch (device->mode) {
540                 case CONNMAN_DEVICE_MODE_UNKNOWN:
541                 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
542                         return __connman_error_invalid_arguments(msg);
543                 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
544                 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
545                         break;
546                 }
547
548                 if (type != DBUS_TYPE_UINT16)
549                         return __connman_error_invalid_arguments(msg);
550
551                 dbus_message_iter_get_basic(&value, &interval);
552
553                 if (device->scan_interval != interval) {
554                         device->scan_interval = interval;
555
556                         __connman_storage_save_device(device);
557
558                         reset_scan_trigger(device);
559                 }
560         } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
561                 int err;
562
563                 if (device->ipconfig == NULL)
564                         return __connman_error_invalid_property(msg);
565
566                 switch (device->mode) {
567                 case CONNMAN_DEVICE_MODE_UNKNOWN:
568                 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
569                 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
570                         return __connman_error_invalid_arguments(msg);
571                 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
572                         break;
573                 }
574
575                 err = __connman_ipconfig_set_ipv4(device->ipconfig,
576                                                         name + 5, &value);
577                 if (err < 0)
578                         return __connman_error_failed(msg, -err);
579         } else
580                 return __connman_error_invalid_property(msg);
581
582         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
583 }
584
585 static DBusMessage *propose_scan(DBusConnection *conn,
586                                         DBusMessage *msg, void *data)
587 {
588         struct connman_device *device = data;
589         int err;
590
591         DBG("conn %p", conn);
592
593         switch (device->mode) {
594         case CONNMAN_DEVICE_MODE_UNKNOWN:
595         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
596                 return __connman_error_not_supported(msg);
597         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
598         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
599                 break;
600         }
601
602         err = __connman_device_scan(device);
603         if (err < 0)
604                 return __connman_error_failed(msg, -err);
605
606         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
607 }
608
609 static GDBusMethodTable device_methods[] = {
610         { "GetProperties", "",      "a{sv}", get_properties },
611         { "SetProperty",   "sv",    "",      set_property,
612                                                 G_DBUS_METHOD_FLAG_ASYNC },
613         { "ProposeScan",   "",      "",      propose_scan   },
614         { },
615 };
616
617 static GDBusSignalTable device_signals[] = {
618         { "PropertyChanged", "sv" },
619         { },
620 };
621
622 static void append_devices(DBusMessageIter *entry)
623 {
624         DBusMessageIter value, iter;
625         const char *key = "Devices";
626
627         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
628
629         dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
630                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
631                                                                 &value);
632
633         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
634                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
635         __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
636         dbus_message_iter_close_container(&value, &iter);
637
638         dbus_message_iter_close_container(entry, &value);
639 }
640
641 static void emit_devices_signal(void)
642 {
643         DBusMessage *signal;
644         DBusMessageIter entry;
645
646         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
647                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
648         if (signal == NULL)
649                 return;
650
651         dbus_message_iter_init_append(signal, &entry);
652
653         append_devices(&entry);
654
655         g_dbus_send_message(connection, signal);
656 }
657
658 static int register_interface(struct connman_element *element)
659 {
660         struct connman_device *device = element->device;
661
662         DBG("element %p name %s", element, element->name);
663
664         if (g_dbus_register_interface(connection, element->path,
665                                         CONNMAN_DEVICE_INTERFACE,
666                                         device_methods, device_signals,
667                                         NULL, device, NULL) == FALSE) {
668                 connman_error("Failed to register %s device", element->path);
669                 return -EIO;
670         }
671
672         device->registered = TRUE;
673
674         emit_devices_signal();
675
676         return 0;
677 }
678
679 static void unregister_interface(struct connman_element *element)
680 {
681         struct connman_device *device = element->device;
682
683         DBG("element %p name %s", element, element->name);
684
685         device->registered = FALSE;
686
687         emit_devices_signal();
688
689         g_dbus_unregister_interface(connection, element->path,
690                                                 CONNMAN_DEVICE_INTERFACE);
691 }
692
693 static int setup_device(struct connman_device *device)
694 {
695         enum connman_service_type type;
696         int err;
697
698         DBG("device %p", device);
699
700         err = register_interface(&device->element);
701         if (err < 0) {
702                 if (device->driver->remove)
703                         device->driver->remove(device);
704                 device->driver = NULL;
705                 return err;
706         }
707
708         type = __connman_device_get_service_type(device);
709         __connman_notifier_register(type);
710
711         switch (device->mode) {
712         case CONNMAN_DEVICE_MODE_UNKNOWN:
713         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
714         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
715                 break;
716         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
717                 if (device->carrier == TRUE && device->secondary == FALSE)
718                         __connman_profile_add_device(device);
719                 break;
720         }
721
722         if (device->offlinemode == FALSE &&
723                                 device->powered_persistent == TRUE)
724                 __connman_device_enable(device);
725
726         return 0;
727 }
728
729 static void probe_driver(struct connman_element *element, gpointer user_data)
730 {
731         struct connman_device_driver *driver = user_data;
732
733         DBG("element %p name %s", element, element->name);
734
735         if (element->device == NULL)
736                 return;
737
738         if (element->device->driver != NULL)
739                 return;
740
741         if (driver->type != element->device->type)
742                 return;
743
744         if (driver->probe(element->device) < 0)
745                 return;
746
747         element->device->driver = driver;
748
749         setup_device(element->device);
750 }
751
752 static void remove_device(struct connman_device *device)
753 {
754         enum connman_service_type type;
755
756         DBG("device %p", device);
757
758         __connman_device_disable(device);
759
760         switch (device->mode) {
761         case CONNMAN_DEVICE_MODE_UNKNOWN:
762         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
763         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
764                 break;
765         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
766                 if (device->secondary == FALSE)
767                         __connman_profile_remove_device(device);
768                 break;
769         }
770
771         type = __connman_device_get_service_type(device);
772         __connman_notifier_unregister(type);
773
774         unregister_interface(&device->element);
775
776         if (device->driver->remove)
777                 device->driver->remove(device);
778
779         device->driver = NULL;
780 }
781
782 static void remove_driver(struct connman_element *element, gpointer user_data)
783 {
784         struct connman_device_driver *driver = user_data;
785
786         DBG("element %p name %s", element, element->name);
787
788         if (element->device == NULL)
789                 return;
790
791         if (element->device->driver == driver)
792                 remove_device(element->device);
793 }
794
795 connman_bool_t __connman_device_has_driver(struct connman_device *device)
796 {
797         if (device == NULL || device->driver == NULL)
798                 return FALSE;
799
800         return device->registered;
801 }
802
803 static GSList *driver_list = NULL;
804
805 static gint compare_priority(gconstpointer a, gconstpointer b)
806 {
807         const struct connman_device_driver *driver1 = a;
808         const struct connman_device_driver *driver2 = b;
809
810         return driver2->priority - driver1->priority;
811 }
812
813 /**
814  * connman_device_driver_register:
815  * @driver: device driver definition
816  *
817  * Register a new device driver
818  *
819  * Returns: %0 on success
820  */
821 int connman_device_driver_register(struct connman_device_driver *driver)
822 {
823         DBG("driver %p name %s", driver, driver->name);
824
825         driver_list = g_slist_insert_sorted(driver_list, driver,
826                                                         compare_priority);
827
828         __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
829                                                 probe_driver, driver);
830
831         return 0;
832 }
833
834 /**
835  * connman_device_driver_unregister:
836  * @driver: device driver definition
837  *
838  * Remove a previously registered device driver
839  */
840 void connman_device_driver_unregister(struct connman_device_driver *driver)
841 {
842         DBG("driver %p name %s", driver, driver->name);
843
844         driver_list = g_slist_remove(driver_list, driver);
845
846         __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
847                                                 remove_driver, driver);
848 }
849
850 static void unregister_network(gpointer data)
851 {
852         struct connman_network *network = data;
853
854         DBG("network %p", network);
855
856         connman_element_unregister((struct connman_element *) network);
857
858         connman_network_unref(network);
859 }
860
861 static void device_destruct(struct connman_element *element)
862 {
863         struct connman_device *device = element->device;
864
865         DBG("element %p name %s", element, element->name);
866
867         if (device->timeout > 0) {
868                 g_source_remove(device->timeout);
869                 device->timeout = 0;
870         }
871
872         clear_scan_trigger(device);
873
874         if (device->pending != NULL) {
875                 dbus_message_unref(device->pending);
876                 device->pending = NULL;
877         }
878
879         g_free(device->ident);
880         g_free(device->node);
881         g_free(device->name);
882         g_free(device->address);
883         g_free(device->control);
884         g_free(device->interface);
885
886         if (device->ipconfig != NULL) {
887                 connman_ipconfig_unref(device->ipconfig);
888                 device->ipconfig = NULL;
889         }
890
891         g_free(device->last_network);
892
893         g_hash_table_destroy(device->networks);
894         device->networks = NULL;
895 }
896
897 /**
898  * connman_device_create:
899  * @node: device node name (for example an address)
900  * @type: device type
901  *
902  * Allocate a new device of given #type and assign the #node name to it.
903  *
904  * Returns: a newly-allocated #connman_device structure
905  */
906 struct connman_device *connman_device_create(const char *node,
907                                                 enum connman_device_type type)
908 {
909         struct connman_device *device;
910         const char *str;
911
912         DBG("node %s type %d", node, type);
913
914         device = g_try_new0(struct connman_device, 1);
915         if (device == NULL)
916                 return NULL;
917
918         DBG("device %p", device);
919
920         __connman_element_initialize(&device->element);
921
922         device->element.name = g_strdup(node);
923         device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
924
925         device->element.device = device;
926         device->element.destruct = device_destruct;
927
928         str = type2string(type);
929         if (str != NULL)
930                 connman_element_set_string(&device->element,
931                                         CONNMAN_PROPERTY_ID_TYPE, str);
932
933         device->element.ipv4.method = CONNMAN_IPCONFIG_METHOD_DHCP;
934
935         device->type      = type;
936         device->name      = g_strdup(type2description(device->type));
937         device->mode      = CONNMAN_DEVICE_MODE_UNKNOWN;
938         device->secondary = FALSE;
939
940         device->powered_persistent = TRUE;
941
942         device->phyindex = -1;
943
944         switch (type) {
945         case CONNMAN_DEVICE_TYPE_UNKNOWN:
946         case CONNMAN_DEVICE_TYPE_VENDOR:
947                 device->scan_interval = 0;
948                 break;
949         case CONNMAN_DEVICE_TYPE_ETHERNET:
950         case CONNMAN_DEVICE_TYPE_WIFI:
951                 device->scan_interval = 300;
952                 break;
953         case CONNMAN_DEVICE_TYPE_WIMAX:
954                 device->scan_interval = 0;
955                 break;
956         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
957                 device->scan_interval = 0;
958                 break;
959         case CONNMAN_DEVICE_TYPE_GPS:
960                 device->scan_interval = 0;
961                 break;
962         case CONNMAN_DEVICE_TYPE_MBM:
963         case CONNMAN_DEVICE_TYPE_CELLULAR:
964         case CONNMAN_DEVICE_TYPE_HSO:
965         case CONNMAN_DEVICE_TYPE_NOZOMI:
966         case CONNMAN_DEVICE_TYPE_HUAWEI:
967         case CONNMAN_DEVICE_TYPE_NOVATEL:
968                 device->scan_interval = 0;
969                 break;
970         }
971
972         device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
973                                                 g_free, unregister_network);
974
975         return device;
976 }
977
978 /**
979  * connman_device_ref:
980  * @device: device structure
981  *
982  * Increase reference counter of device
983  */
984 struct connman_device *connman_device_ref(struct connman_device *device)
985 {
986         if (connman_element_ref(&device->element) == NULL)
987                 return NULL;
988
989         return device;
990 }
991
992 /**
993  * connman_device_unref:
994  * @device: device structure
995  *
996  * Decrease reference counter of device
997  */
998 void connman_device_unref(struct connman_device *device)
999 {
1000         connman_element_unref(&device->element);
1001 }
1002
1003 const char *__connman_device_get_type(struct connman_device *device)
1004 {
1005         return type2string(device->type);
1006 }
1007
1008 /**
1009  * connman_device_get_type:
1010  * @device: device structure
1011  *
1012  * Get type of device
1013  */
1014 enum connman_device_type connman_device_get_type(struct connman_device *device)
1015 {
1016         return device->type;
1017 }
1018
1019 /**
1020  * connman_device_get_name:
1021  * @device: device structure
1022  *
1023  * Get unique name of device
1024  */
1025 const char *connman_device_get_name(struct connman_device *device)
1026 {
1027         return device->element.name;
1028 }
1029
1030 /**
1031  * connman_device_get_path:
1032  * @device: device structure
1033  *
1034  * Get path name of device
1035  */
1036 const char *connman_device_get_path(struct connman_device *device)
1037 {
1038         return device->element.path;
1039 }
1040
1041 /**
1042  * connman_device_set_index:
1043  * @device: device structure
1044  * @index: index number
1045  *
1046  * Set index number of device
1047  */
1048 void connman_device_set_index(struct connman_device *device, int index)
1049 {
1050         device->element.index = index;
1051
1052         if (device->ipconfig != NULL) {
1053                 if (index == connman_ipconfig_get_index(device->ipconfig))
1054                         return;
1055
1056                 connman_ipconfig_unref(device->ipconfig);
1057         }
1058
1059         device->ipconfig = connman_ipconfig_create(index);
1060 }
1061
1062 /**
1063  * connman_device_get_index:
1064  * @device: device structure
1065  *
1066  * Get index number of device
1067  */
1068 int connman_device_get_index(struct connman_device *device)
1069 {
1070         return device->element.index;
1071 }
1072
1073 int __connman_device_get_phyindex(struct connman_device *device)
1074 {
1075         return device->phyindex;
1076 }
1077
1078 void __connman_device_set_phyindex(struct connman_device *device,
1079                                                         int phyindex)
1080 {
1081         device->phyindex = phyindex;
1082 }
1083
1084 /**
1085  * connman_device_set_interface:
1086  * @device: device structure
1087  * @interface: interface name
1088  * @control: control interface
1089  *
1090  * Set interface name of device
1091  */
1092 void connman_device_set_interface(struct connman_device *device,
1093                                 const char *interface, const char *control)
1094 {
1095         g_free(device->element.devname);
1096         device->element.devname = g_strdup(interface);
1097
1098         g_free(device->interface);
1099         device->interface = g_strdup(interface);
1100
1101         g_free(device->control);
1102         device->control = g_strdup(control);
1103
1104         if (device->name == NULL) {
1105                 const char *str = type2description(device->type);
1106                 if (str != NULL && device->interface != NULL)
1107                         device->name = g_strdup_printf("%s (%s)", str,
1108                                                         device->interface);
1109         }
1110 }
1111
1112 const char *connman_device_get_control(struct connman_device *device)
1113 {
1114         return device->control;
1115 }
1116
1117 /**
1118  * connman_device_set_ident:
1119  * @device: device structure
1120  * @ident: unique identifier
1121  *
1122  * Set unique identifier of device
1123  */
1124 void connman_device_set_ident(struct connman_device *device,
1125                                                         const char *ident)
1126 {
1127         g_free(device->ident);
1128         device->ident = g_strdup(ident);
1129 }
1130
1131 const char *__connman_device_get_ident(struct connman_device *device)
1132 {
1133         return device->ident;
1134 }
1135
1136 /**
1137  * connman_device_set_mode:
1138  * @device: device structure
1139  * @mode: network mode
1140  *
1141  * Change network mode of device
1142  */
1143 void connman_device_set_mode(struct connman_device *device,
1144                                                 enum connman_device_mode mode)
1145 {
1146         device->mode = mode;
1147 }
1148
1149 /**
1150  * connman_device_get_mode:
1151  * @device: device structure
1152  *
1153  * Get network mode of device
1154  */
1155 enum connman_device_mode connman_device_get_mode(struct connman_device *device)
1156 {
1157         return device->mode;
1158 }
1159
1160 /**
1161  * connman_device_set_secondary:
1162  * @device: device structure
1163  * @secondary: secondary value
1164  *
1165  * Change secondary value of device
1166  */
1167 void connman_device_set_secondary(struct connman_device *device,
1168                                                 connman_bool_t secondary)
1169 {
1170         device->secondary = secondary;
1171 }
1172
1173 /**
1174  * connman_device_get_secondary:
1175  * @device: device structure
1176  *
1177  * Get secondary value of device
1178  */
1179 connman_bool_t connman_device_get_secondary(struct connman_device *device)
1180 {
1181         return device->secondary;
1182 }
1183
1184 /**
1185  * connman_device_set_powered:
1186  * @device: device structure
1187  * @powered: powered state
1188  *
1189  * Change power state of device
1190  */
1191 int connman_device_set_powered(struct connman_device *device,
1192                                                 connman_bool_t powered)
1193 {
1194         enum connman_service_type type;
1195
1196         DBG("driver %p powered %d", device, powered);
1197
1198         if (device->timeout > 0) {
1199                 g_source_remove(device->timeout);
1200                 device->timeout = 0;
1201         }
1202
1203         if (device->pending != NULL) {
1204                 g_dbus_send_reply(connection, device->pending,
1205                                                         DBUS_TYPE_INVALID);
1206
1207                 dbus_message_unref(device->pending);
1208                 device->pending = NULL;
1209         }
1210
1211         if (device->powered == powered)
1212                 return -EALREADY;
1213
1214         device->powered = powered;
1215         device->powered_pending = powered;
1216
1217         type = __connman_device_get_service_type(device);
1218
1219         if (device->powered == TRUE)
1220                 __connman_notifier_enable(type);
1221         else
1222                 __connman_notifier_disable(type);
1223
1224         if (device->registered == FALSE)
1225                 return 0;
1226
1227         powered_changed(device);
1228
1229         if (powered == FALSE)
1230                 return 0;
1231
1232         reset_scan_trigger(device);
1233
1234         if (device->driver->scan)
1235                 device->driver->scan(device);
1236
1237         return 0;
1238 }
1239
1240 int __connman_device_set_blocked(struct connman_device *device,
1241                                                 connman_bool_t blocked)
1242 {
1243         connman_bool_t powered;
1244
1245         DBG("device %p blocked %d", device, blocked);
1246
1247         device->blocked = blocked;
1248
1249         if (device->offlinemode == TRUE)
1250                 return 0;
1251
1252         connman_info("%s {rfkill} blocked %d", device->interface, blocked);
1253
1254         if (blocked == FALSE)
1255                 powered = device->powered_persistent;
1256         else
1257                 powered = FALSE;
1258
1259         return set_powered(device, powered);
1260 }
1261
1262 /**
1263  * connman_device_set_carrier:
1264  * @device: device structure
1265  * @carrier: carrier state
1266  *
1267  * Change carrier state of device (only for device without scanning)
1268  */
1269 int connman_device_set_carrier(struct connman_device *device,
1270                                                 connman_bool_t carrier)
1271 {
1272         DBG("device %p carrier %d", device, carrier);
1273
1274         switch (device->mode) {
1275         case CONNMAN_DEVICE_MODE_UNKNOWN:
1276         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1277         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1278                 return -EINVAL;
1279         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1280                 break;
1281         }
1282
1283         if (device->carrier == carrier)
1284                 return -EALREADY;
1285
1286         device->carrier = carrier;
1287
1288         return set_carrier(device, device->carrier);
1289 }
1290
1291 int __connman_device_scan(struct connman_device *device)
1292 {
1293         if (!device->driver || !device->driver->scan)
1294                 return -EOPNOTSUPP;
1295
1296         if (device->powered == FALSE)
1297                 return -ENOLINK;
1298
1299         reset_scan_trigger(device);
1300
1301         return device->driver->scan(device);
1302 }
1303
1304 int __connman_device_enable(struct connman_device *device)
1305 {
1306         enum connman_service_type type;
1307         int err;
1308
1309         DBG("device %p", device);
1310
1311         if (!device->driver || !device->driver->enable)
1312                 return -EOPNOTSUPP;
1313
1314         if (device->powered_pending == TRUE)
1315                 return -EALREADY;
1316
1317         device->powered_pending = TRUE;
1318
1319         err = device->driver->enable(device);
1320         if (err < 0)
1321                 return err;
1322
1323         device->powered = TRUE;
1324
1325         type = __connman_device_get_service_type(device);
1326         __connman_notifier_enable(type);
1327
1328         return 0;
1329 }
1330
1331 int __connman_device_enable_persistent(struct connman_device *device)
1332 {
1333         DBG("device %p", device);
1334
1335         device->powered_persistent = TRUE;
1336
1337         __connman_storage_save_device(device);
1338
1339         return __connman_device_enable(device);
1340 }
1341
1342 int __connman_device_disable(struct connman_device *device)
1343 {
1344         enum connman_service_type type;
1345         int err;
1346
1347         DBG("device %p", device);
1348
1349         if (!device->driver || !device->driver->disable)
1350                 return -EOPNOTSUPP;
1351
1352         if (device->powered == FALSE)
1353                 return -ENOLINK;
1354
1355         if (device->powered_pending == FALSE)
1356                 return -EALREADY;
1357
1358         device->powered_pending = FALSE;
1359
1360         device->reconnect = FALSE;
1361
1362         clear_scan_trigger(device);
1363
1364         g_hash_table_remove_all(device->networks);
1365
1366         err = device->driver->disable(device);
1367         if (err < 0)
1368                 return err;
1369
1370         device->powered = FALSE;
1371
1372         type = __connman_device_get_service_type(device);
1373         __connman_notifier_disable(type);
1374
1375         return 0;
1376 }
1377
1378 int __connman_device_disable_persistent(struct connman_device *device)
1379 {
1380         DBG("device %p", device);
1381
1382         device->powered_persistent = FALSE;
1383
1384         __connman_storage_save_device(device);
1385
1386         return __connman_device_disable(device);
1387 }
1388
1389 int __connman_device_connect(struct connman_device *device)
1390 {
1391         DBG("device %p", device);
1392
1393         if (device->disconnected == FALSE)
1394                 return -EINVAL;
1395
1396         if (device->driver && device->driver->connect)
1397                 device->driver->connect(device);
1398
1399         return 0;
1400 }
1401
1402 int __connman_device_disconnect(struct connman_device *device)
1403 {
1404         GHashTableIter iter;
1405         gpointer key, value;
1406
1407         DBG("device %p", device);
1408
1409         connman_device_set_disconnected(device, TRUE);
1410
1411         g_hash_table_iter_init(&iter, device->networks);
1412
1413         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1414                 struct connman_network *network = value;
1415
1416                 __connman_network_disconnect(network);
1417         }
1418
1419         if (device->driver && device->driver->disconnect)
1420                 device->driver->disconnect(device);
1421
1422         return 0;
1423 }
1424
1425 static void mark_network_unavailable(gpointer key, gpointer value,
1426                                                         gpointer user_data)
1427 {
1428         struct connman_network *network = value;
1429
1430         if (connman_network_get_connected(network) == TRUE)
1431                 return;
1432
1433         connman_network_set_available(network, FALSE);
1434 }
1435
1436 static gboolean remove_unavailable_network(gpointer key, gpointer value,
1437                                                         gpointer user_data)
1438 {
1439         struct connman_network *network = value;
1440
1441         if (connman_network_get_connected(network) == TRUE)
1442                 return FALSE;
1443
1444         if (connman_network_get_available(network) == TRUE)
1445                 return FALSE;
1446
1447         return TRUE;
1448 }
1449
1450 void __connman_device_cleanup_networks(struct connman_device *device)
1451 {
1452         g_hash_table_foreach_remove(device->networks,
1453                                         remove_unavailable_network, NULL);
1454 }
1455
1456 static void scanning_changed(struct connman_device *device)
1457 {
1458         DBusMessage *signal;
1459         DBusMessageIter entry, value;
1460         const char *key = "Scanning";
1461
1462         signal = dbus_message_new_signal(device->element.path,
1463                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1464         if (signal == NULL)
1465                 return;
1466
1467         dbus_message_iter_init_append(signal, &entry);
1468
1469         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1470
1471         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1472                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
1473         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
1474                                                         &device->scanning);
1475         dbus_message_iter_close_container(&entry, &value);
1476
1477         g_dbus_send_message(connection, signal);
1478 }
1479
1480 static void mark_network_available(gpointer key, gpointer value,
1481                                                 gpointer user_data)
1482 {
1483         struct connman_network *network = value;
1484
1485         connman_network_set_available(network, TRUE);
1486 }
1487
1488 void connman_device_cleanup_scanning(struct connman_device *device)
1489 {
1490         device->scanning = FALSE;
1491
1492         scanning_changed(device);
1493
1494         g_hash_table_foreach(device->networks,
1495                                 mark_network_available, NULL);
1496 }
1497
1498 /**
1499  * connman_device_set_scanning:
1500  * @device: device structure
1501  * @scanning: scanning state
1502  *
1503  * Change scanning state of device
1504  */
1505 int connman_device_set_scanning(struct connman_device *device,
1506                                                 connman_bool_t scanning)
1507 {
1508         DBG("device %p scanning %d", device, scanning);
1509
1510         if (!device->driver || !device->driver->scan)
1511                 return -EINVAL;
1512
1513         if (device->scanning == scanning)
1514                 return -EALREADY;
1515
1516         device->scanning = scanning;
1517
1518         scanning_changed(device);
1519
1520         if (scanning == TRUE) {
1521                 reset_scan_trigger(device);
1522
1523                 g_hash_table_foreach(device->networks,
1524                                         mark_network_unavailable, NULL);
1525
1526                 return 0;
1527         }
1528
1529         __connman_device_cleanup_networks(device);
1530
1531         if (device->connections > 0)
1532                 return 0;
1533
1534         if (device->disconnected == TRUE)
1535                 return 0;
1536
1537         __connman_service_auto_connect();
1538
1539         return 0;
1540 }
1541
1542 /**
1543  * connman_device_set_disconnected:
1544  * @device: device structure
1545  * @disconnected: disconnected state
1546  *
1547  * Change disconnected state of device (only for device with networks)
1548  */
1549 int connman_device_set_disconnected(struct connman_device *device,
1550                                                 connman_bool_t disconnected)
1551 {
1552         DBG("device %p disconnected %d", device, disconnected);
1553
1554         switch (device->mode) {
1555         case CONNMAN_DEVICE_MODE_UNKNOWN:
1556         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1557                 return -EINVAL;
1558         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1559         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1560                 break;
1561         }
1562
1563         if (device->disconnected == disconnected)
1564                 return -EALREADY;
1565
1566         device->disconnected = disconnected;
1567
1568         if (disconnected == TRUE)
1569                 force_scan_trigger(device);
1570
1571         return 0;
1572 }
1573
1574 /**
1575  * connman_device_get_disconnected:
1576  * @device: device structure
1577  *
1578  * Get device disconnected state
1579  */
1580 connman_bool_t connman_device_get_disconnected(struct connman_device *device)
1581 {
1582         return device->disconnected;
1583 }
1584
1585 /**
1586  * connman_device_set_connected:
1587  * @device: device structure
1588  * @connected: connected state
1589  *
1590  * Change connected state of device (for Ethernet like devices)
1591  */
1592 int connman_device_set_connected(struct connman_device *device,
1593                                                 connman_bool_t connected)
1594 {
1595         DBG("device %p connected %d", device, connected);
1596
1597         switch (device->mode) {
1598         case CONNMAN_DEVICE_MODE_UNKNOWN:
1599         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1600         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1601                 return -EINVAL;
1602         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1603                 break;
1604         }
1605
1606         if (device->carrier == FALSE)
1607                 return -ENOTCONN;
1608
1609         return set_connected(device, connected);
1610 }
1611
1612 /**
1613  * connman_device_set_string:
1614  * @device: device structure
1615  * @key: unique identifier
1616  * @value: string value
1617  *
1618  * Set string value for specific key
1619  */
1620 int connman_device_set_string(struct connman_device *device,
1621                                         const char *key, const char *value)
1622 {
1623         DBG("device %p key %s value %s", device, key, value);
1624
1625         if (g_str_equal(key, "Address") == TRUE) {
1626                 g_free(device->address);
1627                 device->address = g_strdup(value);
1628         } else if (g_str_equal(key, "Name") == TRUE) {
1629                 g_free(device->name);
1630                 device->name = g_strdup(value);
1631         } else if (g_str_equal(key, "Node") == TRUE) {
1632                 g_free(device->node);
1633                 device->node = g_strdup(value);
1634         }
1635
1636         return connman_element_set_string(&device->element, key, value);
1637 }
1638
1639 /**
1640  * connman_device_get_string:
1641  * @device: device structure
1642  * @key: unique identifier
1643  *
1644  * Get string value for specific key
1645  */
1646 const char *connman_device_get_string(struct connman_device *device,
1647                                                         const char *key)
1648 {
1649         DBG("device %p key %s", device, key);
1650
1651         if (g_str_equal(key, "Address") == TRUE)
1652                 return device->address;
1653         else if (g_str_equal(key, "Name") == TRUE)
1654                 return device->name;
1655         else if (g_str_equal(key, "Node") == TRUE)
1656                 return device->node;
1657
1658         return connman_element_get_string(&device->element, key);
1659 }
1660
1661 static void set_offlinemode(struct connman_element *element, gpointer user_data)
1662 {
1663         struct connman_device *device = element->device;
1664         connman_bool_t offlinemode = GPOINTER_TO_UINT(user_data);
1665         connman_bool_t powered;
1666
1667         DBG("element %p name %s", element, element->name);
1668
1669         if (device == NULL)
1670                 return;
1671
1672         device->offlinemode = offlinemode;
1673
1674         powered = (offlinemode == TRUE) ? FALSE : TRUE;
1675
1676         if (device->powered == powered)
1677                 return;
1678
1679         if (device->powered_persistent == FALSE)
1680                 powered = FALSE;
1681
1682         set_powered(device, powered);
1683 }
1684
1685 int __connman_device_set_offlinemode(connman_bool_t offlinemode)
1686 {
1687         DBG("offlinmode %d", offlinemode);
1688
1689         __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
1690                         set_offlinemode, GUINT_TO_POINTER(offlinemode));
1691
1692         __connman_notifier_offlinemode(offlinemode);
1693
1694         return 0;
1695 }
1696
1697 void __connman_device_increase_connections(struct connman_device *device)
1698 {
1699         device->connections++;
1700 }
1701
1702 void __connman_device_decrease_connections(struct connman_device *device)
1703 {
1704         device->connections--;
1705 }
1706
1707 /**
1708  * connman_device_add_network:
1709  * @device: device structure
1710  * @network: network structure
1711  *
1712  * Add new network to the device
1713  */
1714 int connman_device_add_network(struct connman_device *device,
1715                                         struct connman_network *network)
1716 {
1717         const char *identifier = connman_network_get_identifier(network);
1718         int err;
1719
1720         DBG("device %p network %p", device, network);
1721
1722         switch (device->mode) {
1723         case CONNMAN_DEVICE_MODE_UNKNOWN:
1724         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1725                 return -EINVAL;
1726         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1727         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1728                 break;
1729         }
1730
1731         __connman_network_set_device(network, device);
1732
1733         err = connman_element_register((struct connman_element *) network,
1734                                                         &device->element);
1735         if (err < 0) {
1736                 __connman_network_set_device(network, NULL);
1737                 return err;
1738         }
1739
1740         g_hash_table_insert(device->networks, g_strdup(identifier),
1741                                                                 network);
1742
1743         return 0;
1744 }
1745
1746 /**
1747  * connman_device_get_network:
1748  * @device: device structure
1749  * @identifier: network identifier
1750  *
1751  * Get network for given identifier
1752  */
1753 struct connman_network *connman_device_get_network(struct connman_device *device,
1754                                                         const char *identifier)
1755 {
1756         DBG("device %p identifier %s", device, identifier);
1757
1758         return g_hash_table_lookup(device->networks, identifier);
1759 }
1760
1761 /**
1762  * connman_device_remove_network:
1763  * @device: device structure
1764  * @identifier: network identifier
1765  *
1766  * Remove network for given identifier
1767  */
1768 int connman_device_remove_network(struct connman_device *device,
1769                                                         const char *identifier)
1770 {
1771         DBG("device %p identifier %s", device, identifier);
1772
1773         g_hash_table_remove(device->networks, identifier);
1774
1775         return 0;
1776 }
1777
1778 void __connman_device_set_network(struct connman_device *device,
1779                                         struct connman_network *network)
1780 {
1781         const char *name;
1782
1783         if (device->network == network)
1784                 return;
1785
1786         if (device->network != NULL)
1787                 connman_network_unref(device->network);
1788
1789         if (network != NULL) {
1790                 name = connman_network_get_string(network,
1791                                                 CONNMAN_PROPERTY_ID_NAME);
1792                 g_free(device->last_network);
1793                 device->last_network = g_strdup(name);
1794
1795                 device->network = connman_network_ref(network);
1796         } else {
1797                 g_free(device->last_network);
1798                 device->last_network = NULL;
1799
1800                 device->network = NULL;
1801         }
1802 }
1803
1804 void __connman_device_set_reconnect(struct connman_device *device,
1805                                                 connman_bool_t reconnect)
1806 {
1807         device->reconnect = reconnect;
1808 }
1809
1810 connman_bool_t  __connman_device_get_reconnect(
1811                                 struct connman_device *device)
1812 {
1813         return device->reconnect;
1814 }
1815
1816 /**
1817  * connman_device_register:
1818  * @device: device structure
1819  *
1820  * Register device with the system
1821  */
1822 int connman_device_register(struct connman_device *device)
1823 {
1824         __connman_storage_load_device(device);
1825
1826         device->offlinemode = __connman_profile_get_offlinemode();
1827
1828         return connman_element_register(&device->element, NULL);
1829 }
1830
1831 /**
1832  * connman_device_unregister:
1833  * @device: device structure
1834  *
1835  * Unregister device with the system
1836  */
1837 void connman_device_unregister(struct connman_device *device)
1838 {
1839         __connman_storage_save_device(device);
1840
1841         connman_element_unregister(&device->element);
1842 }
1843
1844 /**
1845  * connman_device_get_data:
1846  * @device: device structure
1847  *
1848  * Get private device data pointer
1849  */
1850 void *connman_device_get_data(struct connman_device *device)
1851 {
1852         return device->driver_data;
1853 }
1854
1855 /**
1856  * connman_device_set_data:
1857  * @device: device structure
1858  * @data: data pointer
1859  *
1860  * Set private device data pointer
1861  */
1862 void connman_device_set_data(struct connman_device *device, void *data)
1863 {
1864         device->driver_data = data;
1865 }
1866
1867 static gboolean match_driver(struct connman_device *device,
1868                                         struct connman_device_driver *driver)
1869 {
1870         if (device->type == driver->type ||
1871                         driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1872                 return TRUE;
1873
1874         return FALSE;
1875 }
1876
1877 static int device_probe(struct connman_element *element)
1878 {
1879         struct connman_device *device = element->device;
1880         GSList *list;
1881
1882         DBG("element %p name %s", element, element->name);
1883
1884         if (device == NULL)
1885                 return -ENODEV;
1886
1887         if (device->driver != NULL)
1888                 return -EALREADY;
1889
1890         for (list = driver_list; list; list = list->next) {
1891                 struct connman_device_driver *driver = list->data;
1892
1893                 if (match_driver(device, driver) == FALSE)
1894                         continue;
1895
1896                 DBG("driver %p name %s", driver, driver->name);
1897
1898                 if (driver->probe(device) == 0) {
1899                         device->driver = driver;
1900                         break;
1901                 }
1902         }
1903
1904         if (device->driver == NULL)
1905                 return -ENODEV;
1906
1907         return setup_device(device);
1908 }
1909
1910 static void device_remove(struct connman_element *element)
1911 {
1912         struct connman_device *device = element->device;
1913
1914         DBG("element %p name %s", element, element->name);
1915
1916         if (device == NULL)
1917                 return;
1918
1919         if (device->driver == NULL)
1920                 return;
1921
1922         remove_device(device);
1923 }
1924
1925 static struct connman_driver device_driver = {
1926         .name           = "device",
1927         .type           = CONNMAN_ELEMENT_TYPE_DEVICE,
1928         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
1929         .probe          = device_probe,
1930         .remove         = device_remove,
1931 };
1932
1933 static int device_load(struct connman_device *device)
1934 {
1935         const char *ident = __connman_profile_active_ident();
1936         GKeyFile *keyfile;
1937         GError *error = NULL;
1938         gchar *identifier;
1939         connman_bool_t powered;
1940         int val;
1941
1942         DBG("device %p", device);
1943
1944         keyfile = __connman_storage_open(ident);
1945         if (keyfile == NULL)
1946                 return 0;
1947
1948         identifier = g_strdup_printf("device_%s", device->element.name);
1949         if (identifier == NULL)
1950                 goto done;
1951
1952         powered = g_key_file_get_boolean(keyfile, identifier,
1953                                                 "Powered", &error);
1954         if (error == NULL)
1955                 device->powered_persistent = powered;
1956         g_clear_error(&error);
1957
1958         switch (device->mode) {
1959         case CONNMAN_DEVICE_MODE_UNKNOWN:
1960         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1961                 break;
1962         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1963         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1964                 val = g_key_file_get_integer(keyfile, identifier,
1965                                                 "ScanInterval", &error);
1966                 if (error == NULL && val > 0)
1967                         device->scan_interval = val;
1968                 g_clear_error(&error);
1969                 break;
1970         }
1971
1972 done:
1973         g_free(identifier);
1974
1975         __connman_storage_close(ident, keyfile, FALSE);
1976
1977         return 0;
1978 }
1979
1980 static int device_save(struct connman_device *device)
1981 {
1982         const char *ident = __connman_profile_active_ident();
1983         GKeyFile *keyfile;
1984         gchar *identifier;
1985
1986         DBG("device %p", device);
1987
1988         keyfile = __connman_storage_open(ident);
1989         if (keyfile == NULL)
1990                 return 0;
1991
1992         identifier = g_strdup_printf("device_%s", device->element.name);
1993         if (identifier == NULL)
1994                 goto done;
1995
1996         g_key_file_set_boolean(keyfile, identifier,
1997                                         "Powered", device->powered_persistent);
1998
1999         switch (device->mode) {
2000         case CONNMAN_DEVICE_MODE_UNKNOWN:
2001         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
2002                 break;
2003         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
2004         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
2005                 if (device->scan_interval > 0)
2006                         g_key_file_set_integer(keyfile, identifier,
2007                                         "ScanInterval", device->scan_interval);
2008                 break;
2009         }
2010
2011 done:
2012         g_free(identifier);
2013
2014         __connman_storage_close(ident, keyfile, TRUE);
2015
2016         return 0;
2017 }
2018
2019 static struct connman_storage device_storage = {
2020         .name           = "device",
2021         .priority       = CONNMAN_STORAGE_PRIORITY_LOW,
2022         .device_load    = device_load,
2023         .device_save    = device_save,
2024 };
2025
2026 int __connman_device_init(void)
2027 {
2028         DBG("");
2029
2030         connection = connman_dbus_get_connection();
2031
2032         if (connman_storage_register(&device_storage) < 0)
2033                 connman_error("Failed to register device storage");
2034
2035         return connman_driver_register(&device_driver);
2036 }
2037
2038 void __connman_device_cleanup(void)
2039 {
2040         DBG("");
2041
2042         connman_driver_unregister(&device_driver);
2043
2044         connman_storage_unregister(&device_storage);
2045
2046         dbus_connection_unref(connection);
2047 }