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