5 * Copyright (C) 2016 BMW Car IT GmbH.
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.
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.
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
29 #include <linux/if_ether.h>
31 #define CONNMAN_API_SUBJECT_TO_CHANGE
32 #include <connman/plugin.h>
33 #include <connman/dbus.h>
34 #include <connman/network.h>
35 #include <connman/technology.h>
36 #include <connman/inet.h>
39 static DBusConnection *connection;
40 static GDBusClient *client;
41 static GDBusProxy *agent_proxy;
42 static GHashTable *adapters;
43 static GHashTable *devices;
44 static GHashTable *networks;
45 static bool agent_registered;
47 #define IWD_SERVICE "net.connman.iwd"
49 #define IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager"
50 #define IWD_ADAPTER_INTERFACE "net.connman.iwd.Adapter"
51 #define IWD_DEVICE_INTERFACE "net.connman.iwd.Device"
52 #define IWD_NETWORK_INTERFACE "net.connman.iwd.Network"
54 #define IWD_AGENT_INTERFACE "net.connman.iwd.Agent"
55 #define IWD_AGENT_ERROR_INTERFACE "net.connman.iwd.Agent.Error"
56 #define AGENT_PATH "/net/connman/iwd_agent"
58 enum iwd_device_state {
59 IWD_DEVICE_STATE_UNKNOWN,
60 IWD_DEVICE_STATE_CONNECTED,
61 IWD_DEVICE_STATE_DISCONNECTED,
62 IWD_DEVICE_STATE_CONNECTING,
63 IWD_DEVICE_STATE_DISCONNECTING,
80 enum iwd_device_state state;
84 struct connman_device *device;
95 struct iwd_device *iwdd;
96 struct connman_network *network;
99 static enum iwd_device_state string2state(const char *str)
101 if (!strcmp(str, "connected"))
102 return IWD_DEVICE_STATE_CONNECTED;
103 else if (!strcmp(str, "disconnected"))
104 return IWD_DEVICE_STATE_DISCONNECTED;
105 else if (!strcmp(str, "connecting"))
106 return IWD_DEVICE_STATE_CONNECTING;
107 else if (!strcmp(str, "disconnecting"))
108 return IWD_DEVICE_STATE_DISCONNECTING;
110 return IWD_DEVICE_STATE_UNKNOWN;
113 static const char *state2string(enum iwd_device_state state)
116 case IWD_DEVICE_STATE_CONNECTED:
118 case IWD_DEVICE_STATE_DISCONNECTED:
119 return "disconnected";
120 case IWD_DEVICE_STATE_CONNECTING:
122 case IWD_DEVICE_STATE_DISCONNECTING:
123 return "disconnecting";
131 static const char *proxy_get_string(GDBusProxy *proxy, const char *property)
133 DBusMessageIter iter;
136 if (!g_dbus_proxy_get_property(proxy, property, &iter))
139 dbus_message_iter_get_basic(&iter, &str);
144 static bool proxy_get_bool(GDBusProxy *proxy, const char *property)
146 DBusMessageIter iter;
149 if (!g_dbus_proxy_get_property(proxy, property, &iter))
152 dbus_message_iter_get_basic(&iter, &value);
157 static void address2ident(const char *address, char *ident)
161 for (i = 0; i < ETH_ALEN; i++) {
162 ident[i * 2] = address[i * 3];
163 ident[i * 2 + 1] = address[i * 3 + 1];
165 ident[ETH_ALEN * 2] = '\0';
168 static int cm_network_probe(struct connman_network *network)
173 g_hash_table_iter_init(&iter, networks);
175 while (g_hash_table_iter_next(&iter, &key, &value)) {
176 struct iwd_network *iwdn = value;
178 if (network == iwdn->network)
185 static void update_network_connected(struct iwd_network *iwdn)
187 struct iwd_device *iwdd;
190 iwdd = g_hash_table_lookup(devices, iwdn->device);
194 index = connman_inet_ifindex(iwdd->name);
198 DBG("interface name %s index %d", iwdd->name, index);
199 connman_network_set_index(iwdn->network, index);
200 connman_network_set_connected(iwdn->network, true);
203 static void update_network_disconnected(struct iwd_network *iwdn)
205 DBG("interface name %s", iwdn->name);
206 connman_network_set_connected(iwdn->network, false);
209 static void cm_network_connect_cb(DBusMessage *message, void *user_data)
211 const char *path = user_data;
212 struct iwd_network *iwdn;
214 iwdn = g_hash_table_lookup(networks, path);
218 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
219 const char *dbus_error = dbus_message_get_error_name(message);
221 if (!strcmp(dbus_error, "net.connman.iwd.InProgress"))
224 DBG("%s connect failed: %s", path, dbus_error);
225 connman_network_set_error(iwdn->network,
226 CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
230 update_network_connected(iwdn);
233 static int cm_network_connect(struct connman_network *network)
235 struct iwd_network *iwdn = connman_network_get_data(network);
240 if (!g_dbus_proxy_method_call(iwdn->proxy, "Connect",
241 NULL, cm_network_connect_cb,
242 g_strdup(iwdn->path), g_free))
245 connman_network_set_associating(iwdn->network, true);
250 static void cm_network_disconnect_cb(DBusMessage *message, void *user_data)
252 const char *path = user_data;
253 struct iwd_network *iwdn;
255 iwdn = g_hash_table_lookup(networks, path);
259 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
260 const char *dbus_error = dbus_message_get_error_name(message);
262 if (!strcmp(dbus_error, "net.connman.iwd.NotConnected")) {
265 DBG("%s disconnect failed: %s", path, dbus_error);
271 * We end up in a tight loop in the error case. That is
272 * when we can't connect, bail out in cm_network_connect_cb() with
275 if (connman_network_get_connected(iwdn->network))
276 update_network_disconnected(iwdn);
279 static int cm_network_disconnect(struct connman_network *network)
281 struct iwd_network *iwdn = connman_network_get_data(network);
282 struct iwd_device *iwdd;
287 iwdd = g_hash_table_lookup(devices, iwdn->device);
291 if (!g_dbus_proxy_method_call(iwdd->proxy, "Disconnect",
292 NULL, cm_network_disconnect_cb, g_strdup(iwdn->path), g_free))
298 static struct connman_network_driver network_driver = {
300 .type = CONNMAN_NETWORK_TYPE_WIFI,
301 .probe = cm_network_probe,
302 .connect = cm_network_connect,
303 .disconnect = cm_network_disconnect,
306 static int cm_device_probe(struct connman_device *device)
311 g_hash_table_iter_init(&iter, devices);
313 while (g_hash_table_iter_next(&iter, &key, &value)) {
314 struct iwd_device *iwdd = value;
316 if (device == iwdd->device)
323 static void cm_device_remove(struct connman_device *device)
332 static void device_powered_cb(const DBusError *error, void *user_data)
334 struct dev_cb_data *cbd = user_data;
335 struct iwd_device *iwdd;
337 iwdd = g_hash_table_lookup(devices, cbd->path);
341 if (dbus_error_is_set(error)) {
342 connman_warn("WiFi device %s not enabled %s",
343 cbd->path, error->message);
347 connman_device_set_powered(iwdd->device, cbd->powered);
353 static int set_device_powered(struct connman_device *device, bool powered)
355 struct iwd_device *iwdd = connman_device_get_data(device);
356 dbus_bool_t device_powered = powered;
357 struct dev_cb_data *cbd;
359 if (proxy_get_bool(iwdd->proxy, "Powered"))
362 cbd = g_new(struct dev_cb_data, 1);
363 cbd->path = g_strdup(iwdd->path);
364 cbd->powered = powered;
366 g_dbus_proxy_set_property_basic(iwdd->proxy, "Powered",
367 DBUS_TYPE_BOOLEAN, &device_powered,
368 device_powered_cb, cbd, NULL);
373 static int cm_device_enable(struct connman_device *device)
375 return set_device_powered(device, true);
378 static int cm_device_disable(struct connman_device *device)
380 return set_device_powered(device, false);
383 static struct connman_device_driver device_driver = {
385 .type = CONNMAN_DEVICE_TYPE_WIFI,
386 .probe = cm_device_probe,
387 .remove = cm_device_remove,
388 .enable = cm_device_enable,
389 .disable = cm_device_disable,
392 static int cm_tech_probe(struct connman_technology *technology)
397 static void cm_tech_remove(struct connman_technology *technology)
401 static struct connman_technology_driver tech_driver = {
403 .type = CONNMAN_SERVICE_TYPE_WIFI,
404 .probe = cm_tech_probe,
405 .remove = cm_tech_remove,
408 static unsigned char calculate_strength(int strength)
413 * Network's maximum signal strength expressed in 100 * dBm.
414 * The value is the range of 0 (strongest signal) to -10000
417 * ConnMan expects it in the range from 100 (strongest) to 0
420 res = (unsigned char)((strength * -10000) / 100);
425 static void _update_signal_strength(const char *path, int16_t signal_strength)
427 struct iwd_network *iwdn;
429 iwdn = g_hash_table_lookup(networks, path);
436 connman_network_set_strength(iwdn->network,
437 calculate_strength(signal_strength));
440 static void ordered_networks_cb(DBusMessage *message, void *user_data)
442 DBusMessageIter array, entry;
446 if (!dbus_message_iter_init(message, &array))
449 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
452 dbus_message_iter_recurse(&array, &entry);
453 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRUCT) {
454 DBusMessageIter value;
455 const char *path, *name, *type;
456 int16_t signal_strength;
459 dbus_message_iter_recurse(&entry, &value);
461 dbus_message_iter_get_basic(&value, &path);
463 dbus_message_iter_next(&value);
464 dbus_message_iter_get_basic(&value, &name);
466 dbus_message_iter_next(&value);
467 dbus_message_iter_get_basic(&value, &signal_strength);
469 dbus_message_iter_next(&value);
470 dbus_message_iter_get_basic(&value, &type);
472 _update_signal_strength(path, signal_strength);
474 dbus_message_iter_next(&entry);
478 static void update_signal_strength(struct iwd_device *iwdd)
480 if (!g_dbus_proxy_method_call(iwdd->proxy,
481 "GetOrderedNetworks",
482 NULL, ordered_networks_cb,
484 DBG("GetOrderedNetworks() failed");
487 static void add_network(const char *path, struct iwd_network *iwdn)
489 struct iwd_device *iwdd;
490 const char *identifier;
492 iwdd = g_hash_table_lookup(devices, iwdn->device);
496 identifier = strrchr(path, '/');
497 identifier++; /* strip leading slash as well */
498 iwdn->network = connman_network_create(identifier,
499 CONNMAN_NETWORK_TYPE_WIFI);
500 connman_network_set_data(iwdn->network, iwdn);
502 connman_network_set_name(iwdn->network, iwdn->name);
503 connman_network_set_blob(iwdn->network, "WiFi.SSID", iwdn->name,
505 connman_network_set_string(iwdn->network, "WiFi.Security",
508 if (connman_device_add_network(iwdd->device, iwdn->network) < 0) {
509 connman_network_unref(iwdn->network);
510 iwdn->network = NULL;
515 connman_network_set_available(iwdn->network, true);
516 connman_network_set_group(iwdn->network, identifier);
519 static void remove_network(struct iwd_network *iwdn)
525 connman_device_remove_network(iwdn->iwdd->device,
528 connman_network_unref(iwdn->network);
529 iwdn->network = NULL;
532 static void add_device(const char *path, struct iwd_device *iwdd)
534 char ident[ETH_ALEN * 2 + 1];
536 iwdd->device = connman_device_create("wifi", CONNMAN_DEVICE_TYPE_WIFI);
540 connman_device_set_data(iwdd->device, iwdd);
542 address2ident(iwdd->address, ident);
543 connman_device_set_ident(iwdd->device, ident);
545 if (connman_device_register(iwdd->device) < 0) {
546 g_hash_table_remove(devices, path);
550 connman_device_set_powered(iwdd->device, iwdd->powered);
553 static void remove_device_networks(struct iwd_device *iwdd)
557 struct iwd_network *iwdn;
558 GSList *list, *nets = NULL;
560 g_hash_table_iter_init(&iter, networks);
562 while (g_hash_table_iter_next(&iter, &key, &value)) {
565 if (!strcmp(iwdd->path, iwdn->device))
566 nets = g_slist_prepend(nets, iwdn);
569 for (list = nets; list; list = list->next) {
571 g_hash_table_remove(networks, iwdn->path);
577 static void remove_device(struct iwd_device *iwdd)
582 remove_device_networks(iwdd);
583 connman_device_unregister(iwdd->device);
584 connman_device_unref(iwdd->device);
588 static void adapter_property_change(GDBusProxy *proxy, const char *name,
589 DBusMessageIter *iter, void *user_data)
591 struct iwd_adapter *adapter;
594 path = g_dbus_proxy_get_path(proxy);
595 adapter = g_hash_table_lookup(adapters, path);
599 if (!strcmp(name, "Powered")) {
602 dbus_message_iter_get_basic(iter, &powered);
603 adapter->powered = powered;
605 DBG("%p powered %d", path, adapter->powered);
609 static void device_property_change(GDBusProxy *proxy, const char *name,
610 DBusMessageIter *iter, void *user_data)
612 struct iwd_device *iwdd;
615 path = g_dbus_proxy_get_path(proxy);
616 iwdd = g_hash_table_lookup(devices, path);
620 if (!strcmp(name, "Name")) {
623 dbus_message_iter_get_basic(iter, &name);
625 iwdd->name = g_strdup(name);
627 DBG("%p name %s", path, iwdd->name);
628 } else if (!strcmp(name, "State")) {
631 dbus_message_iter_get_basic(iter, &state);
632 iwdd->state = string2state(state);
634 DBG("%s state %s", path, state2string(iwdd->state));
635 } else if (!strcmp(name, "Powered")) {
638 dbus_message_iter_get_basic(iter, &powered);
639 iwdd->powered = powered;
641 DBG("%s powered %d", path, iwdd->powered);
642 } else if (!strcmp(name, "Scanning")) {
643 dbus_bool_t scanning;
645 dbus_message_iter_get_basic(iter, &scanning);
646 iwdd->scanning = scanning;
648 DBG("%s scanning %d", path, iwdd->scanning);
651 update_signal_strength(iwdd);
656 static void network_property_change(GDBusProxy *proxy, const char *name,
657 DBusMessageIter *iter, void *user_data)
659 struct iwd_network *iwdn;
662 path = g_dbus_proxy_get_path(proxy);
663 iwdn = g_hash_table_lookup(networks, path);
667 if (!strcmp(name, "Connected")) {
668 dbus_bool_t connected;
670 dbus_message_iter_get_basic(iter, &connected);
671 iwdn->connected = connected;
673 DBG("%s connected %d", path, iwdn->connected);
676 update_network_connected(iwdn);
678 update_network_disconnected(iwdn);
682 static void adapter_free(gpointer data)
684 struct iwd_adapter *iwda = data;
687 g_dbus_proxy_unref(iwda->proxy);
692 g_free(iwda->vendor);
697 static void device_free(gpointer data)
699 struct iwd_device *iwdd = data;
702 g_dbus_proxy_unref(iwdd->proxy);
709 g_free(iwdd->adapter);
711 g_free(iwdd->address);
715 static void network_free(gpointer data)
717 struct iwd_network *iwdn = data;
720 g_dbus_proxy_unref(iwdn->proxy);
724 remove_network(iwdn);
727 g_free(iwdn->device);
733 static void create_adapter(GDBusProxy *proxy)
735 const char *path = g_dbus_proxy_get_path(proxy);
736 struct iwd_adapter *iwda;
738 iwda = g_try_new0(struct iwd_adapter, 1);
741 connman_error("Out of memory creating IWD adapter");
745 iwda->path = g_strdup(path);
746 g_hash_table_replace(adapters, iwda->path, iwda);
748 iwda->proxy = g_dbus_proxy_ref(proxy);
751 connman_error("Cannot create IWD adapter watcher %s", path);
752 g_hash_table_remove(adapters, path);
756 iwda->vendor = g_strdup(proxy_get_string(proxy, "Vendor"));
757 iwda->model = g_strdup(proxy_get_string(proxy, "Model"));
758 iwda->powered = proxy_get_bool(proxy, "Powered");
760 DBG("%s vendor '%s' model '%s' powered %d", path, iwda->vendor,
761 iwda->model, iwda->powered);
763 g_dbus_proxy_set_property_watch(iwda->proxy,
764 adapter_property_change, NULL);
767 static void create_device(GDBusProxy *proxy)
769 const char *path = g_dbus_proxy_get_path(proxy);
770 struct iwd_device *iwdd;
772 iwdd = g_try_new0(struct iwd_device, 1);
775 connman_error("Out of memory creating IWD device");
779 iwdd->path = g_strdup(path);
780 g_hash_table_replace(devices, iwdd->path, iwdd);
782 iwdd->proxy = g_dbus_proxy_ref(proxy);
785 connman_error("Cannot create IWD device watcher %s", path);
786 g_hash_table_remove(devices, path);
790 iwdd->adapter = g_strdup(proxy_get_string(proxy, "Adapter"));
791 iwdd->name = g_strdup(proxy_get_string(proxy, "Name"));
792 iwdd->address = g_strdup(proxy_get_string(proxy, "Address"));
793 iwdd->state = string2state(proxy_get_string(proxy, "State"));
794 iwdd->powered = proxy_get_bool(proxy, "Powered");
795 iwdd->scanning = proxy_get_bool(proxy, "Scanning");
797 DBG("adapter %s name %s address %s state %s powered %d scanning %d",
798 iwdd->adapter, iwdd->name, iwdd->address,
799 state2string(iwdd->state),
800 iwdd->powered, iwdd->scanning);
802 g_dbus_proxy_set_property_watch(iwdd->proxy,
803 device_property_change, NULL);
805 add_device(path, iwdd);
808 static void unregister_agent();
810 static DBusMessage *agent_release_method(DBusConnection *dbus_conn,
811 DBusMessage *message, void *user_data)
814 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
817 static DBusMessage *get_reply_on_error(DBusMessage *message, int error)
819 return g_dbus_create_error(message,
820 IWD_AGENT_ERROR_INTERFACE ".Failed", "Invalid parameters");
823 static DBusMessage *agent_request_passphrase(DBusConnection *dbus_conn,
824 DBusMessage *message,
827 struct iwd_network *iwdn;
828 DBusMessageIter iter;
829 const char *path, *passwd;
833 dbus_message_iter_init(message, &iter);
835 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
836 return get_reply_on_error(message, EINVAL);
838 dbus_message_iter_get_basic(&iter, &path);
840 iwdn = g_hash_table_lookup(networks, path);
842 return get_reply_on_error(message, EINVAL);
844 passwd = connman_network_get_string(iwdn->network, "WiFi.Passphrase");
846 return g_dbus_create_reply(message, DBUS_TYPE_STRING, &passwd,
850 static DBusMessage *agent_cancel(DBusConnection *dbus_conn,
851 DBusMessage *message, void *user_data)
853 DBusMessageIter iter;
856 dbus_message_iter_init(message, &iter);
858 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
859 return get_reply_on_error(message, EINVAL);
861 dbus_message_iter_get_basic(&iter, &reason);
863 DBG("cancel: %s", reason);
866 * We don't have to do anything here, because we asked the
867 * user upfront for the passphrase. So
868 * agent_request_passphrase() will always send a passphrase
872 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
875 static const GDBusMethodTable agent_methods[] = {
876 { GDBUS_METHOD("Release", NULL, NULL, agent_release_method) },
877 { GDBUS_METHOD("RequestPassphrase",
878 GDBUS_ARGS({ "path", "o" }),
879 GDBUS_ARGS({ "passphrase", "s" }),
880 agent_request_passphrase)},
881 { GDBUS_METHOD("Cancel",
882 GDBUS_ARGS({ "reason", "s" }),
883 NULL, agent_cancel) },
887 static void agent_register_builder(DBusMessageIter *iter, void *user_data)
889 const char *path = AGENT_PATH;
891 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
895 static void register_agent(GDBusProxy *proxy)
897 if (!g_dbus_proxy_method_call(proxy,
899 agent_register_builder,
903 agent_proxy = g_dbus_proxy_ref(proxy);
906 static void unregister_agent()
911 g_dbus_proxy_method_call(agent_proxy,
913 agent_register_builder,
916 g_dbus_proxy_unref(agent_proxy);
920 static void iwd_is_present(DBusConnection *conn, void *user_data)
922 if (agent_registered)
925 if (!g_dbus_register_interface(connection, AGENT_PATH,
926 IWD_AGENT_INTERFACE, agent_methods,
927 NULL, NULL, NULL, NULL))
930 agent_registered = true;
933 static void iwd_is_out(DBusConnection *conn, void *user_data)
935 if (agent_registered) {
936 g_dbus_unregister_interface(connection,
937 AGENT_PATH, IWD_AGENT_INTERFACE);
938 agent_registered = false;
942 static void create_network(GDBusProxy *proxy)
944 const char *path = g_dbus_proxy_get_path(proxy);
945 struct iwd_network *iwdn;
947 iwdn = g_try_new0(struct iwd_network, 1);
950 connman_error("Out of memory creating IWD network");
954 iwdn->path = g_strdup(path);
955 g_hash_table_replace(networks, iwdn->path, iwdn);
957 iwdn->proxy = g_dbus_proxy_ref(proxy);
960 connman_error("Cannot create IWD network watcher %s", path);
961 g_hash_table_remove(networks, path);
965 iwdn->device = g_strdup(proxy_get_string(proxy, "Device"));
966 iwdn->name = g_strdup(proxy_get_string(proxy, "Name"));
967 iwdn->type = g_strdup(proxy_get_string(proxy, "Type"));
968 iwdn->connected = proxy_get_bool(proxy, "Connected");
970 DBG("device %s name '%s' type %s connected %d",
976 g_dbus_proxy_set_property_watch(iwdn->proxy,
977 network_property_change, NULL);
979 add_network(path, iwdn);
982 static void object_added(GDBusProxy *proxy, void *user_data)
984 const char *interface;
986 interface = g_dbus_proxy_get_interface(proxy);
988 connman_warn("Interface or proxy missing when adding "
993 DBG("%s %s", interface, g_dbus_proxy_get_path(proxy));
995 if (!strcmp(interface, IWD_AGENT_MANAGER_INTERFACE))
996 register_agent(proxy);
997 else if (!strcmp(interface, IWD_ADAPTER_INTERFACE))
998 create_adapter(proxy);
999 else if (!strcmp(interface, IWD_DEVICE_INTERFACE))
1000 create_device(proxy);
1001 else if (!strcmp(interface, IWD_NETWORK_INTERFACE))
1002 create_network(proxy);
1005 static void object_removed(GDBusProxy *proxy, void *user_data)
1007 const char *interface, *path;
1009 interface = g_dbus_proxy_get_interface(proxy);
1011 connman_warn("Interface or proxy missing when removing "
1016 path = g_dbus_proxy_get_path(proxy);
1017 DBG("%s %s", interface, path);
1019 if (!strcmp(interface, IWD_AGENT_MANAGER_INTERFACE))
1021 if (!strcmp(interface, IWD_ADAPTER_INTERFACE))
1022 g_hash_table_remove(adapters, path);
1023 else if (!strcmp(interface, IWD_DEVICE_INTERFACE))
1024 g_hash_table_remove(devices, path);
1025 else if (!strcmp(interface, IWD_NETWORK_INTERFACE))
1026 g_hash_table_remove(networks, path);
1029 static int iwd_init(void)
1031 connection = connman_dbus_get_connection();
1035 adapters = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
1038 devices = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
1041 networks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
1044 if (connman_technology_driver_register(&tech_driver) < 0) {
1045 connman_warn("Failed to initialize technology for IWD");
1049 if (connman_device_driver_register(&device_driver) < 0) {
1050 connman_warn("Failed to initialize device driver for "
1052 connman_technology_driver_unregister(&tech_driver);
1056 if (connman_network_driver_register(&network_driver) < 0) {
1057 connman_technology_driver_unregister(&tech_driver);
1058 connman_device_driver_unregister(&device_driver);
1062 client = g_dbus_client_new(connection, IWD_SERVICE, IWD_PATH);
1064 connman_warn("Failed to initialize D-Bus client for "
1069 g_dbus_client_set_connect_watch(client, iwd_is_present, NULL);
1070 g_dbus_client_set_disconnect_watch(client, iwd_is_out, NULL);
1071 g_dbus_client_set_proxy_handlers(client, object_added, object_removed,
1078 g_hash_table_destroy(devices);
1081 g_hash_table_destroy(networks);
1084 g_hash_table_destroy(adapters);
1087 dbus_connection_unref(connection);
1092 static void iwd_exit(void)
1094 connman_network_driver_unregister(&network_driver);
1095 connman_device_driver_unregister(&device_driver);
1096 connman_technology_driver_unregister(&tech_driver);
1098 g_dbus_client_unref(client);
1100 g_hash_table_destroy(networks);
1101 g_hash_table_destroy(devices);
1102 g_hash_table_destroy(adapters);
1104 dbus_connection_unref(connection);
1107 CONNMAN_PLUGIN_DEFINE(iwd, "IWD plugin", VERSION,
1108 CONNMAN_PLUGIN_PRIORITY_DEFAULT, iwd_init, iwd_exit)