5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
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
30 #include <netinet/ether.h>
34 #define CONNMAN_API_SUBJECT_TO_CHANGE
35 #include <connman/plugin.h>
36 #include <connman/technology.h>
37 #include <connman/device.h>
38 #include <connman/inet.h>
39 #include <connman/dbus.h>
40 #include <connman/log.h>
42 #define BLUEZ_SERVICE "org.bluez"
43 #define BLUEZ_MANAGER_INTERFACE BLUEZ_SERVICE ".Manager"
44 #define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter"
45 #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device"
46 #define BLUEZ_NETWORK_INTERFACE BLUEZ_SERVICE ".Network"
47 #define BLUEZ_NETWORK_SERVER BLUEZ_SERVICE ".NetworkServer"
49 #define LIST_ADAPTERS "ListAdapters"
50 #define ADAPTER_ADDED "AdapterAdded"
51 #define ADAPTER_REMOVED "AdapterRemoved"
52 #define DEVICE_REMOVED "DeviceRemoved"
54 #define PROPERTY_CHANGED "PropertyChanged"
55 #define GET_PROPERTIES "GetProperties"
56 #define SET_PROPERTY "SetProperty"
58 #define CONNECT "Connect"
59 #define DISCONNECT "Disconnect"
61 #define REGISTER "Register"
62 #define UNREGISTER "Unregister"
64 #define UUID_NAP "00001116-0000-1000-8000-00805f9b34fb"
68 static DBusConnection *connection;
70 static GHashTable *bluetooth_devices = NULL;
71 static GHashTable *bluetooth_networks = NULL;
73 static int pan_probe(struct connman_network *network)
75 DBG("network %p", network);
80 static void pan_remove(struct connman_network *network)
82 DBG("network %p", network);
85 static void connect_reply(DBusPendingCall *call, void *user_data)
87 struct connman_network *network = user_data;
90 const char *interface = NULL;
93 DBG("network %p", network);
95 reply = dbus_pending_call_steal_reply(call);
97 dbus_error_init(&error);
99 if (dbus_set_error_from_message(&error, reply) == TRUE) {
100 connman_error("%s", error.message);
101 dbus_error_free(&error);
106 if (dbus_message_get_args(reply, &error,
107 DBUS_TYPE_STRING, &interface,
108 DBUS_TYPE_INVALID) == FALSE) {
109 if (dbus_error_is_set(&error) == TRUE) {
110 connman_error("%s", error.message);
111 dbus_error_free(&error);
113 connman_error("Wrong arguments for connect");
117 if (interface == NULL)
120 DBG("interface %s", interface);
122 index = connman_inet_ifindex(interface);
124 connman_network_set_index(network, index);
126 connman_network_set_connected(network, TRUE);
128 dbus_message_unref(reply);
130 dbus_pending_call_unref(call);
135 connman_network_set_connected(network, FALSE);
137 dbus_message_unref(reply);
139 dbus_pending_call_unref(call);
142 static int pan_connect(struct connman_network *network)
144 const char *path = connman_network_get_string(network, "Path");
145 const char *uuid = "nap";
146 DBusMessage *message;
147 DBusPendingCall *call;
149 DBG("network %p", network);
154 message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
155 BLUEZ_NETWORK_INTERFACE, CONNECT);
159 dbus_message_set_auto_start(message, FALSE);
161 dbus_message_append_args(message, DBUS_TYPE_STRING, &uuid,
164 if (dbus_connection_send_with_reply(connection, message,
165 &call, TIMEOUT * 10) == FALSE) {
166 connman_error("Failed to connect service");
167 dbus_message_unref(message);
172 connman_error("D-Bus connection not available");
173 dbus_message_unref(message);
177 dbus_pending_call_set_notify(call, connect_reply, network, NULL);
179 dbus_message_unref(message);
184 static void disconnect_reply(DBusPendingCall *call, void *user_data)
186 struct connman_network *network = user_data;
190 DBG("network %p", network);
192 reply = dbus_pending_call_steal_reply(call);
194 dbus_error_init(&error);
196 if (dbus_set_error_from_message(&error, reply) == TRUE) {
197 connman_error("%s", error.message);
198 dbus_error_free(&error);
202 if (dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) == FALSE) {
203 if (dbus_error_is_set(&error) == TRUE) {
204 connman_error("%s", error.message);
205 dbus_error_free(&error);
207 connman_error("Wrong arguments for disconnect");
211 connman_network_set_connected(network, FALSE);
214 dbus_message_unref(reply);
216 dbus_pending_call_unref(call);
218 connman_network_unregister(network);
219 connman_network_unref(network);
222 static int pan_disconnect(struct connman_network *network)
224 const char *path = connman_network_get_string(network, "Path");
225 DBusMessage *message;
226 DBusPendingCall *call;
228 DBG("network %p", network);
233 message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
234 BLUEZ_NETWORK_INTERFACE, DISCONNECT);
238 dbus_message_set_auto_start(message, FALSE);
240 dbus_message_append_args(message, DBUS_TYPE_INVALID);
242 if (dbus_connection_send_with_reply(connection, message,
243 &call, TIMEOUT) == FALSE) {
244 connman_error("Failed to disconnect service");
245 dbus_message_unref(message);
250 connman_error("D-Bus connection not available");
251 dbus_message_unref(message);
255 connman_network_ref(network);
257 connman_network_set_associating(network, FALSE);
259 dbus_pending_call_set_notify(call, disconnect_reply, network, NULL);
261 dbus_message_unref(message);
266 static struct connman_network_driver pan_driver = {
267 .name = "bluetooth-pan",
268 .type = CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN,
270 .remove = pan_remove,
271 .connect = pan_connect,
272 .disconnect = pan_disconnect,
275 static gboolean network_changed(DBusConnection *connection,
276 DBusMessage *message, void *user_data)
278 const char *path = dbus_message_get_path(message);
279 struct connman_network *network;
280 DBusMessageIter iter, value;
283 DBG("path %s", path);
285 network = g_hash_table_lookup(bluetooth_networks, path);
289 if (dbus_message_iter_init(message, &iter) == FALSE)
292 dbus_message_iter_get_basic(&iter, &key);
294 dbus_message_iter_next(&iter);
295 dbus_message_iter_recurse(&iter, &value);
297 if (g_str_equal(key, "Connected") == TRUE) {
298 dbus_bool_t connected;
300 dbus_message_iter_get_basic(&value, &connected);
302 if (connected == TRUE)
305 connman_network_set_associating(network, FALSE);
306 connman_network_set_connected(network, FALSE);
312 static void extract_properties(DBusMessage *reply, const char **parent,
313 const char **address,
316 dbus_bool_t *powered,
317 dbus_bool_t *scanning,
318 DBusMessageIter *uuids,
319 DBusMessageIter *networks)
321 DBusMessageIter array, dict;
323 if (dbus_message_iter_init(reply, &array) == FALSE)
326 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
329 dbus_message_iter_recurse(&array, &dict);
331 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
332 DBusMessageIter entry, value;
335 dbus_message_iter_recurse(&dict, &entry);
336 dbus_message_iter_get_basic(&entry, &key);
338 dbus_message_iter_next(&entry);
339 dbus_message_iter_recurse(&entry, &value);
341 if (g_str_equal(key, "Adapter") == TRUE) {
343 dbus_message_iter_get_basic(&value, parent);
344 } else if (g_str_equal(key, "Address") == TRUE) {
346 dbus_message_iter_get_basic(&value, address);
347 } else if (g_str_equal(key, "Name") == TRUE) {
349 dbus_message_iter_get_basic(&value, name);
350 } else if (g_str_equal(key, "Alias") == TRUE) {
352 dbus_message_iter_get_basic(&value, alias);
353 } else if (g_str_equal(key, "Powered") == TRUE) {
355 dbus_message_iter_get_basic(&value, powered);
356 } else if (g_str_equal(key, "Discovering") == TRUE) {
357 if (scanning != NULL)
358 dbus_message_iter_get_basic(&value, scanning);
359 } else if (g_str_equal(key, "Devices") == TRUE) {
360 if (networks != NULL)
361 memcpy(networks, &value, sizeof(value));
362 } else if (g_str_equal(key, "UUIDs") == TRUE) {
364 memcpy(uuids, &value, sizeof(value));
367 dbus_message_iter_next(&dict);
371 static dbus_bool_t has_pan(DBusMessageIter *array)
373 DBusMessageIter value;
375 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
378 dbus_message_iter_recurse(array, &value);
380 while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
383 dbus_message_iter_get_basic(&value, &uuid);
385 if (g_strcmp0(uuid, UUID_NAP) == 0)
388 dbus_message_iter_next(&value);
394 static void network_properties_reply(DBusPendingCall *call, void *user_data)
396 char *path = user_data;
397 struct connman_device *device;
398 struct connman_network *network;
400 DBusMessageIter uuids;
401 const char *parent = NULL, *address = NULL, *name = NULL;
402 struct ether_addr addr;
405 reply = dbus_pending_call_steal_reply(call);
407 extract_properties(reply, &parent, &address, NULL, &name,
408 NULL, NULL, &uuids, NULL);
413 device = g_hash_table_lookup(bluetooth_devices, parent);
420 ether_aton_r(address, &addr);
422 snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
423 addr.ether_addr_octet[0],
424 addr.ether_addr_octet[1],
425 addr.ether_addr_octet[2],
426 addr.ether_addr_octet[3],
427 addr.ether_addr_octet[4],
428 addr.ether_addr_octet[5]);
430 if (has_pan(&uuids) == FALSE)
433 network = connman_device_get_network(device, ident);
437 network = connman_network_create(ident,
438 CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN);
442 connman_network_register(network);
444 connman_network_set_string(network, "Path", path);
446 connman_network_set_name(network, name);
448 connman_device_add_network(device, network);
450 connman_network_set_group(network, ident);
452 g_hash_table_insert(bluetooth_networks, g_strdup(path), network);
455 dbus_message_unref(reply);
457 dbus_pending_call_unref(call);
460 static void add_network(struct connman_device *device, const char *path)
462 DBusMessage *message;
463 DBusPendingCall *call;
465 DBG("path %s", path);
467 message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
468 BLUEZ_DEVICE_INTERFACE, GET_PROPERTIES);
472 dbus_message_set_auto_start(message, FALSE);
474 if (dbus_connection_send_with_reply(connection, message,
475 &call, TIMEOUT) == FALSE) {
476 connman_error("Failed to get network properties for %s", path);
481 connman_error("D-Bus connection not available");
485 dbus_pending_call_set_notify(call, network_properties_reply,
486 g_strdup(path), g_free);
489 dbus_message_unref(message);
492 static void check_networks(struct connman_device *device,
493 DBusMessageIter *array)
495 DBusMessageIter value;
497 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
500 dbus_message_iter_recurse(array, &value);
502 while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_OBJECT_PATH) {
505 dbus_message_iter_get_basic(&value, &path);
507 add_network(device, path);
509 dbus_message_iter_next(&value);
513 static gboolean adapter_changed(DBusConnection *connection,
514 DBusMessage *message, void *user_data)
516 const char *path = dbus_message_get_path(message);
517 struct connman_device *device;
518 DBusMessageIter iter, value;
521 DBG("path %s", path);
523 device = g_hash_table_lookup(bluetooth_devices, path);
527 if (dbus_message_iter_init(message, &iter) == FALSE)
530 dbus_message_iter_get_basic(&iter, &key);
532 dbus_message_iter_next(&iter);
533 dbus_message_iter_recurse(&iter, &value);
535 if (g_str_equal(key, "Powered") == TRUE) {
538 dbus_message_iter_get_basic(&value, &val);
539 connman_device_set_powered(device, val);
540 } else if (g_str_equal(key, "Discovering") == TRUE) {
543 dbus_message_iter_get_basic(&value, &val);
544 connman_device_set_scanning(device, val);
545 } else if (g_str_equal(key, "Devices") == TRUE) {
546 check_networks(device, &value);
552 static gboolean device_removed(DBusConnection *connection,
553 DBusMessage *message, void *user_data)
555 const char *network_path, *identifier;
556 struct connman_network *network;
557 struct connman_device *device;
558 DBusMessageIter iter;
562 if (dbus_message_iter_init(message, &iter) == FALSE)
565 dbus_message_iter_get_basic(&iter, &network_path);
567 network = g_hash_table_lookup(bluetooth_networks, network_path);
571 device = connman_network_get_device(network);
575 identifier = connman_network_get_identifier(network);
577 g_hash_table_remove(bluetooth_networks, network_path);
579 connman_device_remove_network(device, identifier);
584 static gboolean device_changed(DBusConnection *connection,
585 DBusMessage *message, void *user_data)
587 const char *path = dbus_message_get_path(message);
588 DBusMessageIter iter, value;
591 DBG("path %s", path);
593 if (dbus_message_iter_init(message, &iter) == FALSE)
596 dbus_message_iter_get_basic(&iter, &key);
598 dbus_message_iter_next(&iter);
599 dbus_message_iter_recurse(&iter, &value);
603 if (g_str_equal(key, "UUIDs") == TRUE)
604 add_network(NULL, path);
609 static void adapter_properties_reply(DBusPendingCall *call, void *user_data)
611 char *path = user_data;
612 struct connman_device *device;
614 DBusMessageIter networks;
615 const char *address = NULL, *name = NULL;
616 dbus_bool_t powered = FALSE, scanning = FALSE;
617 struct ether_addr addr;
620 DBG("path %s", path);
622 reply = dbus_pending_call_steal_reply(call);
627 extract_properties(reply, NULL, &address, &name, NULL,
628 &powered, &scanning, NULL, &networks);
633 if (g_strcmp0(address, "00:00:00:00:00:00") == 0)
636 device = g_hash_table_lookup(bluetooth_devices, path);
640 ether_aton_r(address, &addr);
642 snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
643 addr.ether_addr_octet[0],
644 addr.ether_addr_octet[1],
645 addr.ether_addr_octet[2],
646 addr.ether_addr_octet[3],
647 addr.ether_addr_octet[4],
648 addr.ether_addr_octet[5]);
650 device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_BLUETOOTH);
654 connman_device_set_ident(device, ident);
656 connman_device_set_string(device, "Path", path);
658 if (connman_device_register(device) < 0) {
659 connman_device_unref(device);
663 g_hash_table_insert(bluetooth_devices, g_strdup(path), device);
666 connman_device_set_string(device, "Address", address);
667 connman_device_set_string(device, "Name", name);
668 connman_device_set_string(device, "Path", path);
670 connman_device_set_powered(device, powered);
671 connman_device_set_scanning(device, scanning);
674 check_networks(device, &networks);
677 dbus_message_unref(reply);
679 dbus_pending_call_unref(call);
682 static void add_adapter(DBusConnection *connection, const char *path)
684 DBusMessage *message;
685 DBusPendingCall *call;
687 DBG("path %s", path);
689 message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
690 BLUEZ_ADAPTER_INTERFACE, GET_PROPERTIES);
694 dbus_message_set_auto_start(message, FALSE);
696 if (dbus_connection_send_with_reply(connection, message,
697 &call, TIMEOUT) == FALSE) {
698 connman_error("Failed to get adapter properties for %s", path);
703 connman_error("D-Bus connection not available");
707 dbus_pending_call_set_notify(call, adapter_properties_reply,
708 g_strdup(path), g_free);
711 dbus_message_unref(message);
714 static gboolean adapter_added(DBusConnection *connection, DBusMessage *message,
719 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
721 add_adapter(connection, path);
725 static void remove_adapter(DBusConnection *connection, const char *path)
727 DBG("path %s", path);
729 g_hash_table_remove(bluetooth_devices, path);
732 static gboolean adapter_removed(DBusConnection *connection, DBusMessage *message,
737 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
739 remove_adapter(connection, path);
743 static void list_adapters_reply(DBusPendingCall *call, void *user_data)
752 reply = dbus_pending_call_steal_reply(call);
754 dbus_error_init(&error);
756 if (dbus_set_error_from_message(&error, reply) == TRUE) {
757 connman_error("%s", error.message);
758 dbus_error_free(&error);
762 if (dbus_message_get_args(reply, &error,
763 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH,
764 &adapters, &num_adapters,
765 DBUS_TYPE_INVALID) == FALSE) {
766 if (dbus_error_is_set(&error) == TRUE) {
767 connman_error("%s", error.message);
768 dbus_error_free(&error);
770 connman_error("Wrong arguments for adapter list");
774 for (i = 0; i < num_adapters; i++)
775 add_adapter(connection, adapters[i]);
777 g_strfreev(adapters);
780 dbus_message_unref(reply);
782 dbus_pending_call_unref(call);
785 static void unregister_device(gpointer data)
787 struct connman_device *device = data;
791 connman_device_unregister(device);
792 connman_device_unref(device);
795 static void bluetooth_connect(DBusConnection *connection, void *user_data)
797 DBusMessage *message;
798 DBusPendingCall *call;
800 DBG("connection %p", connection);
802 bluetooth_devices = g_hash_table_new_full(g_str_hash, g_str_equal,
803 g_free, unregister_device);
805 bluetooth_networks = g_hash_table_new_full(g_str_hash, g_str_equal,
808 message = dbus_message_new_method_call(BLUEZ_SERVICE, "/",
809 BLUEZ_MANAGER_INTERFACE, LIST_ADAPTERS);
813 dbus_message_set_auto_start(message, FALSE);
815 if (dbus_connection_send_with_reply(connection, message,
816 &call, TIMEOUT) == FALSE) {
817 connman_error("Failed to get Bluetooth adapters");
822 connman_error("D-Bus connection not available");
826 dbus_pending_call_set_notify(call, list_adapters_reply, NULL, NULL);
829 dbus_message_unref(message);
832 static void bluetooth_disconnect(DBusConnection *connection, void *user_data)
834 DBG("connection %p", connection);
836 if (bluetooth_devices == NULL)
839 g_hash_table_destroy(bluetooth_networks);
840 g_hash_table_destroy(bluetooth_devices);
841 bluetooth_devices = NULL;
844 static int bluetooth_probe(struct connman_device *device)
846 DBG("device %p", device);
851 static void bluetooth_remove(struct connman_device *device)
853 DBG("device %p", device);
856 static void powered_reply(DBusPendingCall *call, void *user_data)
863 reply = dbus_pending_call_steal_reply(call);
865 dbus_error_init(&error);
867 if (dbus_set_error_from_message(&error, reply) == TRUE) {
868 connman_error("%s", error.message);
869 dbus_error_free(&error);
870 dbus_message_unref(reply);
871 dbus_pending_call_unref(call);
875 dbus_message_unref(reply);
876 dbus_pending_call_unref(call);
878 add_adapter(connection, user_data);
881 static int change_powered(DBusConnection *connection, const char *path,
884 DBusMessage *message;
885 DBusMessageIter iter;
886 DBusPendingCall *call;
893 message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
894 BLUEZ_ADAPTER_INTERFACE, SET_PROPERTY);
898 dbus_message_set_auto_start(message, FALSE);
900 dbus_message_iter_init_append(message, &iter);
901 connman_dbus_property_append_basic(&iter, "Powered",
902 DBUS_TYPE_BOOLEAN, &powered);
904 if (dbus_connection_send_with_reply(connection, message,
905 &call, TIMEOUT) == FALSE) {
906 connman_error("Failed to change Powered property");
907 dbus_message_unref(message);
912 connman_error("D-Bus connection not available");
913 dbus_message_unref(message);
917 dbus_pending_call_set_notify(call, powered_reply,
918 g_strdup(path), g_free);
920 dbus_message_unref(message);
925 static int bluetooth_enable(struct connman_device *device)
927 const char *path = connman_device_get_string(device, "Path");
929 DBG("device %p", device);
931 return change_powered(connection, path, TRUE);
934 static int bluetooth_disable(struct connman_device *device)
936 const char *path = connman_device_get_string(device, "Path");
938 DBG("device %p", device);
940 return change_powered(connection, path, FALSE);
943 static struct connman_device_driver bluetooth_driver = {
945 .type = CONNMAN_DEVICE_TYPE_BLUETOOTH,
946 .probe = bluetooth_probe,
947 .remove = bluetooth_remove,
948 .enable = bluetooth_enable,
949 .disable = bluetooth_disable,
952 static int tech_probe(struct connman_technology *technology)
957 static void tech_remove(struct connman_technology *technology)
961 static void server_register_reply(DBusPendingCall *call, void *user_data)
963 struct connman_technology *technology = user_data;
969 reply = dbus_pending_call_steal_reply(call);
971 dbus_error_init(&error);
973 if (dbus_set_error_from_message(&error, reply) == TRUE) {
974 connman_error("%s", error.message);
975 dbus_error_free(&error);
976 dbus_message_unref(reply);
977 dbus_pending_call_unref(call);
981 dbus_message_unref(reply);
982 dbus_pending_call_unref(call);
984 connman_technology_tethering_notify(technology, TRUE);
987 static void server_unregister_reply(DBusPendingCall *call, void *user_data)
989 struct connman_technology *technology = user_data;
995 reply = dbus_pending_call_steal_reply(call);
997 dbus_error_init(&error);
999 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1000 connman_error("%s", error.message);
1001 dbus_error_free(&error);
1002 dbus_message_unref(reply);
1003 dbus_pending_call_unref(call);
1007 dbus_message_unref(reply);
1008 dbus_pending_call_unref(call);
1010 connman_technology_tethering_notify(technology, FALSE);
1014 static void server_register(const char *path, const char *uuid,
1015 struct connman_technology *technology,
1016 const char *bridge, connman_bool_t enabled)
1018 DBusMessage *message;
1019 DBusPendingCall *call;
1022 DBG("path %s enabled %d", path, enabled);
1024 command = enabled ? REGISTER : UNREGISTER;
1026 message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
1027 BLUEZ_NETWORK_SERVER, command);
1028 if (message == NULL)
1031 dbus_message_set_auto_start(message, FALSE);
1033 dbus_message_append_args(message, DBUS_TYPE_STRING, &uuid,
1036 if (enabled == TRUE)
1037 dbus_message_append_args(message, DBUS_TYPE_STRING, &bridge,
1040 if (dbus_connection_send_with_reply(connection, message,
1041 &call, TIMEOUT) == FALSE) {
1042 connman_error("Failed to enable PAN server");
1043 dbus_message_unref(message);
1048 connman_error("D-Bus connection not available");
1049 dbus_message_unref(message);
1053 if (enabled == TRUE)
1054 dbus_pending_call_set_notify(call, server_register_reply,
1057 dbus_pending_call_set_notify(call, server_unregister_reply,
1060 dbus_message_unref(message);
1063 struct tethering_info {
1064 struct connman_technology *technology;
1068 static void enable_nap(gpointer key, gpointer value, gpointer user_data)
1070 struct tethering_info *info = user_data;
1071 struct connman_device *device = value;
1076 path = connman_device_get_string(device, "Path");
1078 server_register(path, "nap", info->technology, info->bridge, TRUE);
1081 static void disable_nap(gpointer key, gpointer value, gpointer user_data)
1083 struct tethering_info *info = user_data;
1084 struct connman_device *device = value;
1089 path = connman_device_get_string(device, "Path");
1091 server_register(path, "nap", info->technology, info->bridge, FALSE);
1094 static int tech_set_tethering(struct connman_technology *technology,
1095 const char *identifier, const char *passphrase,
1096 const char *bridge, connman_bool_t enabled)
1098 struct tethering_info info = {
1099 .technology = technology,
1103 DBG("bridge %s", bridge);
1106 g_hash_table_foreach(bluetooth_devices, enable_nap, &info);
1108 g_hash_table_foreach(bluetooth_devices, disable_nap, &info);
1113 static struct connman_technology_driver tech_driver = {
1114 .name = "bluetooth",
1115 .type = CONNMAN_SERVICE_TYPE_BLUETOOTH,
1116 .probe = tech_probe,
1117 .remove = tech_remove,
1118 .set_tethering = tech_set_tethering,
1122 static guint added_watch;
1123 static guint removed_watch;
1124 static guint adapter_watch;
1125 static guint device_watch;
1126 static guint device_removed_watch;
1127 static guint network_watch;
1129 static int bluetooth_init(void)
1133 connection = connman_dbus_get_connection();
1134 if (connection == NULL)
1137 watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE,
1138 bluetooth_connect, bluetooth_disconnect, NULL, NULL);
1140 added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1141 BLUEZ_MANAGER_INTERFACE,
1142 ADAPTER_ADDED, adapter_added,
1145 removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1146 BLUEZ_MANAGER_INTERFACE,
1147 ADAPTER_REMOVED, adapter_removed,
1150 adapter_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1151 BLUEZ_ADAPTER_INTERFACE,
1152 PROPERTY_CHANGED, adapter_changed,
1155 device_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1156 BLUEZ_ADAPTER_INTERFACE,
1157 DEVICE_REMOVED, device_removed,
1160 device_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1161 BLUEZ_DEVICE_INTERFACE,
1162 PROPERTY_CHANGED, device_changed,
1165 network_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1166 BLUEZ_NETWORK_INTERFACE,
1167 PROPERTY_CHANGED, network_changed,
1170 if (watch == 0 || added_watch == 0 || removed_watch == 0
1171 || adapter_watch == 0 || network_watch == 0
1172 || device_watch == 0
1173 || device_removed_watch == 0) {
1178 err = connman_network_driver_register(&pan_driver);
1182 err = connman_device_driver_register(&bluetooth_driver);
1184 connman_network_driver_unregister(&pan_driver);
1188 err = connman_technology_driver_register(&tech_driver);
1190 connman_device_driver_unregister(&bluetooth_driver);
1191 connman_network_driver_unregister(&pan_driver);
1198 g_dbus_remove_watch(connection, watch);
1199 g_dbus_remove_watch(connection, added_watch);
1200 g_dbus_remove_watch(connection, removed_watch);
1201 g_dbus_remove_watch(connection, adapter_watch);
1202 g_dbus_remove_watch(connection, device_removed_watch);
1203 g_dbus_remove_watch(connection, device_watch);
1204 g_dbus_remove_watch(connection, network_watch);
1206 dbus_connection_unref(connection);
1211 static void bluetooth_exit(void)
1213 g_dbus_remove_watch(connection, watch);
1214 g_dbus_remove_watch(connection, added_watch);
1215 g_dbus_remove_watch(connection, removed_watch);
1216 g_dbus_remove_watch(connection, adapter_watch);
1217 g_dbus_remove_watch(connection, device_removed_watch);
1218 g_dbus_remove_watch(connection, device_watch);
1219 g_dbus_remove_watch(connection, network_watch);
1221 bluetooth_disconnect(connection, NULL);
1223 connman_technology_driver_unregister(&tech_driver);
1225 connman_device_driver_unregister(&bluetooth_driver);
1226 connman_network_driver_unregister(&pan_driver);
1228 dbus_connection_unref(connection);
1231 CONNMAN_PLUGIN_DEFINE(bluetooth, "Bluetooth technology plugin", VERSION,
1232 CONNMAN_PLUGIN_PRIORITY_DEFAULT, bluetooth_init, bluetooth_exit)