summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2011-01-21 06:56:55 +0200
committerJohan Hedberg <johan.hedberg@nokia.com>2011-01-21 06:56:55 +0200
commitbda6bb0079268b7db27695f40168aba07e960d8b (patch)
treed62077f2b6654a05c54d2e6108f3f9e08175f8b0
parentb115f344441c31c642f360fa5ce7d2fc73c1cfb2 (diff)
Keep connection handle information inside adapter_ops
There's no point to export connection handle details to the core daemon since it will not be available in the management interface. Instead track the handles inside hciops (managment interface will do this inside the kernel).
-rw-r--r--plugins/hciops.c118
-rw-r--r--plugins/mgmtops.c16
-rw-r--r--src/adapter.c39
-rw-r--r--src/adapter.h14
-rw-r--r--src/device.c43
-rw-r--r--src/device.h7
-rw-r--r--src/event.c26
-rw-r--r--src/event.h4
8 files changed, 137 insertions, 130 deletions
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 5f3b48ba..481f8864 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -68,6 +68,11 @@ struct uuid_info {
uint8_t svc_hint;
};
+struct acl_connection {
+ bdaddr_t bdaddr;
+ uint16_t handle;
+};
+
static int max_dev = -1;
static struct dev_info {
int sk;
@@ -103,6 +108,8 @@ static struct dev_info {
uint8_t pin_length;
GSList *uuids;
+
+ GSList *connections;
} *devs = NULL;
static int ignore_device(struct hci_dev_info *di)
@@ -575,28 +582,22 @@ static int hciops_set_did(int index, uint16_t vendor, uint16_t product,
static int get_handle(int index, const bdaddr_t *bdaddr, uint16_t *handle)
{
struct dev_info *dev = &devs[index];
- struct hci_conn_info_req *cr;
+ struct acl_connection *conn;
+ GSList *match;
char addr[18];
- int err;
ba2str(bdaddr, addr);
DBG("hci%d dba %s", index, addr);
- cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info));
- bacpy(&cr->bdaddr, bdaddr);
- cr->type = ACL_LINK;
+ match = g_slist_find_custom(dev->connections, bdaddr,
+ (GCompareFunc) bacmp);
+ if (match == NULL)
+ return -ENOENT;
- if (ioctl(dev->sk, HCIGETCONNINFO, (unsigned long) cr) < 0) {
- err = -errno;
- goto fail;
- }
-
- err = 0;
- *handle = cr->conn_info->handle;
+ conn = match->data;
+ *handle = conn->handle;
-fail:
- g_free(cr);
- return err;
+ return 0;
}
static int disconnect_addr(int index, bdaddr_t *dba, uint8_t reason)
@@ -1711,8 +1712,18 @@ static inline void conn_complete(int index, void *ptr)
if (evt->link_type != ACL_LINK)
return;
- btd_event_conn_complete(&dev->bdaddr, evt->status,
- btohs(evt->handle), &evt->bdaddr);
+ if (evt->status == 0) {
+ struct acl_connection *conn;
+
+ conn = g_new0(struct acl_connection, 1);
+
+ bacpy(&conn->bdaddr, &evt->bdaddr);
+ conn->handle = evt->handle;
+
+ dev->connections = g_slist_append(dev->connections, conn);
+ }
+
+ btd_event_conn_complete(&dev->bdaddr, evt->status, &evt->bdaddr);
if (evt->status)
return;
@@ -1738,8 +1749,18 @@ static inline void le_conn_complete(int index, void *ptr)
char filename[PATH_MAX];
char local_addr[18], peer_addr[18], *str;
- btd_event_conn_complete(&dev->bdaddr, evt->status,
- btohs(evt->handle), &evt->peer_bdaddr);
+ if (evt->status == 0) {
+ struct acl_connection *conn;
+
+ conn = g_new0(struct acl_connection, 1);
+
+ bacpy(&conn->bdaddr, &evt->peer_bdaddr);
+ conn->handle = evt->handle;
+
+ dev->connections = g_slist_append(dev->connections, conn);
+ }
+
+ btd_event_conn_complete(&dev->bdaddr, evt->status, &evt->peer_bdaddr);
if (evt->status)
return;
@@ -1758,13 +1779,38 @@ static inline void le_conn_complete(int index, void *ptr)
free(str);
}
+static int conn_handle_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct acl_connection *conn = a;
+ uint16_t handle = *((uint16_t *) b);
+
+ return (int) conn->handle - (int) handle;
+}
+
static inline void disconn_complete(int index, void *ptr)
{
struct dev_info *dev = &devs[index];
evt_disconn_complete *evt = ptr;
+ struct acl_connection *conn;
+ uint16_t handle;
+ GSList *match;
+
+ if (evt->status != 0)
+ return;
- btd_event_disconn_complete(&dev->bdaddr, evt->status,
- btohs(evt->handle), evt->reason);
+ handle = btohs(evt->handle);
+ match = g_slist_find_custom(dev->connections, &handle,
+ conn_handle_cmp);
+ if (match == NULL)
+ return;
+
+ conn = match->data;
+
+ dev->connections = g_slist_delete_link(dev->connections, match);
+
+ btd_event_disconn_complete(&dev->bdaddr, &conn->bdaddr);
+
+ g_free(conn);
}
static inline void auth_complete(int index, void *ptr)
@@ -1857,6 +1903,9 @@ static void stop_hci_dev(int index)
g_slist_foreach(dev->uuids, (GFunc) g_free, NULL);
g_slist_free(dev->uuids);
+ g_slist_foreach(dev->connections, (GFunc) g_free, NULL);
+ g_slist_free(dev->connections);
+
init_dev_info(index, -1, dev->registered);
}
@@ -2823,22 +2872,11 @@ static int hciops_read_local_features(int index, uint8_t *features)
return 0;
}
-static int hciops_disconnect(int index, uint16_t handle)
+static int hciops_disconnect(int index, bdaddr_t *bdaddr)
{
- struct dev_info *dev = &devs[index];
- disconnect_cp cp;
-
- DBG("hci%d handle %u", index, handle);
-
- memset(&cp, 0, sizeof(cp));
- cp.handle = htobs(handle);
- cp.reason = HCI_OE_USER_ENDED_CONNECTION;
-
- if (hci_send_cmd(dev->sk, OGF_LINK_CTL, OCF_DISCONNECT,
- DISCONNECT_CP_SIZE, &cp) < 0)
- return -errno;
+ DBG("hci%d", index);
- return 0;
+ return disconnect_addr(index, bdaddr, HCI_OE_USER_ENDED_CONNECTION);
}
static int hciops_remove_bonding(int index, bdaddr_t *bdaddr)
@@ -2868,12 +2906,18 @@ static int hciops_remove_bonding(int index, bdaddr_t *bdaddr)
return 0;
}
-static int hciops_request_authentication(int index, uint16_t handle)
+static int hciops_request_authentication(int index, bdaddr_t *bdaddr)
{
struct dev_info *dev = &devs[index];
auth_requested_cp cp;
+ uint16_t handle;
+ int err;
- DBG("hci%d handle %u", index, handle);
+ DBG("hci%d", index);
+
+ err = get_handle(index, bdaddr, &handle);
+ if (err < 0)
+ return err;
memset(&cp, 0, sizeof(cp));
cp.handle = htobs(handle);
diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index c0825868..cf3b15a2 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -1117,9 +1117,13 @@ static int mgmt_read_local_features(int index, uint8_t *features)
return 0;
}
-static int mgmt_disconnect(int index, uint16_t handle)
+static int mgmt_disconnect(int index, bdaddr_t *bdaddr)
{
- DBG("index %d handle %u", index, handle);
+ char addr[18];
+
+ ba2str(bdaddr, addr);
+ DBG("index %d %s", index, addr);
+
return -ENOSYS;
}
@@ -1147,9 +1151,13 @@ static int mgmt_remove_bonding(int index, bdaddr_t *bdaddr)
return 0;
}
-static int mgmt_request_authentication(int index, uint16_t handle)
+static int mgmt_request_authentication(int index, bdaddr_t *bdaddr)
{
- DBG("index %d handle %u", index, handle);
+ char addr[18];
+
+ ba2str(bdaddr, addr);
+ DBG("index %d %s", index, addr);
+
return -ENOSYS;
}
diff --git a/src/adapter.c b/src/adapter.c
index 3f128844..e61a7d8f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -947,21 +947,6 @@ struct btd_device *adapter_find_device(struct btd_adapter *adapter,
return device;
}
-struct btd_device *adapter_find_connection(struct btd_adapter *adapter,
- uint16_t handle)
-{
- GSList *l;
-
- for (l = adapter->connections; l; l = l->next) {
- struct btd_device *device = l->data;
-
- if (device_has_connection(device, handle))
- return device;
- }
-
- return NULL;
-}
-
static void adapter_update_devices(struct btd_adapter *adapter)
{
char **devices;
@@ -2246,7 +2231,7 @@ static void load_connections(struct btd_adapter *adapter)
ba2str(&ci->bdaddr, address);
device = adapter_get_device(connection, adapter, address);
if (device)
- adapter_add_connection(adapter, device, ci->handle);
+ adapter_add_connection(adapter, device);
}
g_slist_foreach(conns, (GFunc) g_free, NULL);
@@ -2513,7 +2498,7 @@ int btd_adapter_stop(struct btd_adapter *adapter)
while (adapter->connections) {
struct btd_device *device = adapter->connections->data;
- adapter_remove_connection(adapter, device, 0);
+ adapter_remove_connection(adapter, device);
}
if (adapter->scan_mode == (SCAN_PAGE | SCAN_INQUIRY)) {
@@ -3191,29 +3176,29 @@ struct agent *adapter_get_agent(struct btd_adapter *adapter)
}
void adapter_add_connection(struct btd_adapter *adapter,
- struct btd_device *device, uint16_t handle)
+ struct btd_device *device)
{
if (g_slist_find(adapter->connections, device)) {
- error("Unable to add connection %d", handle);
+ error("Device is already marked as connected");
return;
}
- device_add_connection(device, connection, handle);
+ device_add_connection(device, connection);
adapter->connections = g_slist_append(adapter->connections, device);
}
void adapter_remove_connection(struct btd_adapter *adapter,
- struct btd_device *device, uint16_t handle)
+ struct btd_device *device)
{
bdaddr_t bdaddr;
if (!g_slist_find(adapter->connections, device)) {
- error("No matching connection for handle %u", handle);
+ error("No matching connection for device");
return;
}
- device_remove_connection(device, connection, handle);
+ device_remove_connection(device, connection);
adapter->connections = g_slist_remove(adapter->connections, device);
@@ -3594,9 +3579,9 @@ int btd_adapter_read_clock(struct btd_adapter *adapter, bdaddr_t *bdaddr,
timeout, clock, accuracy);
}
-int btd_adapter_disconnect_device(struct btd_adapter *adapter, uint16_t handle)
+int btd_adapter_disconnect_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
{
- return adapter_ops->disconnect(adapter->dev_id, handle);
+ return adapter_ops->disconnect(adapter->dev_id, bdaddr);
}
int btd_adapter_remove_bonding(struct btd_adapter *adapter, bdaddr_t *bdaddr)
@@ -3605,9 +3590,9 @@ int btd_adapter_remove_bonding(struct btd_adapter *adapter, bdaddr_t *bdaddr)
}
int btd_adapter_request_authentication(struct btd_adapter *adapter,
- uint16_t handle)
+ bdaddr_t *bdaddr)
{
- return adapter_ops->request_authentication(adapter->dev_id, handle);
+ return adapter_ops->request_authentication(adapter->dev_id, bdaddr);
}
int btd_adapter_pincode_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
diff --git a/src/adapter.h b/src/adapter.h
index 83965692..27553b74 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -115,8 +115,6 @@ struct btd_device *adapter_get_device(DBusConnection *conn,
struct btd_device *adapter_find_device(struct btd_adapter *adapter, const char *dest);
-struct btd_device *adapter_find_connection(struct btd_adapter *adapter, uint16_t handle);
-
void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
struct btd_device *device,
gboolean remove_storage);
@@ -156,9 +154,9 @@ void btd_adapter_pairable_changed(struct btd_adapter *adapter,
struct agent *adapter_get_agent(struct btd_adapter *adapter);
void adapter_add_connection(struct btd_adapter *adapter,
- struct btd_device *device, uint16_t handle);
+ struct btd_device *device);
void adapter_remove_connection(struct btd_adapter *adapter,
- struct btd_device *device, uint16_t handle);
+ struct btd_device *device);
gboolean adapter_has_discov_sessions(struct btd_adapter *adapter);
void adapter_suspend_discovery(struct btd_adapter *adapter);
void adapter_resume_discovery(struct btd_adapter *adapter);
@@ -221,9 +219,9 @@ struct btd_adapter_ops {
int (*get_conn_list) (int index, GSList **conns);
int (*read_local_version) (int index, struct hci_version *ver);
int (*read_local_features) (int index, uint8_t *features);
- int (*disconnect) (int index, uint16_t handle);
+ int (*disconnect) (int index, bdaddr_t *bdaddr);
int (*remove_bonding) (int index, bdaddr_t *bdaddr);
- int (*request_authentication) (int index, uint16_t handle);
+ int (*request_authentication) (int index, bdaddr_t *bdaddr);
int (*pincode_reply) (int index, bdaddr_t *bdaddr, const char *pin);
int (*confirm_reply) (int index, bdaddr_t *bdaddr, gboolean success);
int (*passkey_reply) (int index, bdaddr_t *bdaddr, uint32_t passkey);
@@ -266,12 +264,12 @@ int btd_adapter_block_address(struct btd_adapter *adapter, bdaddr_t *bdaddr);
int btd_adapter_unblock_address(struct btd_adapter *adapter, bdaddr_t *bdaddr);
int btd_adapter_disconnect_device(struct btd_adapter *adapter,
- uint16_t handle);
+ bdaddr_t *bdaddr);
int btd_adapter_remove_bonding(struct btd_adapter *adapter, bdaddr_t *bdaddr);
int btd_adapter_request_authentication(struct btd_adapter *adapter,
- uint16_t handle);
+ bdaddr_t *bdaddr);
int btd_adapter_pincode_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
const char *pin);
diff --git a/src/device.c b/src/device.c
index b7b9a983..bf42b4b0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -134,7 +134,7 @@ struct btd_device {
uint8_t cap;
uint8_t auth;
- uint16_t handle; /* Connection handle */
+ gboolean connected;
/* Whether were creating a security mode 3 connection */
gboolean secmode3;
@@ -328,9 +328,8 @@ static DBusMessage *get_properties(DBusConnection *conn,
dict_append_entry(&dict, "Blocked", DBUS_TYPE_BOOLEAN, &boolean);
/* Connected */
- boolean = (device->handle != 0);
dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN,
- &boolean);
+ &device->connected);
/* UUIDs */
str = g_new0(char *, g_slist_length(device->uuids) + 1);
@@ -435,7 +434,7 @@ static gboolean do_disconnect(gpointer user_data)
device->disconn_timer = 0;
- btd_adapter_disconnect_device(device->adapter, device->handle);
+ btd_adapter_disconnect_device(device->adapter, &device->bdaddr);
return FALSE;
}
@@ -448,7 +447,7 @@ static int device_block(DBusConnection *conn, struct btd_device *device)
if (device->blocked)
return 0;
- if (device->handle)
+ if (device->connected)
do_disconnect(device);
g_slist_foreach(device->drivers, (GFunc) driver_remove, device);
@@ -783,7 +782,7 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
{
struct btd_device *device = user_data;
- if (!device->handle)
+ if (!device->connected)
return btd_error_not_connected(msg);
device_request_disconnect(device, msg);
@@ -810,7 +809,7 @@ static GDBusSignalTable device_signals[] = {
gboolean device_is_connected(struct btd_device *device)
{
- return (device->handle != 0);
+ return device->connected;
}
static void device_set_connected(struct btd_device *device,
@@ -832,34 +831,30 @@ static void device_set_connected(struct btd_device *device,
}
}
-void device_add_connection(struct btd_device *device, DBusConnection *conn,
- uint16_t handle)
+void device_add_connection(struct btd_device *device, DBusConnection *conn)
{
- if (device->handle) {
+ if (device->connected) {
char addr[18];
ba2str(&device->bdaddr, addr);
- error("%s: Unable to add connection %u, %u already exist",
- addr, handle, device->handle);
+ error("Device %s is already connected", addr);
return;
}
- device->handle = handle;
+ device->connected = TRUE;
device_set_connected(device, conn, TRUE);
}
-void device_remove_connection(struct btd_device *device, DBusConnection *conn,
- uint16_t handle)
+void device_remove_connection(struct btd_device *device, DBusConnection *conn)
{
- if (handle && device->handle != handle) {
+ if (!device->connected) {
char addr[18];
ba2str(&device->bdaddr, addr);
- error("%s: connection handle mismatch %u != %u",
- addr, handle, device->handle);
+ error("Device %s isn't connected", addr);
return;
}
- device->handle = 0;
+ device->connected = FALSE;
if (device->disconn_timer > 0) {
g_source_remove(device->disconn_timer);
@@ -876,11 +871,6 @@ void device_remove_connection(struct btd_device *device, DBusConnection *conn,
device_set_connected(device, conn, FALSE);
}
-gboolean device_has_connection(struct btd_device *device, uint16_t handle)
-{
- return (handle == device->handle);
-}
-
guint device_add_disconnect_watch(struct btd_device *device,
disconnect_watch watch, void *user_data,
GDestroyNotify destroy)
@@ -1064,7 +1054,7 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
browse_request_cancel(device->browse);
}
- if (device->handle)
+ if (device->connected)
do_disconnect(device);
if (remove_stored)
@@ -2016,7 +2006,8 @@ static void bonding_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
goto failed;
}
- if (btd_adapter_request_authentication(device->adapter, handle) < 0)
+ if (btd_adapter_request_authentication(device->adapter,
+ &device->bdaddr) < 0)
goto failed;
return;
diff --git a/src/device.h b/src/device.h
index 5dea953d..f1bdd395 100644
--- a/src/device.h
+++ b/src/device.h
@@ -98,11 +98,8 @@ void device_set_authorizing(struct btd_device *device, gboolean auth);
void device_set_renewed_key(struct btd_device *device, gboolean renewed);
gboolean device_set_debug_key(struct btd_device *device, uint8_t *key);
gboolean device_get_debug_key(struct btd_device *device, uint8_t *key);
-void device_add_connection(struct btd_device *device, DBusConnection *conn,
- uint16_t handle);
-void device_remove_connection(struct btd_device *device, DBusConnection *conn,
- uint16_t handle);
-gboolean device_has_connection(struct btd_device *device, uint16_t handle);
+void device_add_connection(struct btd_device *device, DBusConnection *conn);
+void device_remove_connection(struct btd_device *device, DBusConnection *conn);
void device_request_disconnect(struct btd_device *device, DBusMessage *msg);
typedef void (*disconnect_watch) (struct btd_device *device, gboolean removal,
diff --git a/src/event.c b/src/event.c
index 00b9ad7e..11f153ee 100644
--- a/src/event.c
+++ b/src/event.c
@@ -785,8 +785,7 @@ proceed:
return 0;
}
-void btd_event_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle,
- bdaddr_t *peer)
+void btd_event_conn_complete(bdaddr_t *local, uint8_t status, bdaddr_t *peer)
{
struct btd_adapter *adapter;
struct btd_device *device;
@@ -809,33 +808,18 @@ void btd_event_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle,
update_lastused(local, peer);
- adapter_add_connection(adapter, device, handle);
+ adapter_add_connection(adapter, device);
}
-void btd_event_disconn_complete(bdaddr_t *local, uint8_t status,
- uint16_t handle, uint8_t reason)
+void btd_event_disconn_complete(bdaddr_t *local, bdaddr_t *peer)
{
struct btd_adapter *adapter;
struct btd_device *device;
- if (status) {
- error("Disconnection failed: 0x%02x", status);
- return;
- }
-
- adapter = manager_find_adapter(local);
- if (!adapter) {
- error("No matching adapter found");
- return;
- }
-
- device = adapter_find_connection(adapter, handle);
- if (!device) {
- DBG("No matching connection found for handle %u", handle);
+ if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
return;
- }
- adapter_remove_connection(adapter, device, handle);
+ adapter_remove_connection(adapter, device);
}
/* Section reserved to device HCI callbacks */
diff --git a/src/event.h b/src/event.h
index 941902a9..ab51018c 100644
--- a/src/event.h
+++ b/src/event.h
@@ -29,8 +29,8 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
void btd_event_set_legacy_pairing(bdaddr_t *local, bdaddr_t *peer, gboolean legacy);
void btd_event_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t class);
void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name);
-void btd_event_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer);
-void btd_event_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, uint8_t reason);
+void btd_event_conn_complete(bdaddr_t *local, uint8_t status, bdaddr_t *peer);
+void btd_event_disconn_complete(bdaddr_t *local, bdaddr_t *peer);
void btd_event_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t status);
void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t status);
void btd_event_setscan_enable_complete(bdaddr_t *local);