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