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