Properly skip over quoted values
[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_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         if (device->pending != NULL) {
870                 dbus_message_unref(device->pending);
871                 device->pending = NULL;
872         }
873
874         g_free(device->ident);
875         g_free(device->node);
876         g_free(device->name);
877         g_free(device->address);
878         g_free(device->control);
879         g_free(device->interface);
880
881         if (device->ipconfig != NULL) {
882                 connman_ipconfig_unref(device->ipconfig);
883                 device->ipconfig = NULL;
884         }
885
886         g_free(device->last_network);
887
888         g_hash_table_destroy(device->networks);
889         device->networks = NULL;
890 }
891
892 /**
893  * connman_device_create:
894  * @node: device node name (for example an address)
895  * @type: device type
896  *
897  * Allocate a new device of given #type and assign the #node name to it.
898  *
899  * Returns: a newly-allocated #connman_device structure
900  */
901 struct connman_device *connman_device_create(const char *node,
902                                                 enum connman_device_type type)
903 {
904         struct connman_device *device;
905         const char *str;
906
907         DBG("node %s type %d", node, type);
908
909         device = g_try_new0(struct connman_device, 1);
910         if (device == NULL)
911                 return NULL;
912
913         DBG("device %p", device);
914
915         __connman_element_initialize(&device->element);
916
917         device->element.name = g_strdup(node);
918         device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
919
920         device->element.device = device;
921         device->element.destruct = device_destruct;
922
923         str = type2string(type);
924         if (str != NULL)
925                 connman_element_set_string(&device->element,
926                                         CONNMAN_PROPERTY_ID_TYPE, str);
927
928         device->element.ipv4.method = CONNMAN_IPCONFIG_METHOD_DHCP;
929
930         device->type      = type;
931         device->name      = g_strdup(type2description(device->type));
932         device->mode      = CONNMAN_DEVICE_MODE_UNKNOWN;
933         device->secondary = FALSE;
934
935         device->powered_persistent = TRUE;
936
937         device->phyindex = -1;
938
939         switch (type) {
940         case CONNMAN_DEVICE_TYPE_UNKNOWN:
941         case CONNMAN_DEVICE_TYPE_VENDOR:
942                 device->scan_interval = 0;
943                 break;
944         case CONNMAN_DEVICE_TYPE_ETHERNET:
945         case CONNMAN_DEVICE_TYPE_WIFI:
946                 device->scan_interval = 300;
947                 break;
948         case CONNMAN_DEVICE_TYPE_WIMAX:
949                 device->scan_interval = 0;
950                 break;
951         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
952                 device->scan_interval = 0;
953                 break;
954         case CONNMAN_DEVICE_TYPE_GPS:
955                 device->scan_interval = 0;
956                 break;
957         case CONNMAN_DEVICE_TYPE_MBM:
958         case CONNMAN_DEVICE_TYPE_HSO:
959         case CONNMAN_DEVICE_TYPE_NOZOMI:
960         case CONNMAN_DEVICE_TYPE_HUAWEI:
961         case CONNMAN_DEVICE_TYPE_NOVATEL:
962                 device->scan_interval = 0;
963                 break;
964         }
965
966         device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
967                                                 g_free, unregister_network);
968
969         return device;
970 }
971
972 /**
973  * connman_device_ref:
974  * @device: device structure
975  *
976  * Increase reference counter of device
977  */
978 struct connman_device *connman_device_ref(struct connman_device *device)
979 {
980         if (connman_element_ref(&device->element) == NULL)
981                 return NULL;
982
983         return device;
984 }
985
986 /**
987  * connman_device_unref:
988  * @device: device structure
989  *
990  * Decrease reference counter of device
991  */
992 void connman_device_unref(struct connman_device *device)
993 {
994         connman_element_unref(&device->element);
995 }
996
997 const char *__connman_device_get_type(struct connman_device *device)
998 {
999         return type2string(device->type);
1000 }
1001
1002 /**
1003  * connman_device_get_type:
1004  * @device: device structure
1005  *
1006  * Get type of device
1007  */
1008 enum connman_device_type connman_device_get_type(struct connman_device *device)
1009 {
1010         return device->type;
1011 }
1012
1013 /**
1014  * connman_device_get_name:
1015  * @device: device structure
1016  *
1017  * Get unique name of device
1018  */
1019 const char *connman_device_get_name(struct connman_device *device)
1020 {
1021         return device->element.name;
1022 }
1023
1024 /**
1025  * connman_device_get_path:
1026  * @device: device structure
1027  *
1028  * Get path name of device
1029  */
1030 const char *connman_device_get_path(struct connman_device *device)
1031 {
1032         return device->element.path;
1033 }
1034
1035 /**
1036  * connman_device_set_index:
1037  * @device: device structure
1038  * @index: index number
1039  *
1040  * Set index number of device
1041  */
1042 void connman_device_set_index(struct connman_device *device, int index)
1043 {
1044         device->element.index = index;
1045
1046         if (device->ipconfig != NULL) {
1047                 if (index == connman_ipconfig_get_index(device->ipconfig))
1048                         return;
1049
1050                 connman_ipconfig_unref(device->ipconfig);
1051         }
1052
1053         device->ipconfig = connman_ipconfig_create(index);
1054 }
1055
1056 /**
1057  * connman_device_get_index:
1058  * @device: device structure
1059  *
1060  * Get index number of device
1061  */
1062 int connman_device_get_index(struct connman_device *device)
1063 {
1064         return device->element.index;
1065 }
1066
1067 int __connman_device_get_phyindex(struct connman_device *device)
1068 {
1069         return device->phyindex;
1070 }
1071
1072 void __connman_device_set_phyindex(struct connman_device *device,
1073                                                         int phyindex)
1074 {
1075         device->phyindex = phyindex;
1076 }
1077
1078 /**
1079  * connman_device_set_interface:
1080  * @device: device structure
1081  * @interface: interface name
1082  * @control: control interface
1083  *
1084  * Set interface name of device
1085  */
1086 void connman_device_set_interface(struct connman_device *device,
1087                                 const char *interface, const char *control)
1088 {
1089         g_free(device->element.devname);
1090         device->element.devname = g_strdup(interface);
1091
1092         g_free(device->interface);
1093         device->interface = g_strdup(interface);
1094
1095         g_free(device->control);
1096         device->control = g_strdup(control);
1097
1098         if (device->name == NULL) {
1099                 const char *str = type2description(device->type);
1100                 if (str != NULL && device->interface != NULL)
1101                         device->name = g_strdup_printf("%s (%s)", str,
1102                                                         device->interface);
1103         }
1104 }
1105
1106 const char *connman_device_get_control(struct connman_device *device)
1107 {
1108         return device->control;
1109 }
1110
1111 /**
1112  * connman_device_set_ident:
1113  * @device: device structure
1114  * @ident: unique identifier
1115  *
1116  * Set unique identifier of device
1117  */
1118 void connman_device_set_ident(struct connman_device *device,
1119                                                         const char *ident)
1120 {
1121         g_free(device->ident);
1122         device->ident = g_strdup(ident);
1123 }
1124
1125 const char *__connman_device_get_ident(struct connman_device *device)
1126 {
1127         return device->ident;
1128 }
1129
1130 /**
1131  * connman_device_set_mode:
1132  * @device: device structure
1133  * @mode: network mode
1134  *
1135  * Change network mode of device
1136  */
1137 void connman_device_set_mode(struct connman_device *device,
1138                                                 enum connman_device_mode mode)
1139 {
1140         device->mode = mode;
1141 }
1142
1143 /**
1144  * connman_device_get_mode:
1145  * @device: device structure
1146  *
1147  * Get network mode of device
1148  */
1149 enum connman_device_mode connman_device_get_mode(struct connman_device *device)
1150 {
1151         return device->mode;
1152 }
1153
1154 /**
1155  * connman_device_set_secondary:
1156  * @device: device structure
1157  * @secondary: secondary value
1158  *
1159  * Change secondary value of device
1160  */
1161 void connman_device_set_secondary(struct connman_device *device,
1162                                                 connman_bool_t secondary)
1163 {
1164         device->secondary = secondary;
1165 }
1166
1167 /**
1168  * connman_device_get_secondary:
1169  * @device: device structure
1170  *
1171  * Get secondary value of device
1172  */
1173 connman_bool_t connman_device_get_secondary(struct connman_device *device)
1174 {
1175         return device->secondary;
1176 }
1177
1178 /**
1179  * connman_device_set_powered:
1180  * @device: device structure
1181  * @powered: powered state
1182  *
1183  * Change power state of device
1184  */
1185 int connman_device_set_powered(struct connman_device *device,
1186                                                 connman_bool_t powered)
1187 {
1188         enum connman_service_type type;
1189
1190         DBG("driver %p powered %d", device, powered);
1191
1192         if (device->timeout > 0) {
1193                 g_source_remove(device->timeout);
1194                 device->timeout = 0;
1195         }
1196
1197         if (device->pending != NULL) {
1198                 g_dbus_send_reply(connection, device->pending,
1199                                                         DBUS_TYPE_INVALID);
1200
1201                 dbus_message_unref(device->pending);
1202                 device->pending = NULL;
1203         }
1204
1205         if (device->powered == powered)
1206                 return -EALREADY;
1207
1208         device->powered = powered;
1209         device->powered_pending = powered;
1210
1211         type = __connman_device_get_service_type(device);
1212
1213         if (device->powered == TRUE)
1214                 __connman_notifier_enable(type);
1215         else
1216                 __connman_notifier_disable(type);
1217
1218         if (device->registered == FALSE)
1219                 return 0;
1220
1221         powered_changed(device);
1222
1223         if (powered == FALSE)
1224                 return 0;
1225
1226         reset_scan_trigger(device);
1227
1228         if (device->driver->scan)
1229                 device->driver->scan(device);
1230
1231         return 0;
1232 }
1233
1234 int __connman_device_set_blocked(struct connman_device *device,
1235                                                 connman_bool_t blocked)
1236 {
1237         connman_bool_t powered;
1238
1239         DBG("device %p blocked %d", device, blocked);
1240
1241         device->blocked = blocked;
1242
1243         if (device->offlinemode == TRUE)
1244                 return 0;
1245
1246         connman_info("%s {rfkill} blocked %d", device->interface, blocked);
1247
1248         if (blocked == FALSE)
1249                 powered = device->powered_persistent;
1250         else
1251                 powered = FALSE;
1252
1253         return set_powered(device, powered);
1254 }
1255
1256 /**
1257  * connman_device_set_carrier:
1258  * @device: device structure
1259  * @carrier: carrier state
1260  *
1261  * Change carrier state of device (only for device without scanning)
1262  */
1263 int connman_device_set_carrier(struct connman_device *device,
1264                                                 connman_bool_t carrier)
1265 {
1266         DBG("device %p carrier %d", device, carrier);
1267
1268         switch (device->mode) {
1269         case CONNMAN_DEVICE_MODE_UNKNOWN:
1270         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1271         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1272                 return -EINVAL;
1273         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1274                 break;
1275         }
1276
1277         if (device->carrier == carrier)
1278                 return -EALREADY;
1279
1280         device->carrier = carrier;
1281
1282         return set_carrier(device, device->carrier);
1283 }
1284
1285 int __connman_device_scan(struct connman_device *device)
1286 {
1287         if (!device->driver || !device->driver->scan)
1288                 return -EOPNOTSUPP;
1289
1290         if (device->powered == FALSE)
1291                 return -ENOLINK;
1292
1293         reset_scan_trigger(device);
1294
1295         return device->driver->scan(device);
1296 }
1297
1298 int __connman_device_enable(struct connman_device *device)
1299 {
1300         enum connman_service_type type;
1301         int err;
1302
1303         DBG("device %p", device);
1304
1305         if (!device->driver || !device->driver->enable)
1306                 return -EOPNOTSUPP;
1307
1308         if (device->powered_pending == TRUE)
1309                 return -EALREADY;
1310
1311         device->powered_pending = TRUE;
1312
1313         err = device->driver->enable(device);
1314         if (err < 0)
1315                 return err;
1316
1317         device->powered = TRUE;
1318
1319         type = __connman_device_get_service_type(device);
1320         __connman_notifier_enable(type);
1321
1322         return 0;
1323 }
1324
1325 int __connman_device_enable_persistent(struct connman_device *device)
1326 {
1327         DBG("device %p", device);
1328
1329         device->powered_persistent = TRUE;
1330
1331         __connman_storage_save_device(device);
1332
1333         return __connman_device_enable(device);
1334 }
1335
1336 int __connman_device_disable(struct connman_device *device)
1337 {
1338         enum connman_service_type type;
1339         int err;
1340
1341         DBG("device %p", device);
1342
1343         if (!device->driver || !device->driver->disable)
1344                 return -EOPNOTSUPP;
1345
1346         if (device->powered == FALSE)
1347                 return -ENOLINK;
1348
1349         if (device->powered_pending == FALSE)
1350                 return -EALREADY;
1351
1352         device->powered_pending = FALSE;
1353
1354         device->reconnect = FALSE;
1355
1356         clear_scan_trigger(device);
1357
1358         g_hash_table_remove_all(device->networks);
1359
1360         err = device->driver->disable(device);
1361         if (err < 0)
1362                 return err;
1363
1364         device->powered = FALSE;
1365
1366         type = __connman_device_get_service_type(device);
1367         __connman_notifier_disable(type);
1368
1369         return 0;
1370 }
1371
1372 int __connman_device_disable_persistent(struct connman_device *device)
1373 {
1374         DBG("device %p", device);
1375
1376         device->powered_persistent = FALSE;
1377
1378         __connman_storage_save_device(device);
1379
1380         return __connman_device_disable(device);
1381 }
1382
1383 int __connman_device_connect(struct connman_device *device)
1384 {
1385         DBG("device %p", device);
1386
1387         if (device->disconnected == FALSE)
1388                 return -EINVAL;
1389
1390         if (device->driver && device->driver->connect)
1391                 device->driver->connect(device);
1392
1393         return 0;
1394 }
1395
1396 int __connman_device_disconnect(struct connman_device *device)
1397 {
1398         GHashTableIter iter;
1399         gpointer key, value;
1400
1401         DBG("device %p", device);
1402
1403         connman_device_set_disconnected(device, TRUE);
1404
1405         g_hash_table_iter_init(&iter, device->networks);
1406
1407         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1408                 struct connman_network *network = value;
1409
1410                 __connman_network_disconnect(network);
1411         }
1412
1413         if (device->driver && device->driver->disconnect)
1414                 device->driver->disconnect(device);
1415
1416         return 0;
1417 }
1418
1419 static void mark_network_unavailable(gpointer key, gpointer value,
1420                                                         gpointer user_data)
1421 {
1422         struct connman_network *network = value;
1423
1424         if (connman_network_get_connected(network) == TRUE)
1425                 return;
1426
1427         connman_network_set_available(network, FALSE);
1428 }
1429
1430 static gboolean remove_unavailable_network(gpointer key, gpointer value,
1431                                                         gpointer user_data)
1432 {
1433         struct connman_network *network = value;
1434
1435         if (connman_network_get_connected(network) == TRUE)
1436                 return FALSE;
1437
1438         if (connman_network_get_available(network) == TRUE)
1439                 return FALSE;
1440
1441         return TRUE;
1442 }
1443
1444 void __connman_device_cleanup_networks(struct connman_device *device)
1445 {
1446         g_hash_table_foreach_remove(device->networks,
1447                                         remove_unavailable_network, NULL);
1448 }
1449
1450 static void scanning_changed(struct connman_device *device)
1451 {
1452         DBusMessage *signal;
1453         DBusMessageIter entry, value;
1454         const char *key = "Scanning";
1455
1456         signal = dbus_message_new_signal(device->element.path,
1457                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1458         if (signal == NULL)
1459                 return;
1460
1461         dbus_message_iter_init_append(signal, &entry);
1462
1463         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1464
1465         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1466                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
1467         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
1468                                                         &device->scanning);
1469         dbus_message_iter_close_container(&entry, &value);
1470
1471         g_dbus_send_message(connection, signal);
1472 }
1473
1474 static void mark_network_available(gpointer key, gpointer value,
1475                                                 gpointer user_data)
1476 {
1477         struct connman_network *network = value;
1478
1479         connman_network_set_available(network, TRUE);
1480 }
1481
1482 void connman_device_cleanup_scanning(struct connman_device *device)
1483 {
1484         device->scanning = FALSE;
1485
1486         scanning_changed(device);
1487
1488         g_hash_table_foreach(device->networks,
1489                                 mark_network_available, NULL);
1490 }
1491
1492 /**
1493  * connman_device_set_scanning:
1494  * @device: device structure
1495  * @scanning: scanning state
1496  *
1497  * Change scanning state of device
1498  */
1499 int connman_device_set_scanning(struct connman_device *device,
1500                                                 connman_bool_t scanning)
1501 {
1502         DBG("device %p scanning %d", device, scanning);
1503
1504         if (!device->driver || !device->driver->scan)
1505                 return -EINVAL;
1506
1507         if (device->scanning == scanning)
1508                 return -EALREADY;
1509
1510         device->scanning = scanning;
1511
1512         scanning_changed(device);
1513
1514         if (scanning == TRUE) {
1515                 reset_scan_trigger(device);
1516
1517                 g_hash_table_foreach(device->networks,
1518                                         mark_network_unavailable, NULL);
1519
1520                 return 0;
1521         }
1522
1523         __connman_device_cleanup_networks(device);
1524
1525         if (device->connections > 0)
1526                 return 0;
1527
1528         if (device->disconnected == TRUE)
1529                 return 0;
1530
1531         __connman_service_auto_connect();
1532
1533         return 0;
1534 }
1535
1536 /**
1537  * connman_device_set_disconnected:
1538  * @device: device structure
1539  * @disconnected: disconnected state
1540  *
1541  * Change disconnected state of device (only for device with networks)
1542  */
1543 int connman_device_set_disconnected(struct connman_device *device,
1544                                                 connman_bool_t disconnected)
1545 {
1546         DBG("device %p disconnected %d", device, disconnected);
1547
1548         switch (device->mode) {
1549         case CONNMAN_DEVICE_MODE_UNKNOWN:
1550         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1551                 return -EINVAL;
1552         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1553         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1554                 break;
1555         }
1556
1557         if (device->disconnected == disconnected)
1558                 return -EALREADY;
1559
1560         device->disconnected = disconnected;
1561
1562         if (disconnected == TRUE)
1563                 force_scan_trigger(device);
1564
1565         return 0;
1566 }
1567
1568 /**
1569  * connman_device_get_disconnected:
1570  * @device: device structure
1571  *
1572  * Get device disconnected state
1573  */
1574 connman_bool_t connman_device_get_disconnected(struct connman_device *device)
1575 {
1576         return device->disconnected;
1577 }
1578
1579 /**
1580  * connman_device_set_connected:
1581  * @device: device structure
1582  * @connected: connected state
1583  *
1584  * Change connected state of device (for Ethernet like devices)
1585  */
1586 int connman_device_set_connected(struct connman_device *device,
1587                                                 connman_bool_t connected)
1588 {
1589         DBG("device %p connected %d", device, connected);
1590
1591         switch (device->mode) {
1592         case CONNMAN_DEVICE_MODE_UNKNOWN:
1593         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1594         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1595                 return -EINVAL;
1596         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1597                 break;
1598         }
1599
1600         if (device->carrier == FALSE)
1601                 return -ENOTCONN;
1602
1603         return set_connected(device, connected);
1604 }
1605
1606 /**
1607  * connman_device_set_string:
1608  * @device: device structure
1609  * @key: unique identifier
1610  * @value: string value
1611  *
1612  * Set string value for specific key
1613  */
1614 int connman_device_set_string(struct connman_device *device,
1615                                         const char *key, const char *value)
1616 {
1617         DBG("device %p key %s value %s", device, key, value);
1618
1619         if (g_str_equal(key, "Address") == TRUE) {
1620                 g_free(device->address);
1621                 device->address = g_strdup(value);
1622         } else if (g_str_equal(key, "Name") == TRUE) {
1623                 g_free(device->name);
1624                 device->name = g_strdup(value);
1625         } else if (g_str_equal(key, "Node") == TRUE) {
1626                 g_free(device->node);
1627                 device->node = g_strdup(value);
1628         }
1629
1630         return connman_element_set_string(&device->element, key, value);
1631 }
1632
1633 /**
1634  * connman_device_get_string:
1635  * @device: device structure
1636  * @key: unique identifier
1637  *
1638  * Get string value for specific key
1639  */
1640 const char *connman_device_get_string(struct connman_device *device,
1641                                                         const char *key)
1642 {
1643         DBG("device %p key %s", device, key);
1644
1645         if (g_str_equal(key, "Address") == TRUE)
1646                 return device->address;
1647         else if (g_str_equal(key, "Name") == TRUE)
1648                 return device->name;
1649         else if (g_str_equal(key, "Node") == TRUE)
1650                 return device->node;
1651
1652         return connman_element_get_string(&device->element, key);
1653 }
1654
1655 static void set_offlinemode(struct connman_element *element, gpointer user_data)
1656 {
1657         struct connman_device *device = element->device;
1658         connman_bool_t offlinemode = GPOINTER_TO_UINT(user_data);
1659         connman_bool_t powered;
1660
1661         DBG("element %p name %s", element, element->name);
1662
1663         if (device == NULL)
1664                 return;
1665
1666         device->offlinemode = offlinemode;
1667
1668         powered = (offlinemode == TRUE) ? FALSE : TRUE;
1669
1670         if (device->powered == powered)
1671                 return;
1672
1673         if (device->powered_persistent == FALSE)
1674                 powered = FALSE;
1675
1676         set_powered(device, powered);
1677 }
1678
1679 int __connman_device_set_offlinemode(connman_bool_t offlinemode)
1680 {
1681         DBG("offlinmode %d", offlinemode);
1682
1683         __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
1684                         set_offlinemode, GUINT_TO_POINTER(offlinemode));
1685
1686         __connman_notifier_offlinemode(offlinemode);
1687
1688         return 0;
1689 }
1690
1691 void __connman_device_increase_connections(struct connman_device *device)
1692 {
1693         device->connections++;
1694 }
1695
1696 void __connman_device_decrease_connections(struct connman_device *device)
1697 {
1698         device->connections--;
1699 }
1700
1701 /**
1702  * connman_device_add_network:
1703  * @device: device structure
1704  * @network: network structure
1705  *
1706  * Add new network to the device
1707  */
1708 int connman_device_add_network(struct connman_device *device,
1709                                         struct connman_network *network)
1710 {
1711         const char *identifier = connman_network_get_identifier(network);
1712         int err;
1713
1714         DBG("device %p network %p", device, network);
1715
1716         switch (device->mode) {
1717         case CONNMAN_DEVICE_MODE_UNKNOWN:
1718         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1719                 return -EINVAL;
1720         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1721         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1722                 break;
1723         }
1724
1725         __connman_network_set_device(network, device);
1726
1727         err = connman_element_register((struct connman_element *) network,
1728                                                         &device->element);
1729         if (err < 0) {
1730                 __connman_network_set_device(network, NULL);
1731                 return err;
1732         }
1733
1734         g_hash_table_insert(device->networks, g_strdup(identifier),
1735                                                                 network);
1736
1737         return 0;
1738 }
1739
1740 /**
1741  * connman_device_get_network:
1742  * @device: device structure
1743  * @identifier: network identifier
1744  *
1745  * Get network for given identifier
1746  */
1747 struct connman_network *connman_device_get_network(struct connman_device *device,
1748                                                         const char *identifier)
1749 {
1750         DBG("device %p identifier %s", device, identifier);
1751
1752         return g_hash_table_lookup(device->networks, identifier);
1753 }
1754
1755 /**
1756  * connman_device_remove_network:
1757  * @device: device structure
1758  * @identifier: network identifier
1759  *
1760  * Remove network for given identifier
1761  */
1762 int connman_device_remove_network(struct connman_device *device,
1763                                                         const char *identifier)
1764 {
1765         DBG("device %p identifier %s", device, identifier);
1766
1767         g_hash_table_remove(device->networks, identifier);
1768
1769         return 0;
1770 }
1771
1772 void __connman_device_set_network(struct connman_device *device,
1773                                         struct connman_network *network)
1774 {
1775         const char *name;
1776
1777         if (device->network == network)
1778                 return;
1779
1780         if (device->network != NULL)
1781                 connman_network_unref(device->network);
1782
1783         if (network != NULL) {
1784                 name = connman_network_get_string(network,
1785                                                 CONNMAN_PROPERTY_ID_NAME);
1786                 g_free(device->last_network);
1787                 device->last_network = g_strdup(name);
1788
1789                 device->network = connman_network_ref(network);
1790         } else {
1791                 g_free(device->last_network);
1792                 device->last_network = NULL;
1793
1794                 device->network = NULL;
1795         }
1796 }
1797
1798 void __connman_device_set_reconnect(struct connman_device *device,
1799                                                 connman_bool_t reconnect)
1800 {
1801         device->reconnect = reconnect;
1802 }
1803
1804 connman_bool_t  __connman_device_get_reconnect(
1805                                 struct connman_device *device)
1806 {
1807         return device->reconnect;
1808 }
1809
1810 /**
1811  * connman_device_register:
1812  * @device: device structure
1813  *
1814  * Register device with the system
1815  */
1816 int connman_device_register(struct connman_device *device)
1817 {
1818         __connman_storage_load_device(device);
1819
1820         device->offlinemode = __connman_profile_get_offlinemode();
1821
1822         return connman_element_register(&device->element, NULL);
1823 }
1824
1825 /**
1826  * connman_device_unregister:
1827  * @device: device structure
1828  *
1829  * Unregister device with the system
1830  */
1831 void connman_device_unregister(struct connman_device *device)
1832 {
1833         __connman_storage_save_device(device);
1834
1835         connman_element_unregister(&device->element);
1836 }
1837
1838 /**
1839  * connman_device_get_data:
1840  * @device: device structure
1841  *
1842  * Get private device data pointer
1843  */
1844 void *connman_device_get_data(struct connman_device *device)
1845 {
1846         return device->driver_data;
1847 }
1848
1849 /**
1850  * connman_device_set_data:
1851  * @device: device structure
1852  * @data: data pointer
1853  *
1854  * Set private device data pointer
1855  */
1856 void connman_device_set_data(struct connman_device *device, void *data)
1857 {
1858         device->driver_data = data;
1859 }
1860
1861 static gboolean match_driver(struct connman_device *device,
1862                                         struct connman_device_driver *driver)
1863 {
1864         if (device->type == driver->type ||
1865                         driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1866                 return TRUE;
1867
1868         return FALSE;
1869 }
1870
1871 static int device_probe(struct connman_element *element)
1872 {
1873         struct connman_device *device = element->device;
1874         GSList *list;
1875
1876         DBG("element %p name %s", element, element->name);
1877
1878         if (device == NULL)
1879                 return -ENODEV;
1880
1881         if (device->driver != NULL)
1882                 return -EALREADY;
1883
1884         for (list = driver_list; list; list = list->next) {
1885                 struct connman_device_driver *driver = list->data;
1886
1887                 if (match_driver(device, driver) == FALSE)
1888                         continue;
1889
1890                 DBG("driver %p name %s", driver, driver->name);
1891
1892                 if (driver->probe(device) == 0) {
1893                         device->driver = driver;
1894                         break;
1895                 }
1896         }
1897
1898         if (device->driver == NULL)
1899                 return -ENODEV;
1900
1901         return setup_device(device);
1902 }
1903
1904 static void device_remove(struct connman_element *element)
1905 {
1906         struct connman_device *device = element->device;
1907
1908         DBG("element %p name %s", element, element->name);
1909
1910         if (device == NULL)
1911                 return;
1912
1913         if (device->driver == NULL)
1914                 return;
1915
1916         remove_device(device);
1917 }
1918
1919 static struct connman_driver device_driver = {
1920         .name           = "device",
1921         .type           = CONNMAN_ELEMENT_TYPE_DEVICE,
1922         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
1923         .probe          = device_probe,
1924         .remove         = device_remove,
1925 };
1926
1927 static int device_load(struct connman_device *device)
1928 {
1929         const char *ident = __connman_profile_active_ident();
1930         GKeyFile *keyfile;
1931         GError *error = NULL;
1932         gchar *identifier;
1933         connman_bool_t powered;
1934         int val;
1935
1936         DBG("device %p", device);
1937
1938         keyfile = __connman_storage_open(ident);
1939         if (keyfile == NULL)
1940                 return 0;
1941
1942         identifier = g_strdup_printf("device_%s", device->element.name);
1943         if (identifier == NULL)
1944                 goto done;
1945
1946         powered = g_key_file_get_boolean(keyfile, identifier,
1947                                                 "Powered", &error);
1948         if (error == NULL)
1949                 device->powered_persistent = powered;
1950         g_clear_error(&error);
1951
1952         switch (device->mode) {
1953         case CONNMAN_DEVICE_MODE_UNKNOWN:
1954         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1955                 break;
1956         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1957         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1958                 val = g_key_file_get_integer(keyfile, identifier,
1959                                                 "ScanInterval", &error);
1960                 if (error == NULL && val > 0)
1961                         device->scan_interval = val;
1962                 g_clear_error(&error);
1963                 break;
1964         }
1965
1966 done:
1967         g_free(identifier);
1968
1969         __connman_storage_close(ident, keyfile, FALSE);
1970
1971         return 0;
1972 }
1973
1974 static int device_save(struct connman_device *device)
1975 {
1976         const char *ident = __connman_profile_active_ident();
1977         GKeyFile *keyfile;
1978         gchar *identifier;
1979
1980         DBG("device %p", device);
1981
1982         keyfile = __connman_storage_open(ident);
1983         if (keyfile == NULL)
1984                 return 0;
1985
1986         identifier = g_strdup_printf("device_%s", device->element.name);
1987         if (identifier == NULL)
1988                 goto done;
1989
1990         g_key_file_set_boolean(keyfile, identifier,
1991                                         "Powered", device->powered_persistent);
1992
1993         switch (device->mode) {
1994         case CONNMAN_DEVICE_MODE_UNKNOWN:
1995         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1996                 break;
1997         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1998         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1999                 if (device->scan_interval > 0)
2000                         g_key_file_set_integer(keyfile, identifier,
2001                                         "ScanInterval", device->scan_interval);
2002                 break;
2003         }
2004
2005 done:
2006         g_free(identifier);
2007
2008         __connman_storage_close(ident, keyfile, TRUE);
2009
2010         return 0;
2011 }
2012
2013 static struct connman_storage device_storage = {
2014         .name           = "device",
2015         .priority       = CONNMAN_STORAGE_PRIORITY_LOW,
2016         .device_load    = device_load,
2017         .device_save    = device_save,
2018 };
2019
2020 int __connman_device_init(void)
2021 {
2022         DBG("");
2023
2024         connection = connman_dbus_get_connection();
2025
2026         if (connman_storage_register(&device_storage) < 0)
2027                 connman_error("Failed to register device storage");
2028
2029         return connman_driver_register(&device_driver);
2030 }
2031
2032 void __connman_device_cleanup(void)
2033 {
2034         DBG("");
2035
2036         connman_driver_unregister(&device_driver);
2037
2038         connman_storage_unregister(&device_storage);
2039
2040         dbus_connection_unref(connection);
2041 }