summaryrefslogtreecommitdiff
path: root/plugins/bluetooth_legacy.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/bluetooth_legacy.c')
-rw-r--r--plugins/bluetooth_legacy.c1385
1 files changed, 0 insertions, 1385 deletions
diff --git a/plugins/bluetooth_legacy.c b/plugins/bluetooth_legacy.c
deleted file mode 100644
index 2d7a9e01..00000000
--- a/plugins/bluetooth_legacy.c
+++ /dev/null
@@ -1,1385 +0,0 @@
-/*
- *
- * Connection Manager
- *
- * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netinet/ether.h>
-
-#include <gdbus.h>
-
-#define CONNMAN_API_SUBJECT_TO_CHANGE
-#include <connman/plugin.h>
-#include <connman/technology.h>
-#include <connman/device.h>
-#include <connman/inet.h>
-#include <connman/dbus.h>
-#include <connman/log.h>
-
-#define BLUEZ_SERVICE "org.bluez"
-#define BLUEZ_MANAGER_INTERFACE BLUEZ_SERVICE ".Manager"
-#define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter"
-#define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device"
-#define BLUEZ_NETWORK_INTERFACE BLUEZ_SERVICE ".Network"
-#define BLUEZ_NETWORK_SERVER BLUEZ_SERVICE ".NetworkServer"
-
-#define LIST_ADAPTERS "ListAdapters"
-#define ADAPTER_ADDED "AdapterAdded"
-#define ADAPTER_REMOVED "AdapterRemoved"
-#define DEVICE_REMOVED "DeviceRemoved"
-
-#define PROPERTY_CHANGED "PropertyChanged"
-#define GET_PROPERTIES "GetProperties"
-#define SET_PROPERTY "SetProperty"
-
-#define CONNECT "Connect"
-#define DISCONNECT "Disconnect"
-
-#define REGISTER "Register"
-#define UNREGISTER "Unregister"
-
-#define UUID_NAP "00001116-0000-1000-8000-00805f9b34fb"
-
-#define TIMEOUT 60000
-
-static DBusConnection *connection;
-
-static GHashTable *bluetooth_devices = NULL;
-static GHashTable *bluetooth_networks = NULL;
-static GHashTable *pending_networks = NULL;
-
-static int pan_probe(struct connman_network *network)
-{
- GHashTableIter iter;
- gpointer key, val;
-
- g_hash_table_iter_init(&iter, bluetooth_networks);
- while (g_hash_table_iter_next(&iter, &key, &val)) {
- struct connman_network *known = val;
-
- if (network != known)
- continue;
-
- DBG("network %p", network);
-
- return 0;
- }
-
- return -EOPNOTSUPP;
-}
-
-static void pan_remove(struct connman_network *network)
-{
- DBG("network %p", network);
-}
-
-static void connect_reply(DBusPendingCall *call, void *user_data)
-{
- char *path = user_data;
- struct connman_network *network;
- DBusMessage *reply;
- DBusError error;
- const char *interface = NULL;
- int index;
-
- network = g_hash_table_lookup(bluetooth_networks, path);
- if (!network)
- return;
-
- DBG("network %p", network);
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&error);
-
- if (dbus_set_error_from_message(&error, reply)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
-
- goto err;
- }
-
- if (!dbus_message_get_args(reply, &error, DBUS_TYPE_STRING,
- &interface, DBUS_TYPE_INVALID)) {
- if (dbus_error_is_set(&error)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- } else
- connman_error("Wrong arguments for connect");
- goto err;
- }
-
- if (!interface)
- goto err;
-
- DBG("interface %s", interface);
-
- index = connman_inet_ifindex(interface);
-
- connman_network_set_index(network, index);
-
- connman_network_set_connected(network, true);
-
- dbus_message_unref(reply);
-
- dbus_pending_call_unref(call);
-
- return;
-err:
-
- connman_network_set_connected(network, false);
-
- dbus_message_unref(reply);
-
- dbus_pending_call_unref(call);
-}
-
-static int pan_connect(struct connman_network *network)
-{
- const char *path = connman_network_get_string(network, "Path");
- const char *uuid = "nap";
- DBusMessage *message;
- DBusPendingCall *call;
-
- DBG("network %p", network);
-
- if (!path)
- return -EINVAL;
-
- message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
- BLUEZ_NETWORK_INTERFACE, CONNECT);
- if (!message)
- return -ENOMEM;
-
- dbus_message_set_auto_start(message, FALSE);
-
- dbus_message_append_args(message, DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- if (!dbus_connection_send_with_reply(connection, message,
- &call, TIMEOUT * 10)) {
- connman_error("Failed to connect service");
- dbus_message_unref(message);
- return -EINVAL;
- }
-
- if (!call) {
- connman_error("D-Bus connection not available");
- dbus_message_unref(message);
- return -EINVAL;
- }
-
- dbus_pending_call_set_notify(call, connect_reply, g_strdup(path),
- g_free);
-
- dbus_message_unref(message);
-
- return -EINPROGRESS;
-}
-
-static void disconnect_reply(DBusPendingCall *call, void *user_data)
-{
- char *path = user_data;
- struct connman_network *network;
- DBusMessage *reply;
- DBusError error;
-
- network = g_hash_table_lookup(bluetooth_networks, path);
- if (!network)
- return;
-
- DBG("network %p", network);
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&error);
-
- if (dbus_set_error_from_message(&error, reply)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- goto done;
- }
-
- if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID)) {
- if (dbus_error_is_set(&error)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- } else
- connman_error("Wrong arguments for disconnect");
- goto done;
- }
-
- connman_network_set_connected(network, false);
-
-done:
- dbus_message_unref(reply);
-
- dbus_pending_call_unref(call);
-
- connman_network_unref(network);
-}
-
-static int pan_disconnect(struct connman_network *network)
-{
- const char *path = connman_network_get_string(network, "Path");
- DBusMessage *message;
- DBusPendingCall *call;
-
- DBG("network %p", network);
-
- if (!path)
- return -EINVAL;
-
- message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
- BLUEZ_NETWORK_INTERFACE, DISCONNECT);
- if (!message)
- return -ENOMEM;
-
- dbus_message_set_auto_start(message, FALSE);
-
- dbus_message_append_args(message, DBUS_TYPE_INVALID);
-
- if (!dbus_connection_send_with_reply(connection, message,
- &call, TIMEOUT)) {
- connman_error("Failed to disconnect service");
- dbus_message_unref(message);
- return -EINVAL;
- }
-
- if (!call) {
- connman_error("D-Bus connection not available");
- dbus_message_unref(message);
- return -EINVAL;
- }
-
- connman_network_ref(network);
-
- connman_network_set_associating(network, false);
-
- dbus_pending_call_set_notify(call, disconnect_reply, g_strdup(path),
- g_free);
-
- dbus_message_unref(message);
-
- return 0;
-}
-
-static struct connman_network_driver pan_driver = {
- .name = "bluetooth_legacy-pan",
- .type = CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN,
- .priority = CONNMAN_NETWORK_PRIORITY_LOW,
- .probe = pan_probe,
- .remove = pan_remove,
- .connect = pan_connect,
- .disconnect = pan_disconnect,
-};
-
-static gboolean network_changed(DBusConnection *conn,
- DBusMessage *message, void *user_data)
-{
- const char *path = dbus_message_get_path(message);
- struct connman_network *network;
- DBusMessageIter iter, value;
- const char *key;
-
- DBG("path %s", path);
-
- network = g_hash_table_lookup(bluetooth_networks, path);
- if (!network)
- return TRUE;
-
- if (!dbus_message_iter_init(message, &iter))
- return TRUE;
-
- dbus_message_iter_get_basic(&iter, &key);
-
- dbus_message_iter_next(&iter);
- dbus_message_iter_recurse(&iter, &value);
-
- if (g_str_equal(key, "Connected")) {
- dbus_bool_t connected;
-
- dbus_message_iter_get_basic(&value, &connected);
-
- if (connected)
- return TRUE;
-
- connman_network_set_associating(network, false);
- connman_network_set_connected(network, false);
- }
-
- return TRUE;
-}
-
-static void extract_properties(DBusMessage *reply, const char **parent,
- const char **address,
- const char **name,
- const char **alias,
- dbus_bool_t *powered,
- dbus_bool_t *scanning,
- DBusMessageIter *uuids,
- DBusMessageIter *networks)
-{
- DBusMessageIter array, dict;
-
- if (!dbus_message_iter_init(reply, &array))
- return;
-
- if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
- return;
-
- dbus_message_iter_recurse(&array, &dict);
-
- while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
- DBusMessageIter entry, value;
- const char *key;
-
- dbus_message_iter_recurse(&dict, &entry);
- dbus_message_iter_get_basic(&entry, &key);
-
- dbus_message_iter_next(&entry);
- dbus_message_iter_recurse(&entry, &value);
-
- if (g_str_equal(key, "Adapter")) {
- if (parent)
- dbus_message_iter_get_basic(&value, parent);
- } else if (g_str_equal(key, "Address")) {
- if (address)
- dbus_message_iter_get_basic(&value, address);
- } else if (g_str_equal(key, "Name")) {
- if (name)
- dbus_message_iter_get_basic(&value, name);
- } else if (g_str_equal(key, "Alias")) {
- if (alias)
- dbus_message_iter_get_basic(&value, alias);
- } else if (g_str_equal(key, "Powered")) {
- if (powered)
- dbus_message_iter_get_basic(&value, powered);
- } else if (g_str_equal(key, "Discovering")) {
- if (scanning)
- dbus_message_iter_get_basic(&value, scanning);
- } else if (g_str_equal(key, "Devices")) {
- if (networks)
- memcpy(networks, &value, sizeof(value));
- } else if (g_str_equal(key, "UUIDs")) {
- if (uuids)
- memcpy(uuids, &value, sizeof(value));
- }
-
- dbus_message_iter_next(&dict);
- }
-}
-
-static dbus_bool_t has_pan(DBusMessageIter *array)
-{
- DBusMessageIter value;
-
- if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
- return FALSE;
-
- dbus_message_iter_recurse(array, &value);
-
- while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
- const char *uuid;
-
- dbus_message_iter_get_basic(&value, &uuid);
-
- if (g_strcmp0(uuid, UUID_NAP) == 0)
- return TRUE;
-
- dbus_message_iter_next(&value);
- }
-
- return FALSE;
-}
-
-static void network_properties_reply(DBusPendingCall *call, void *user_data)
-{
- char *path = user_data;
- struct connman_device *device;
- struct connman_network *network;
- DBusMessage *reply;
- DBusMessageIter uuids;
- const char *parent = NULL, *address = NULL, *name = NULL;
- struct ether_addr addr;
- char ident[13];
-
- reply = dbus_pending_call_steal_reply(call);
-
- extract_properties(reply, &parent, &address, NULL, &name,
- NULL, NULL, &uuids, NULL);
-
- if (!parent)
- goto done;
-
- device = g_hash_table_lookup(bluetooth_devices, parent);
- if (!device)
- goto done;
-
- if (!address)
- goto done;
-
- ether_aton_r(address, &addr);
-
- snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
- addr.ether_addr_octet[0],
- addr.ether_addr_octet[1],
- addr.ether_addr_octet[2],
- addr.ether_addr_octet[3],
- addr.ether_addr_octet[4],
- addr.ether_addr_octet[5]);
-
- if (!has_pan(&uuids))
- goto done;
-
- network = connman_device_get_network(device, ident);
- if (network)
- goto done;
-
- network = connman_network_create(ident,
- CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN);
- if (!network)
- goto done;
-
- connman_network_set_string(network, "Path", path);
-
- connman_network_set_name(network, name);
-
- g_hash_table_replace(bluetooth_networks, g_strdup(path), network);
-
- connman_device_add_network(device, network);
-
- connman_network_set_group(network, ident);
-
-done:
- dbus_message_unref(reply);
-
- dbus_pending_call_unref(call);
-}
-
-static void add_network(const char *path)
-{
- DBusMessage *message;
- DBusPendingCall *call;
-
- DBG("path %s", path);
-
- message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
- BLUEZ_DEVICE_INTERFACE, GET_PROPERTIES);
- if (!message)
- return;
-
- dbus_message_set_auto_start(message, FALSE);
-
- if (!dbus_connection_send_with_reply(connection, message,
- &call, TIMEOUT)) {
- connman_error("Failed to get network properties for %s", path);
- goto done;
- }
-
- if (!call) {
- connman_error("D-Bus connection not available");
- goto done;
- }
-
- dbus_pending_call_set_notify(call, network_properties_reply,
- g_strdup(path), g_free);
-
-done:
- dbus_message_unref(message);
-}
-
-static void check_networks(DBusMessageIter *array)
-{
- DBusMessageIter value;
-
- if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
- return;
-
- dbus_message_iter_recurse(array, &value);
-
- while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_OBJECT_PATH) {
- const char *path;
-
- dbus_message_iter_get_basic(&value, &path);
-
- add_network(path);
-
- dbus_message_iter_next(&value);
- }
-}
-
-static void check_pending_networks(const char *adapter)
-{
- GSList *networks, *list;
-
- networks = g_hash_table_lookup(pending_networks, adapter);
- if (!networks)
- return;
-
- for (list = networks; list; list = list->next) {
- char *path = list->data;
-
- add_network(path);
- }
-
- g_hash_table_remove(pending_networks, adapter);
-}
-
-static gboolean adapter_changed(DBusConnection *conn,
- DBusMessage *message, void *user_data)
-{
- const char *path = dbus_message_get_path(message);
- struct connman_device *device;
- DBusMessageIter iter, value;
- const char *key;
-
- DBG("path %s", path);
-
- device = g_hash_table_lookup(bluetooth_devices, path);
- if (!device)
- return TRUE;
-
- if (!dbus_message_iter_init(message, &iter))
- return TRUE;
-
- dbus_message_iter_get_basic(&iter, &key);
-
- dbus_message_iter_next(&iter);
- dbus_message_iter_recurse(&iter, &value);
-
- if (g_str_equal(key, "Powered")) {
- dbus_bool_t val;
-
- dbus_message_iter_get_basic(&value, &val);
- connman_device_set_powered(device, val);
- if (val)
- check_pending_networks(path);
- } else if (g_str_equal(key, "Discovering")) {
- dbus_bool_t val;
-
- dbus_message_iter_get_basic(&value, &val);
- connman_device_set_scanning(device,
- CONNMAN_SERVICE_TYPE_BLUETOOTH, val);
- } else if (g_str_equal(key, "Devices")) {
- check_networks(&value);
- }
-
- return TRUE;
-}
-
-static gboolean device_removed(DBusConnection *conn,
- DBusMessage *message, void *user_data)
-{
- const char *network_path;
- struct connman_network *network;
- struct connman_device *device;
- DBusMessageIter iter;
-
- DBG("");
-
- if (!dbus_message_iter_init(message, &iter))
- return TRUE;
-
- dbus_message_iter_get_basic(&iter, &network_path);
-
- network = g_hash_table_lookup(bluetooth_networks, network_path);
- if (!network)
- return TRUE;
-
- device = connman_network_get_device(network);
- if (!device)
- return TRUE;
-
- g_hash_table_remove(bluetooth_networks, network_path);
-
- return TRUE;
-}
-
-static gboolean device_changed(DBusConnection *conn,
- DBusMessage *message, void *user_data)
-{
- const char *path = dbus_message_get_path(message);
- DBusMessageIter iter, value;
- const char *key;
-
- DBG("path %s", path);
-
- if (!dbus_message_iter_init(message, &iter))
- return TRUE;
-
- dbus_message_iter_get_basic(&iter, &key);
-
- dbus_message_iter_next(&iter);
- dbus_message_iter_recurse(&iter, &value);
-
- DBG("key %s", key);
-
- if (g_str_equal(key, "UUIDs"))
- add_network(path);
-
- return TRUE;
-}
-
-static void remove_device_networks(struct connman_device *device)
-{
- GHashTableIter iter;
- gpointer key, value;
- GSList *key_list = NULL;
- GSList *list;
-
- if (!bluetooth_networks)
- return;
-
- g_hash_table_iter_init(&iter, bluetooth_networks);
-
- while (g_hash_table_iter_next(&iter, &key, &value)) {
- struct connman_network *network = value;
-
- if (connman_network_get_device(network) != device)
- continue;
-
- key_list = g_slist_prepend(key_list, key);
- }
-
- for (list = key_list; list; list = list->next) {
- const char *network_path = list->data;
-
- g_hash_table_remove(bluetooth_networks, network_path);
- }
-
- g_slist_free(key_list);
-}
-
-static void add_pending_networks(const char *adapter, DBusMessageIter *array)
-{
- DBusMessageIter value;
- GSList *list = NULL;
-
- if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
- return;
-
- dbus_message_iter_recurse(array, &value);
-
- while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_OBJECT_PATH) {
- const char *path;
-
- dbus_message_iter_get_basic(&value, &path);
-
- list = g_slist_prepend(list, g_strdup(path));
-
- dbus_message_iter_next(&value);
- }
-
- if (!list)
- return;
-
- g_hash_table_replace(pending_networks, g_strdup(adapter), list);
-}
-
-static void adapter_properties_reply(DBusPendingCall *call, void *user_data)
-{
- char *path = user_data;
- struct connman_device *device;
- DBusMessage *reply;
- DBusMessageIter networks;
- const char *address = NULL, *name = NULL;
- dbus_bool_t powered = FALSE, scanning = FALSE;
- struct ether_addr addr;
- char ident[13];
-
- DBG("path %s", path);
-
- reply = dbus_pending_call_steal_reply(call);
-
- if (!path)
- goto done;
-
- extract_properties(reply, NULL, &address, &name, NULL,
- &powered, &scanning, NULL, &networks);
-
- if (!address)
- goto done;
-
- if (g_strcmp0(address, "00:00:00:00:00:00") == 0)
- goto done;
-
- device = g_hash_table_lookup(bluetooth_devices, path);
- if (device)
- goto update;
-
- ether_aton_r(address, &addr);
-
- snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
- addr.ether_addr_octet[0],
- addr.ether_addr_octet[1],
- addr.ether_addr_octet[2],
- addr.ether_addr_octet[3],
- addr.ether_addr_octet[4],
- addr.ether_addr_octet[5]);
-
- device = connman_device_create("bluetooth_legacy",
- CONNMAN_DEVICE_TYPE_BLUETOOTH);
- if (!device)
- goto done;
-
- g_hash_table_insert(bluetooth_devices, g_strdup(path), device);
-
- connman_device_set_ident(device, ident);
-
- connman_device_set_string(device, "Path", path);
-
- if (connman_device_register(device) < 0) {
- connman_device_unref(device);
- g_hash_table_remove(bluetooth_devices, path);
- goto done;
- }
-
-update:
- connman_device_set_string(device, "Address", address);
- connman_device_set_string(device, "Name", name);
- connman_device_set_string(device, "Path", path);
-
- connman_device_set_powered(device, powered);
- connman_device_set_scanning(device,
- CONNMAN_SERVICE_TYPE_BLUETOOTH, scanning);
-
- if (!powered) {
- remove_device_networks(device);
- add_pending_networks(path, &networks);
- } else
- check_networks(&networks);
-
-done:
- dbus_message_unref(reply);
-
- dbus_pending_call_unref(call);
-}
-
-static void add_adapter(DBusConnection *conn, const char *path)
-{
- DBusMessage *message;
- DBusPendingCall *call;
-
- DBG("path %s", path);
-
- message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
- BLUEZ_ADAPTER_INTERFACE, GET_PROPERTIES);
- if (!message)
- return;
-
- dbus_message_set_auto_start(message, FALSE);
-
- if (!dbus_connection_send_with_reply(conn, message, &call, TIMEOUT)) {
- connman_error("Failed to get adapter properties for %s", path);
- goto done;
- }
-
- if (!call) {
- connman_error("D-Bus connection not available");
- goto done;
- }
-
- dbus_pending_call_set_notify(call, adapter_properties_reply,
- g_strdup(path), g_free);
-
-done:
- dbus_message_unref(message);
-}
-
-static gboolean adapter_added(DBusConnection *conn, DBusMessage *message,
- void *user_data)
-{
- const char *path;
-
- dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID);
- add_adapter(conn, path);
- return TRUE;
-}
-
-static void remove_adapter(DBusConnection *conn, const char *path)
-{
- DBG("path %s", path);
-
- g_hash_table_remove(bluetooth_devices, path);
- g_hash_table_remove(pending_networks, path);
-}
-
-static gboolean adapter_removed(DBusConnection *conn, DBusMessage *message,
- void *user_data)
-{
- const char *path;
-
- dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID);
- remove_adapter(conn, path);
- return TRUE;
-}
-
-static void list_adapters_reply(DBusPendingCall *call, void *user_data)
-{
- DBusMessage *reply;
- DBusError error;
- char **adapters;
- int i, num_adapters;
-
- DBG("");
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&error);
-
- if (dbus_set_error_from_message(&error, reply)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- goto done;
- }
-
- if (!dbus_message_get_args(reply, &error, DBUS_TYPE_ARRAY,
- DBUS_TYPE_OBJECT_PATH, &adapters,
- &num_adapters, DBUS_TYPE_INVALID)) {
- if (dbus_error_is_set(&error)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- } else
- connman_error("Wrong arguments for adapter list");
- goto done;
- }
-
- for (i = 0; i < num_adapters; i++)
- add_adapter(connection, adapters[i]);
-
- g_strfreev(adapters);
-
-done:
- dbus_message_unref(reply);
-
- dbus_pending_call_unref(call);
-}
-
-static void unregister_device(gpointer data)
-{
- struct connman_device *device = data;
-
- DBG("");
-
- remove_device_networks(device);
-
- connman_device_unregister(device);
- connman_device_unref(device);
-}
-
-static void remove_network(gpointer data)
-{
- struct connman_network *network = data;
- struct connman_device *device;
-
- DBG("network %p", network);
-
- device = connman_network_get_device(network);
- if (device)
- connman_device_remove_network(device, network);
-
- connman_network_unref(network);
-}
-
-static void remove_pending_networks(gpointer data)
-{
- GSList *list = data;
-
- g_slist_free_full(list, g_free);
-}
-
-static void bluetooth_connect(DBusConnection *conn, void *user_data)
-{
- DBusMessage *message;
- DBusPendingCall *call;
-
- DBG("connection %p", conn);
-
- bluetooth_devices = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, unregister_device);
-
- bluetooth_networks = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, remove_network);
-
- pending_networks = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, remove_pending_networks);
-
- message = dbus_message_new_method_call(BLUEZ_SERVICE, "/",
- BLUEZ_MANAGER_INTERFACE, LIST_ADAPTERS);
- if (!message)
- return;
-
- dbus_message_set_auto_start(message, FALSE);
-
- if (!dbus_connection_send_with_reply(conn, message, &call, TIMEOUT)) {
- connman_error("Failed to get Bluetooth adapters");
- goto done;
- }
-
- if (!call) {
- connman_error("D-Bus connection not available");
- goto done;
- }
-
- dbus_pending_call_set_notify(call, list_adapters_reply, NULL, NULL);
-
-done:
- dbus_message_unref(message);
-}
-
-static void bluetooth_disconnect(DBusConnection *conn, void *user_data)
-{
- DBG("connection %p", conn);
-
- if (!bluetooth_devices)
- return;
-
- g_hash_table_destroy(bluetooth_networks);
- bluetooth_networks = NULL;
- g_hash_table_destroy(bluetooth_devices);
- bluetooth_devices = NULL;
- g_hash_table_destroy(pending_networks);
- pending_networks = NULL;
-}
-
-static int bluetooth_probe(struct connman_device *device)
-{
- GHashTableIter iter;
- gpointer key, value;
-
- DBG("device %p", device);
-
- if (!bluetooth_devices)
- return -ENOTSUP;
-
- g_hash_table_iter_init(&iter, bluetooth_devices);
-
- while (g_hash_table_iter_next(&iter, &key, &value)) {
- struct connman_device *device_pan = value;
-
- if (device == device_pan)
- return 0;
- }
-
- return -ENOTSUP;
-}
-
-static void bluetooth_remove(struct connman_device *device)
-{
- DBG("device %p", device);
-}
-
-static void powered_reply(DBusPendingCall *call, void *user_data)
-{
- DBusError error;
- DBusMessage *reply;
-
- DBG("");
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&error);
-
- if (dbus_set_error_from_message(&error, reply)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- dbus_message_unref(reply);
- dbus_pending_call_unref(call);
- return;
- }
-
- dbus_message_unref(reply);
- dbus_pending_call_unref(call);
-
- add_adapter(connection, user_data);
-}
-
-static int change_powered(DBusConnection *conn, const char *path,
- dbus_bool_t powered)
-{
- DBusMessage *message;
- DBusMessageIter iter;
- DBusPendingCall *call;
-
- DBG("");
-
- if (!path)
- return -EINVAL;
-
- message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
- BLUEZ_ADAPTER_INTERFACE, SET_PROPERTY);
- if (!message)
- return -ENOMEM;
-
- dbus_message_set_auto_start(message, FALSE);
-
- dbus_message_iter_init_append(message, &iter);
- connman_dbus_property_append_basic(&iter, "Powered",
- DBUS_TYPE_BOOLEAN, &powered);
-
- if (!dbus_connection_send_with_reply(conn, message, &call, TIMEOUT)) {
- connman_error("Failed to change Powered property");
- dbus_message_unref(message);
- return -EINVAL;
- }
-
- if (!call) {
- connman_error("D-Bus connection not available");
- dbus_message_unref(message);
- return -EINVAL;
- }
-
- dbus_pending_call_set_notify(call, powered_reply,
- g_strdup(path), g_free);
-
- dbus_message_unref(message);
-
- return -EINPROGRESS;
-}
-
-static int bluetooth_enable(struct connman_device *device)
-{
- const char *path = connman_device_get_string(device, "Path");
-
- DBG("device %p", device);
-
- return change_powered(connection, path, TRUE);
-}
-
-static int bluetooth_disable(struct connman_device *device)
-{
- const char *path = connman_device_get_string(device, "Path");
-
- DBG("device %p", device);
-
- return change_powered(connection, path, FALSE);
-}
-
-static struct connman_device_driver bluetooth_driver = {
- .name = "bluetooth_legacy",
- .type = CONNMAN_DEVICE_TYPE_BLUETOOTH,
- .probe = bluetooth_probe,
- .remove = bluetooth_remove,
- .enable = bluetooth_enable,
- .disable = bluetooth_disable,
-};
-
-static int tech_probe(struct connman_technology *technology)
-{
- return 0;
-}
-
-static void tech_remove(struct connman_technology *technology)
-{
-}
-
-static void server_register_reply(DBusPendingCall *call, void *user_data)
-{
- struct connman_technology *technology = user_data;
- DBusError error;
- DBusMessage *reply;
-
- DBG("");
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&error);
-
- if (dbus_set_error_from_message(&error, reply)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- dbus_message_unref(reply);
- dbus_pending_call_unref(call);
- return;
- }
-
- dbus_message_unref(reply);
- dbus_pending_call_unref(call);
-
- connman_technology_tethering_notify(technology, true);
-}
-
-static void server_unregister_reply(DBusPendingCall *call, void *user_data)
-{
- struct connman_technology *technology = user_data;
- DBusError error;
- DBusMessage *reply;
-
- DBG("");
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&error);
-
- if (dbus_set_error_from_message(&error, reply)) {
- connman_error("%s", error.message);
- dbus_error_free(&error);
- dbus_message_unref(reply);
- dbus_pending_call_unref(call);
- return;
- }
-
- dbus_message_unref(reply);
- dbus_pending_call_unref(call);
-
- connman_technology_tethering_notify(technology, false);
-}
-
-
-static void server_register(const char *path, const char *uuid,
- struct connman_technology *technology,
- const char *bridge, bool enabled)
-{
- DBusMessage *message;
- DBusPendingCall *call;
- char *command;
-
- DBG("path %s enabled %d", path, enabled);
-
- command = enabled ? REGISTER : UNREGISTER;
-
- message = dbus_message_new_method_call(BLUEZ_SERVICE, path,
- BLUEZ_NETWORK_SERVER, command);
- if (!message)
- return;
-
- dbus_message_set_auto_start(message, FALSE);
-
- dbus_message_append_args(message, DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- if (enabled)
- dbus_message_append_args(message, DBUS_TYPE_STRING, &bridge,
- DBUS_TYPE_INVALID);
-
- if (!dbus_connection_send_with_reply(connection, message,
- &call, TIMEOUT)) {
- connman_error("Failed to enable PAN server");
- dbus_message_unref(message);
- return;
- }
-
- if (!call) {
- connman_error("D-Bus connection not available");
- dbus_message_unref(message);
- return;
- }
-
- if (enabled)
- dbus_pending_call_set_notify(call, server_register_reply,
- technology, NULL);
- else
- dbus_pending_call_set_notify(call, server_unregister_reply,
- technology, NULL);
-
- dbus_message_unref(message);
-}
-
-struct tethering_info {
- struct connman_technology *technology;
- const char *bridge;
-};
-
-static void enable_nap(gpointer key, gpointer value, gpointer user_data)
-{
- struct tethering_info *info = user_data;
- struct connman_device *device = value;
- const char *path;
-
- DBG("");
-
- path = connman_device_get_string(device, "Path");
-
- server_register(path, "nap", info->technology, info->bridge, true);
-}
-
-static void disable_nap(gpointer key, gpointer value, gpointer user_data)
-{
- struct tethering_info *info = user_data;
- struct connman_device *device = value;
- const char *path;
-
- DBG("");
-
- path = connman_device_get_string(device, "Path");
-
- server_register(path, "nap", info->technology, info->bridge, false);
-}
-
-static int tech_set_tethering(struct connman_technology *technology,
- const char *identifier, const char *passphrase,
- const char *bridge, bool enabled)
-{
- struct tethering_info info = {
- .technology = technology,
- .bridge = bridge,
- };
-
- DBG("bridge %s", bridge);
-
- if (!bluetooth_devices)
- return -ENOTCONN;
-
- if (enabled)
- g_hash_table_foreach(bluetooth_devices, enable_nap, &info);
- else
- g_hash_table_foreach(bluetooth_devices, disable_nap, &info);
-
- return 0;
-}
-
-static struct connman_technology_driver tech_driver = {
- .name = "bluetooth_legacy",
- .type = CONNMAN_SERVICE_TYPE_BLUETOOTH,
- .priority = -10,
- .probe = tech_probe,
- .remove = tech_remove,
- .set_tethering = tech_set_tethering,
-};
-
-static guint watch;
-static guint added_watch;
-static guint removed_watch;
-static guint adapter_watch;
-static guint device_watch;
-static guint device_removed_watch;
-static guint network_watch;
-
-static int bluetooth_init(void)
-{
- int err;
-
- connection = connman_dbus_get_connection();
- if (!connection)
- return -EIO;
-
- watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE,
- bluetooth_connect, bluetooth_disconnect, NULL, NULL);
-
- added_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE, NULL,
- BLUEZ_MANAGER_INTERFACE,
- ADAPTER_ADDED, adapter_added,
- NULL, NULL);
-
- removed_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE, NULL,
- BLUEZ_MANAGER_INTERFACE,
- ADAPTER_REMOVED, adapter_removed,
- NULL, NULL);
-
- adapter_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE,
- NULL, BLUEZ_ADAPTER_INTERFACE,
- PROPERTY_CHANGED, adapter_changed,
- NULL, NULL);
-
- device_removed_watch = g_dbus_add_signal_watch(connection,
- BLUEZ_SERVICE, NULL,
- BLUEZ_ADAPTER_INTERFACE,
- DEVICE_REMOVED, device_removed,
- NULL, NULL);
-
- device_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE, NULL,
- BLUEZ_DEVICE_INTERFACE,
- PROPERTY_CHANGED, device_changed,
- NULL, NULL);
-
- network_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE,
- NULL, BLUEZ_NETWORK_INTERFACE,
- PROPERTY_CHANGED, network_changed,
- NULL, NULL);
-
- if (watch == 0 || added_watch == 0 || removed_watch == 0
- || adapter_watch == 0 || network_watch == 0
- || device_watch == 0
- || device_removed_watch == 0) {
- err = -EIO;
- goto remove;
- }
-
- err = connman_network_driver_register(&pan_driver);
- if (err < 0)
- goto remove;
-
- err = connman_device_driver_register(&bluetooth_driver);
- if (err < 0) {
- connman_network_driver_unregister(&pan_driver);
- goto remove;
- }
-
- err = connman_technology_driver_register(&tech_driver);
- if (err < 0) {
- connman_device_driver_unregister(&bluetooth_driver);
- connman_network_driver_unregister(&pan_driver);
- goto remove;
- }
-
- return 0;
-
-remove:
- g_dbus_remove_watch(connection, watch);
- g_dbus_remove_watch(connection, added_watch);
- g_dbus_remove_watch(connection, removed_watch);
- g_dbus_remove_watch(connection, adapter_watch);
- g_dbus_remove_watch(connection, device_removed_watch);
- g_dbus_remove_watch(connection, device_watch);
- g_dbus_remove_watch(connection, network_watch);
-
- dbus_connection_unref(connection);
-
- return err;
-}
-
-static void bluetooth_exit(void)
-{
- g_dbus_remove_watch(connection, watch);
- g_dbus_remove_watch(connection, added_watch);
- g_dbus_remove_watch(connection, removed_watch);
- g_dbus_remove_watch(connection, adapter_watch);
- g_dbus_remove_watch(connection, device_removed_watch);
- g_dbus_remove_watch(connection, device_watch);
- g_dbus_remove_watch(connection, network_watch);
-
- /*
- * We unset the disabling of the Bluetooth device when shutting down
- * so that non-PAN BT connections are not affected.
- */
- bluetooth_driver.disable = NULL;
-
- bluetooth_disconnect(connection, NULL);
-
- connman_technology_driver_unregister(&tech_driver);
-
- connman_device_driver_unregister(&bluetooth_driver);
- connman_network_driver_unregister(&pan_driver);
-
- dbus_connection_unref(connection);
-}
-
-CONNMAN_PLUGIN_DEFINE(bluetooth_legacy, "Bluetooth technology plugin (legacy)",
- VERSION, CONNMAN_PLUGIN_PRIORITY_LOW,
- bluetooth_init, bluetooth_exit)