Register default device and network storage drivers
[connman] / 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 <gdbus.h>
28
29 #include "connman.h"
30
31 struct connman_device {
32         struct connman_element element;
33         enum connman_device_type type;
34         enum connman_device_mode mode;
35         enum connman_device_policy policy;
36         gboolean powered;
37         gboolean carrier;
38         gboolean scanning;
39         char *path;
40         char *interface;
41
42         struct connman_device_driver *driver;
43         void *driver_data;
44
45         connman_bool_t registered;
46
47         GHashTable *networks;
48 };
49
50 static const char *type2description(enum connman_device_type type)
51 {
52         switch (type) {
53         case CONNMAN_DEVICE_TYPE_UNKNOWN:
54         case CONNMAN_DEVICE_TYPE_VENDOR:
55                 break;
56         case CONNMAN_DEVICE_TYPE_ETHERNET:
57                 return "Ethernet";
58         case CONNMAN_DEVICE_TYPE_WIFI:
59                 return "Wireless";
60         case CONNMAN_DEVICE_TYPE_WIMAX:
61                 return "WiMAX";
62         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
63                 return "Bluetooth";
64         case CONNMAN_DEVICE_TYPE_HSO:
65         case CONNMAN_DEVICE_TYPE_NOZOMI:
66         case CONNMAN_DEVICE_TYPE_HUAWEI:
67         case CONNMAN_DEVICE_TYPE_NOVATEL:
68                 return "Cellular";
69         }
70
71         return NULL;
72 }
73
74 static const char *type2string(enum connman_device_type type)
75 {
76         switch (type) {
77         case CONNMAN_DEVICE_TYPE_UNKNOWN:
78         case CONNMAN_DEVICE_TYPE_VENDOR:
79                 break;
80         case CONNMAN_DEVICE_TYPE_ETHERNET:
81                 return "ethernet";
82         case CONNMAN_DEVICE_TYPE_WIFI:
83                 return "wifi";
84         case CONNMAN_DEVICE_TYPE_WIMAX:
85                 return "wimax";
86         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
87                 return "bluetooth";
88         case CONNMAN_DEVICE_TYPE_HSO:
89         case CONNMAN_DEVICE_TYPE_HUAWEI:
90         case CONNMAN_DEVICE_TYPE_NOZOMI:
91         case CONNMAN_DEVICE_TYPE_NOVATEL:
92                 return "cellular";
93         }
94
95         return NULL;
96 }
97
98 static const char *policy2string(enum connman_device_policy policy)
99 {
100         switch (policy) {
101         case CONNMAN_DEVICE_POLICY_UNKNOWN:
102                 break;
103         case CONNMAN_DEVICE_POLICY_IGNORE:
104                 return "ignore";
105         case CONNMAN_DEVICE_POLICY_OFF:
106                 return "off";
107         case CONNMAN_DEVICE_POLICY_AUTO:
108                 return "auto";
109         case CONNMAN_DEVICE_POLICY_MANUAL:
110                 return "manual";
111         }
112
113         return NULL;
114 }
115
116 static enum connman_device_policy string2policy(const char *policy)
117 {
118         if (g_str_equal(policy, "ignore") == TRUE)
119                 return CONNMAN_DEVICE_POLICY_IGNORE;
120         else if (g_str_equal(policy, "off") == TRUE)
121                 return CONNMAN_DEVICE_POLICY_OFF;
122         else if (g_str_equal(policy, "auto") == TRUE)
123                 return CONNMAN_DEVICE_POLICY_AUTO;
124         else if (g_str_equal(policy, "manual") == TRUE)
125                 return CONNMAN_DEVICE_POLICY_MANUAL;
126         else
127                 return CONNMAN_DEVICE_POLICY_UNKNOWN;
128 }
129
130 static int set_powered(struct connman_device *device, gboolean powered)
131 {
132         struct connman_device_driver *driver = device->driver;
133         int err;
134
135         DBG("device %p powered %d", device, powered);
136
137         if (!driver)
138                 return -EINVAL;
139
140         if (powered == TRUE) {
141                 if (driver->enable)
142                         err = driver->enable(device);
143                 else
144                         err = -EINVAL;
145         } else {
146                 g_hash_table_remove_all(device->networks);
147
148                 if (driver->disable)
149                         err = driver->disable(device);
150                 else
151                         err = -EINVAL;
152         }
153
154         return err;
155 }
156
157 static int set_policy(DBusConnection *connection,
158                                 struct connman_device *device,
159                                         enum connman_device_policy policy)
160 {
161         DBusMessage *signal;
162         DBusMessageIter entry, value;
163         const char *str, *key = "Policy";
164         int err = 0;
165
166         DBG("device %p policy %d", device, policy);
167
168         if (device->policy == policy)
169                 return 0;
170
171         switch (policy) {
172         case CONNMAN_DEVICE_POLICY_UNKNOWN:
173                 return -EINVAL;
174         case CONNMAN_DEVICE_POLICY_IGNORE:
175                 break;
176         case CONNMAN_DEVICE_POLICY_OFF:
177                 if (device->powered == TRUE)
178                         err = set_powered(device, FALSE);
179                 break;
180         case CONNMAN_DEVICE_POLICY_AUTO:
181         case CONNMAN_DEVICE_POLICY_MANUAL:
182                 if (device->powered == FALSE)
183                         err = set_powered(device, TRUE);
184                 break;
185         }
186
187         if (err < 0)
188                 return err;
189
190         device->policy = policy;
191
192         signal = dbus_message_new_signal(device->element.path,
193                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
194         if (signal == NULL)
195                 return 0;
196
197         dbus_message_iter_init_append(signal, &entry);
198
199         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
200
201         str = policy2string(policy);
202
203         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
204                                         DBUS_TYPE_STRING_AS_STRING, &value);
205         dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
206         dbus_message_iter_close_container(&entry, &value);
207
208         g_dbus_send_message(connection, signal);
209
210         return 0;
211 }
212
213 static void append_networks(struct connman_device *device,
214                                                 DBusMessageIter *entry)
215 {
216         DBusMessageIter value, iter;
217         const char *key = "Networks";
218
219         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
220
221         dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
222                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
223                                                                 &value);
224
225         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
226                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
227         __connman_element_list((struct connman_element *) device,
228                                         CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
229         dbus_message_iter_close_container(&value, &iter);
230
231         dbus_message_iter_close_container(entry, &value);
232 }
233
234 static DBusMessage *get_properties(DBusConnection *conn,
235                                         DBusMessage *msg, void *data)
236 {
237         struct connman_device *device = data;
238         DBusMessage *reply;
239         DBusMessageIter array, dict, entry;
240         const char *str;
241
242         DBG("conn %p", conn);
243
244         reply = dbus_message_new_method_return(msg);
245         if (reply == NULL)
246                 return NULL;
247
248         dbus_message_iter_init_append(reply, &array);
249
250         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
251                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
252                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
253                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
254
255         str = type2description(device->type);
256         if (str != NULL && device->interface != NULL) {
257                 char *name = g_strdup_printf("%s (%s)", str, device->interface);
258                 if (name != NULL)
259                         connman_dbus_dict_append_variant(&dict, "Name",
260                                                 DBUS_TYPE_STRING, &name);
261                 g_free(name);
262         }
263
264         str = type2string(device->type);
265         if (str != NULL)
266                 connman_dbus_dict_append_variant(&dict, "Type",
267                                                 DBUS_TYPE_STRING, &str);
268
269         if (device->interface != NULL)
270                 connman_dbus_dict_append_variant(&dict, "Interface",
271                                         DBUS_TYPE_STRING, &device->interface);
272
273         str = policy2string(device->policy);
274         if (str != NULL)
275                 connman_dbus_dict_append_variant(&dict, "Policy",
276                                                 DBUS_TYPE_STRING, &str);
277
278         connman_dbus_dict_append_variant(&dict, "Powered",
279                                         DBUS_TYPE_BOOLEAN, &device->powered);
280
281         if (device->driver && device->driver->scan)
282                 connman_dbus_dict_append_variant(&dict, "Scanning",
283                                         DBUS_TYPE_BOOLEAN, &device->scanning);
284
285         switch (device->mode) {
286         case CONNMAN_DEVICE_MODE_UNKNOWN:
287         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
288                 break;
289         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
290         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
291                 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
292                                                                 NULL, &entry);
293                 append_networks(device, &entry);
294                 dbus_message_iter_close_container(&dict, &entry);
295                 break;
296         }
297
298         dbus_message_iter_close_container(&array, &dict);
299
300         return reply;
301 }
302
303 static DBusMessage *set_property(DBusConnection *conn,
304                                         DBusMessage *msg, void *data)
305 {
306         struct connman_device *device = data;
307         DBusMessageIter iter, value;
308         const char *name;
309
310         DBG("conn %p", conn);
311
312         if (dbus_message_iter_init(msg, &iter) == FALSE)
313                 return __connman_error_invalid_arguments(msg);
314
315         dbus_message_iter_get_basic(&iter, &name);
316         dbus_message_iter_next(&iter);
317         dbus_message_iter_recurse(&iter, &value);
318
319         if (__connman_security_check_privileges(msg) < 0)
320                 return __connman_error_permission_denied(msg);
321
322         if (g_str_equal(name, "Powered") == TRUE) {
323                 gboolean powered;
324                 int err;
325
326                 dbus_message_iter_get_basic(&value, &powered);
327
328                 if (device->powered == powered)
329                         return __connman_error_invalid_arguments(msg);
330
331                 err = set_powered(device, powered);
332                 if (err < 0 && err != -EINPROGRESS)
333                         return __connman_error_failed(msg);
334         } else if (g_str_equal(name, "Policy") == TRUE) {
335                 enum connman_device_policy policy;
336                 const char *str;
337                 int err;
338
339                 dbus_message_iter_get_basic(&value, &str);
340                 policy = string2policy(str);
341                 if (policy == CONNMAN_DEVICE_POLICY_UNKNOWN)
342                         return __connman_error_invalid_arguments(msg);
343
344                 err = set_policy(conn, device, policy);
345                 if (err < 0)
346                         return __connman_error_failed(msg);
347         }
348
349         __connman_element_store(&device->element);
350
351         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
352 }
353
354 static DBusMessage *create_network(DBusConnection *conn,
355                                         DBusMessage *msg, void *data)
356 {
357         DBG("conn %p", conn);
358
359         if (__connman_security_check_privileges(msg) < 0)
360                 return __connman_error_permission_denied(msg);
361
362         return __connman_error_invalid_arguments(msg);
363 }
364
365 static DBusMessage *remove_network(DBusConnection *conn,
366                                         DBusMessage *msg, void *data)
367 {
368         DBG("conn %p", conn);
369
370         if (__connman_security_check_privileges(msg) < 0)
371                 return __connman_error_permission_denied(msg);
372
373         return __connman_error_invalid_arguments(msg);
374 }
375
376 static DBusMessage *propose_scan(DBusConnection *conn,
377                                         DBusMessage *msg, void *data)
378 {
379         struct connman_device *device = data;
380         int err;
381
382         DBG("conn %p", conn);
383
384         switch (device->mode) {
385         case CONNMAN_DEVICE_MODE_UNKNOWN:
386         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
387                 return __connman_error_not_supported(msg);
388         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
389         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
390                 break;
391         }
392
393         if (!device->driver || !device->driver->scan)
394                 return __connman_error_not_supported(msg);
395
396         err = device->driver->scan(device);
397         if (err < 0)
398                 return __connman_error_failed(msg);
399
400         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
401 }
402
403 static GDBusMethodTable device_methods[] = {
404         { "GetProperties", "",      "a{sv}", get_properties },
405         { "SetProperty",   "sv",    "",      set_property   },
406         { "CreateNetwork", "a{sv}", "o",     create_network },
407         { "RemoveNetwork", "o",     "",      remove_network },
408         { "ProposeScan",   "",      "",      propose_scan   },
409         { },
410 };
411
412 static GDBusSignalTable device_signals[] = {
413         { "PropertyChanged", "sv" },
414         { },
415 };
416
417 static DBusConnection *connection;
418
419 static void append_devices(DBusMessageIter *entry)
420 {
421         DBusMessageIter value, iter;
422         const char *key = "Devices";
423
424         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
425
426         dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
427                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
428                                                                 &value);
429
430         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
431                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
432         __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
433         dbus_message_iter_close_container(&value, &iter);
434
435         dbus_message_iter_close_container(entry, &value);
436 }
437
438 static void emit_devices_signal(void)
439 {
440         DBusMessage *signal;
441         DBusMessageIter entry;
442
443         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
444                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
445         if (signal == NULL)
446                 return;
447
448         dbus_message_iter_init_append(signal, &entry);
449
450         append_devices(&entry);
451
452         g_dbus_send_message(connection, signal);
453 }
454
455 static int register_interface(struct connman_element *element)
456 {
457         struct connman_device *device = element->device;
458
459         DBG("element %p name %s", element, element->name);
460
461         if (g_dbus_register_interface(connection, element->path,
462                                         CONNMAN_DEVICE_INTERFACE,
463                                         device_methods, device_signals,
464                                         NULL, device, NULL) == FALSE) {
465                 connman_error("Failed to register %s device", element->path);
466                 return -EIO;
467         }
468
469         device->registered = TRUE;
470
471         emit_devices_signal();
472
473         return 0;
474 }
475
476 static void unregister_interface(struct connman_element *element)
477 {
478         struct connman_device *device = element->device;
479
480         DBG("element %p name %s", element, element->name);
481
482         device->registered = FALSE;
483
484         emit_devices_signal();
485
486         g_dbus_unregister_interface(connection, element->path,
487                                                 CONNMAN_DEVICE_INTERFACE);
488 }
489
490 static void device_enable(struct connman_device *device)
491 {
492         DBG("device %p", device);
493
494         if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE ||
495                                 device->policy == CONNMAN_DEVICE_POLICY_OFF)
496                 return;
497
498         if (device->powered == TRUE)
499                 return;
500
501         if (device->driver->enable)
502                 device->driver->enable(device);
503 }
504
505 static void device_disable(struct connman_device *device)
506 {
507         DBG("device %p", device);
508
509         if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE)
510                 return;
511
512         if (device->powered == FALSE)
513                 return;
514
515         g_hash_table_remove_all(device->networks);
516
517         if (device->driver->disable)
518                 device->driver->disable(device);
519 }
520
521 static int setup_device(struct connman_device *device)
522 {
523         int err;
524
525         DBG("device %p", device);
526
527         err = register_interface(&device->element);
528         if (err < 0) {
529                 if (device->driver->remove)
530                         device->driver->remove(device);
531                 device->driver = NULL;
532                 return err;
533         }
534
535         device_enable(device);
536
537         return 0;
538 }
539
540 static void probe_driver(struct connman_element *element, gpointer user_data)
541 {
542         struct connman_device_driver *driver = user_data;
543
544         DBG("element %p name %s", element, element->name);
545
546         if (element->device == NULL)
547                 return;
548
549         if (driver->probe(element->device) < 0)
550                 return;
551
552         element->device->driver = driver;
553
554         setup_device(element->device);
555 }
556
557 static void remove_device(struct connman_device *device)
558 {
559         DBG("device %p", device);
560
561         device_disable(device);
562
563         unregister_interface(&device->element);
564
565         if (device->driver->remove)
566                 device->driver->remove(device);
567
568         device->driver = NULL;
569 }
570
571 static void remove_driver(struct connman_element *element, gpointer user_data)
572 {
573         struct connman_device_driver *driver = user_data;
574
575         DBG("element %p name %s", element, element->name);
576
577         if (element->device == NULL)
578                 return;
579
580         if (element->device->driver == driver)
581                 remove_device(element->device);
582 }
583
584 connman_bool_t __connman_device_has_driver(struct connman_device *device)
585 {
586         if (device->driver == NULL)
587                 return FALSE;
588
589         return device->registered;
590 }
591
592 static GSList *driver_list = NULL;
593
594 static gint compare_priority(gconstpointer a, gconstpointer b)
595 {
596         const struct connman_device_driver *driver1 = a;
597         const struct connman_device_driver *driver2 = b;
598
599         return driver2->priority - driver1->priority;
600 }
601
602 /**
603  * connman_device_driver_register:
604  * @driver: device driver definition
605  *
606  * Register a new device driver
607  *
608  * Returns: %0 on success
609  */
610 int connman_device_driver_register(struct connman_device_driver *driver)
611 {
612         DBG("driver %p name %s", driver, driver->name);
613
614         driver_list = g_slist_insert_sorted(driver_list, driver,
615                                                         compare_priority);
616
617         __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
618                                                 probe_driver, driver);
619
620         return 0;
621 }
622
623 /**
624  * connman_device_driver_unregister:
625  * @driver: device driver definition
626  *
627  * Remove a previously registered device driver
628  */
629 void connman_device_driver_unregister(struct connman_device_driver *driver)
630 {
631         DBG("driver %p name %s", driver, driver->name);
632
633         driver_list = g_slist_remove(driver_list, driver);
634
635         __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
636                                                 remove_driver, driver);
637 }
638
639 static void unregister_network(gpointer data)
640 {
641         struct connman_network *network = data;
642
643         DBG("network %p", network);
644
645         connman_element_unregister((struct connman_element *) network);
646
647         connman_network_unref(network);
648 }
649
650 static void device_destruct(struct connman_element *element)
651 {
652         struct connman_device *device = element->device;
653
654         DBG("element %p name %s", element, element->name);
655
656         g_free(device->path);
657         g_free(device->interface);
658
659         g_hash_table_destroy(device->networks);
660         device->networks = NULL;
661 }
662
663 /**
664  * connman_device_create:
665  * @node: device node name (for example an address)
666  * @type: device type
667  *
668  * Allocate a new device of given #type and assign the #node name to it.
669  *
670  * Returns: a newly-allocated #connman_device structure
671  */
672 struct connman_device *connman_device_create(const char *node,
673                                                 enum connman_device_type type)
674 {
675         struct connman_device *device;
676
677         DBG("node %s type %d", node, type);
678
679         device = g_try_new0(struct connman_device, 1);
680         if (device == NULL)
681                 return NULL;
682
683         DBG("device %p", device);
684
685         device->element.refcount = 1;
686
687         device->element.name = g_strdup(node);
688         device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
689         device->element.index = -1;
690
691         switch (type) {
692         case CONNMAN_DEVICE_TYPE_UNKNOWN:
693         case CONNMAN_DEVICE_TYPE_VENDOR:
694         case CONNMAN_DEVICE_TYPE_WIFI:
695         case CONNMAN_DEVICE_TYPE_WIMAX:
696         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
697         case CONNMAN_DEVICE_TYPE_HSO:
698         case CONNMAN_DEVICE_TYPE_NOZOMI:
699         case CONNMAN_DEVICE_TYPE_HUAWEI:
700         case CONNMAN_DEVICE_TYPE_NOVATEL:
701                 device->element.subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
702                 break;
703         case CONNMAN_DEVICE_TYPE_ETHERNET:
704                 device->element.subtype = CONNMAN_ELEMENT_SUBTYPE_ETHERNET;
705                 break;
706         }
707
708         device->element.device = device;
709         device->element.destruct = device_destruct;
710
711         device->type   = type;
712         device->mode   = CONNMAN_DEVICE_MODE_UNKNOWN;
713         device->policy = CONNMAN_DEVICE_POLICY_AUTO;
714
715         device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
716                                                 g_free, unregister_network);
717
718         return device;
719 }
720
721 /**
722  * connman_device_ref:
723  * @device: device structure
724  *
725  * Increase reference counter of device
726  */
727 struct connman_device *connman_device_ref(struct connman_device *device)
728 {
729         if (connman_element_ref(&device->element) == NULL)
730                 return NULL;
731
732         return device;
733 }
734
735 /**
736  * connman_device_unref:
737  * @device: device structure
738  *
739  * Decrease reference counter of device
740  */
741 void connman_device_unref(struct connman_device *device)
742 {
743         connman_element_unref(&device->element);
744 }
745
746 /**
747  * connman_device_set_path:
748  * @device: device structure
749  * @path: path name
750  *
751  * Set path name of device
752  */
753 void connman_device_set_path(struct connman_device *device, const char *path)
754 {
755         g_free(device->element.devpath);
756         device->element.devpath = g_strdup(path);
757
758         g_free(device->path);
759         device->path = g_strdup(path);
760 }
761
762 /**
763  * connman_device_get_path:
764  * @device: device structure
765  *
766  * Get path name of device
767  */
768 const char *connman_device_get_path(struct connman_device *device)
769 {
770         return device->path;
771 }
772
773 /**
774  * connman_device_set_index:
775  * @device: device structure
776  * @index: index number
777  *
778  * Set index number of device
779  */
780 void connman_device_set_index(struct connman_device *device, int index)
781 {
782         device->element.index = index;
783 }
784
785 /**
786  * connman_device_get_index:
787  * @device: device structure
788  *
789  * Get index number of device
790  */
791 int connman_device_get_index(struct connman_device *device)
792 {
793         return device->element.index;
794 }
795
796 /**
797  * connman_device_set_interface:
798  * @device: device structure
799  * @interface: interface name
800  *
801  * Set interface name of device
802  */
803 void connman_device_set_interface(struct connman_device *device,
804                                                         const char *interface)
805 {
806         g_free(device->element.devname);
807         device->element.devname = g_strdup(interface);
808
809         g_free(device->interface);
810         device->interface = g_strdup(interface);
811 }
812
813 /**
814  * connman_device_get_interface:
815  * @device: device structure
816  *
817  * Get interface name of device
818  */
819 const char *connman_device_get_interface(struct connman_device *device)
820 {
821         return device->interface;
822 }
823
824 /**
825  * connman_device_set_policy:
826  * @device: device structure
827  * @policy: power and connection policy
828  *
829  * Change power and connection policy of device
830  */
831 void connman_device_set_policy(struct connman_device *device,
832                                         enum connman_device_policy policy)
833 {
834         device->policy = policy;
835 }
836
837 /**
838  * connman_device_set_mode:
839  * @device: device structure
840  * @mode: network mode
841  *
842  * Change network mode of device
843  */
844 void connman_device_set_mode(struct connman_device *device,
845                                                 enum connman_device_mode mode)
846 {
847         device->mode = mode;
848 }
849
850 /**
851  * connman_device_set_powered:
852  * @device: device structure
853  * @powered: powered state
854  *
855  * Change power state of device
856  */
857 int connman_device_set_powered(struct connman_device *device,
858                                                 connman_bool_t powered)
859 {
860         DBusMessage *signal;
861         DBusMessageIter entry, value;
862         const char *key = "Powered";
863
864         DBG("driver %p powered %d", device, powered);
865
866         if (device->powered == powered)
867                 return -EALREADY;
868
869         device->powered = powered;
870
871         signal = dbus_message_new_signal(device->element.path,
872                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
873         if (signal == NULL)
874                 return 0;
875
876         dbus_message_iter_init_append(signal, &entry);
877
878         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
879
880         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
881                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
882         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
883         dbus_message_iter_close_container(&entry, &value);
884
885         g_dbus_send_message(connection, signal);
886
887         return 0;
888 }
889
890 /**
891  * connman_device_set_carrier:
892  * @device: device structure
893  * @carrier: carrier state
894  *
895  * Change carrier state of device (only for device without scanning)
896  */
897 int connman_device_set_carrier(struct connman_device *device,
898                                                 connman_bool_t carrier)
899 {
900         DBG("driver %p carrier %d", device, carrier);
901
902         switch (device->mode) {
903         case CONNMAN_DEVICE_MODE_UNKNOWN:
904         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
905         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
906                 return -EINVAL;
907         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
908                 break;
909         }
910
911         if (device->carrier == carrier)
912                 return -EALREADY;
913
914         device->carrier = carrier;
915
916         if (carrier == TRUE) {
917                 struct connman_element *element;
918
919                 element = connman_element_create(NULL);
920                 if (element != NULL) {
921                         element->type    = CONNMAN_ELEMENT_TYPE_DHCP;
922                         element->subtype = device->element.subtype;
923                         element->index   = device->element.index;
924
925                         if (connman_element_register(element,
926                                                         &device->element) < 0)
927                                 connman_element_unref(element);
928                 }
929         } else
930                 connman_element_unregister_children(&device->element);
931
932         return 0;
933 }
934
935 /**
936  * connman_device_set_scanning:
937  * @device: device structure
938  * @scanning: scanning state
939  *
940  * Change scanning state of device
941  */
942 int connman_device_set_scanning(struct connman_device *device,
943                                                 connman_bool_t scanning)
944 {
945         DBusMessage *signal;
946         DBusMessageIter entry, value;
947         const char *key = "Scanning";
948
949         DBG("driver %p scanning %d", device, scanning);
950
951         if (!device->driver || !device->driver->scan)
952                 return -EINVAL;
953
954         if (device->scanning == scanning)
955                 return -EALREADY;
956
957         device->scanning = scanning;
958
959         signal = dbus_message_new_signal(device->element.path,
960                                 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
961         if (signal == NULL)
962                 return 0;
963
964         dbus_message_iter_init_append(signal, &entry);
965
966         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
967
968         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
969                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
970         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
971         dbus_message_iter_close_container(&entry, &value);
972
973         g_dbus_send_message(connection, signal);
974
975         return 0;
976 }
977
978 /**
979  * connman_device_add_network:
980  * @device: device structure
981  * @network: network structure
982  *
983  * Add new network to the device
984  */
985 int connman_device_add_network(struct connman_device *device,
986                                         struct connman_network *network)
987 {
988         const char *identifier = connman_network_get_identifier(network);
989         int err;
990
991         DBG("device %p network %p", device, network);
992
993         switch (device->mode) {
994         case CONNMAN_DEVICE_MODE_UNKNOWN:
995         case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
996                 return -EINVAL;
997         case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
998         case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
999                 break;
1000         }
1001
1002         __connman_network_set_device(network, device);
1003
1004         err = connman_element_register((struct connman_element *) network,
1005                                                         &device->element);
1006         if (err < 0) {
1007                 __connman_network_set_device(network, NULL);
1008                 return err;
1009         }
1010
1011         g_hash_table_insert(device->networks, g_strdup(identifier),
1012                                                                 network);
1013
1014         return 0;
1015 }
1016
1017 /**
1018  * connman_device_get_network:
1019  * @device: device structure
1020  * @identifier: network identifier
1021  *
1022  * Get network for given identifier
1023  */
1024 struct connman_network *connman_device_get_network(struct connman_device *device,
1025                                                         const char *identifier)
1026 {
1027         DBG("device %p identifier %s", device, identifier);
1028
1029         return g_hash_table_lookup(device->networks, identifier);
1030 }
1031
1032 /**
1033  * connman_device_remove_network:
1034  * @device: device structure
1035  * @identifier: network identifier
1036  *
1037  * Remove network for given identifier
1038  */
1039 int connman_device_remove_network(struct connman_device *device,
1040                                                         const char *identifier)
1041 {
1042         DBG("device %p identifier %s", device, identifier);
1043
1044         g_hash_table_remove(device->networks, identifier);
1045
1046         return 0;
1047 }
1048
1049 /**
1050  * connman_device_register:
1051  * @device: device structure
1052  *
1053  * Register device with the system
1054  */
1055 int connman_device_register(struct connman_device *device)
1056 {
1057         return connman_element_register(&device->element, NULL);
1058 }
1059
1060 /**
1061  * connman_device_unregister:
1062  * @device: device structure
1063  *
1064  * Unregister device with the system
1065  */
1066 void connman_device_unregister(struct connman_device *device)
1067 {
1068         connman_element_unregister(&device->element);
1069 }
1070
1071 /**
1072  * connman_device_get_data:
1073  * @device: device structure
1074  *
1075  * Get private device data pointer
1076  */
1077 void *connman_device_get_data(struct connman_device *device)
1078 {
1079         return device->driver_data;
1080 }
1081
1082 /**
1083  * connman_device_set_data:
1084  * @device: device structure
1085  * @data: data pointer
1086  *
1087  * Set private device data pointer
1088  */
1089 void connman_device_set_data(struct connman_device *device, void *data)
1090 {
1091         device->driver_data = data;
1092 }
1093
1094 static gboolean match_driver(struct connman_device *device,
1095                                         struct connman_device_driver *driver)
1096 {
1097         if (device->type == driver->type ||
1098                         driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1099                 return TRUE;
1100
1101         return FALSE;
1102 }
1103
1104 static int device_probe(struct connman_element *element)
1105 {
1106         struct connman_device *device = element->device;
1107         GSList *list;
1108
1109         DBG("element %p name %s", element, element->name);
1110
1111         if (device == NULL)
1112                 return -ENODEV;
1113
1114         for (list = driver_list; list; list = list->next) {
1115                 struct connman_device_driver *driver = list->data;
1116
1117                 if (match_driver(device, driver) == FALSE)
1118                         continue;
1119
1120                 DBG("driver %p name %s", driver, driver->name);
1121
1122                 if (driver->probe(device) == 0) {
1123                         device->driver = driver;
1124                         break;
1125                 }
1126         }
1127
1128         if (device->driver == NULL)
1129                 return -ENODEV;
1130
1131         return setup_device(device);
1132 }
1133
1134 static void device_remove(struct connman_element *element)
1135 {
1136         struct connman_device *device = element->device;
1137
1138         DBG("element %p name %s", element, element->name);
1139
1140         if (device == NULL)
1141                 return;
1142
1143         if (device->driver == NULL)
1144                 return;
1145
1146         remove_device(device);
1147 }
1148
1149 static struct connman_driver device_driver = {
1150         .name           = "device",
1151         .type           = CONNMAN_ELEMENT_TYPE_DEVICE,
1152         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
1153         .probe          = device_probe,
1154         .remove         = device_remove,
1155 };
1156
1157 static struct connman_storage device_storage = {
1158         .name           = "device",
1159         .priority       = CONNMAN_STORAGE_PRIORITY_LOW,
1160 };
1161
1162 int __connman_device_init(void)
1163 {
1164         DBG("");
1165
1166         connection = connman_dbus_get_connection();
1167
1168         if (connman_storage_register(&device_storage) < 0)
1169                 connman_error("Failed to register device storage");
1170
1171         return connman_driver_register(&device_driver);
1172 }
1173
1174 void __connman_device_cleanup(void)
1175 {
1176         DBG("");
1177
1178         connman_driver_unregister(&device_driver);
1179
1180         connman_storage_unregister(&device_storage);
1181
1182         dbus_connection_unref(connection);
1183 }