From 67a60317056c82fe94d059c21d327215aa5de1e4 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 6 Jan 2013 17:40:11 +0200 Subject: [PATCH] core: Move mgmt disconnection handling to adapter code --- src/adapter.c | 159 +++++++++++++++++++++++++++++++++++++------------- src/adapter.h | 2 - src/mgmt.c | 65 +-------------------- 3 files changed, 119 insertions(+), 107 deletions(-) diff --git a/src/adapter.c b/src/adapter.c index 536edb106..d596e4856 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -2302,46 +2302,6 @@ static void unload_drivers(struct btd_adapter *adapter) adapter->profiles = NULL; } -static void adapter_stop(struct btd_adapter *adapter) -{ - bool emit_discovering = false; - - /* check pending requests */ - reply_pending_requests(adapter); - - if (adapter->discovery) { - emit_discovering = true; - stop_discovery(adapter); - } - - if (adapter->disc_sessions) { - g_slist_free_full(adapter->disc_sessions, session_free); - adapter->disc_sessions = NULL; - } - - while (adapter->connections) { - struct btd_device *device = adapter->connections->data; - adapter_remove_connection(adapter, device); - } - - if (emit_discovering) - g_dbus_emit_property_changed(dbus_conn, adapter->path, - ADAPTER_INTERFACE, "Discovering"); - - if (adapter->dev_class) { - /* the kernel should reset the class of device when powering - * down, but it does not. So force it here ... */ - adapter->dev_class = 0; - g_dbus_emit_property_changed(dbus_conn, adapter->path, - ADAPTER_INTERFACE, "Class"); - } - - g_dbus_emit_property_changed(dbus_conn, adapter->path, - ADAPTER_INTERFACE, "Powered"); - - DBG("adapter %s has been disabled", adapter->path); -} - static void free_service_auth(gpointer data, gpointer user_data) { struct service_auth *auth = data; @@ -3629,7 +3589,7 @@ void adapter_add_connection(struct btd_adapter *adapter, adapter->connections = g_slist_append(adapter->connections, device); } -void adapter_remove_connection(struct btd_adapter *adapter, +static void adapter_remove_connection(struct btd_adapter *adapter, struct btd_device *device) { DBG(""); @@ -3654,6 +3614,46 @@ void adapter_remove_connection(struct btd_adapter *adapter, } } +static void adapter_stop(struct btd_adapter *adapter) +{ + bool emit_discovering = false; + + /* check pending requests */ + reply_pending_requests(adapter); + + if (adapter->discovery) { + emit_discovering = true; + stop_discovery(adapter); + } + + if (adapter->disc_sessions) { + g_slist_free_full(adapter->disc_sessions, session_free); + adapter->disc_sessions = NULL; + } + + while (adapter->connections) { + struct btd_device *device = adapter->connections->data; + adapter_remove_connection(adapter, device); + } + + if (emit_discovering) + g_dbus_emit_property_changed(dbus_conn, adapter->path, + ADAPTER_INTERFACE, "Discovering"); + + if (adapter->dev_class) { + /* the kernel should reset the class of device when powering + * down, but it does not. So force it here ... */ + adapter->dev_class = 0; + g_dbus_emit_property_changed(dbus_conn, adapter->path, + ADAPTER_INTERFACE, "Class"); + } + + g_dbus_emit_property_changed(dbus_conn, adapter->path, + ADAPTER_INTERFACE, "Powered"); + + DBG("adapter %s has been disabled", adapter->path); +} + int btd_register_adapter_driver(struct btd_adapter_driver *driver) { adapter_drivers = g_slist_append(adapter_drivers, driver); @@ -3921,12 +3921,62 @@ int btd_adapter_read_clock(struct btd_adapter *adapter, const bdaddr_t *bdaddr, return -ENOSYS; } +static void dev_disconnected(struct btd_adapter *adapter, + const struct mgmt_addr_info *addr, + uint8_t reason) +{ + struct btd_device *device; + char dst[18]; + + ba2str(&addr->bdaddr, dst); + + DBG("Device %s disconnected, reason %u", dst, reason); + + device = adapter_find_device(adapter, dst); + if (device) + adapter_remove_connection(adapter, device); + + adapter_bonding_complete(adapter, &addr->bdaddr, addr->type, + MGMT_STATUS_DISCONNECTED); +} + +static void disconnect_complete(uint8_t status, uint16_t length, + const void *param, void *user_data) +{ + const struct mgmt_rp_disconnect *rp = param; + struct btd_adapter *adapter = user_data; + + if (status != MGMT_STATUS_SUCCESS) { + error("Failed to disconnect device: %s (0x%02x)", + mgmt_errstr(status), status); + return; + } + + if (length < sizeof(*rp)) { + error("Too small device disconnect response"); + return; + } + + dev_disconnected(adapter, &rp->addr, MGMT_DEV_DISCONN_LOCAL_HOST); +} + int btd_adapter_disconnect_device(struct btd_adapter *adapter, const bdaddr_t *bdaddr, uint8_t bdaddr_type) { - return mgmt_disconnect(adapter->dev_id, bdaddr, bdaddr_type); + struct mgmt_cp_disconnect cp; + + memset(&cp, 0, sizeof(cp)); + bacpy(&cp.addr.bdaddr, bdaddr); + cp.addr.type = bdaddr_type; + + if (mgmt_send(adapter->mgmt, MGMT_OP_DISCONNECT, + adapter->dev_id, sizeof(cp), &cp, + disconnect_complete, adapter, NULL) > 0) + return 0; + + return -EIO; } int btd_adapter_remove_bonding(struct btd_adapter *adapter, @@ -4194,6 +4244,26 @@ static int adapter_unregister(struct btd_adapter *adapter) return 0; } +static void disconnected_callback(uint16_t index, uint16_t length, + const void *param, void *user_data) +{ + const struct mgmt_ev_device_disconnected *ev = param; + struct btd_adapter *adapter = user_data; + uint8_t reason; + + if (length < sizeof(struct mgmt_addr_info)) { + error("Too small device disconnected event"); + return; + } + + if (length < sizeof(*ev)) + reason = MGMT_DEV_DISCONN_UNKNOWN; + else + reason = ev->reason; + + dev_disconnected(adapter, &ev->addr, reason); +} + static void read_info_complete(uint8_t status, uint16_t length, const void *param, void *user_data) { @@ -4268,6 +4338,11 @@ static void read_info_complete(uint8_t status, uint16_t length, discovering_callback, adapter, NULL); + mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_DISCONNECTED, + adapter->dev_id, + disconnected_callback, + adapter, NULL); + set_dev_class(adapter, adapter->major_class, adapter->minor_class); set_name(adapter, btd_adapter_get_name(adapter)); diff --git a/src/adapter.h b/src/adapter.h index 8f0276bc8..944364b65 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -110,8 +110,6 @@ void adapter_service_remove(struct btd_adapter *adapter, void *rec); struct agent *adapter_get_agent(struct btd_adapter *adapter); void adapter_add_connection(struct btd_adapter *adapter, struct btd_device *device); -void adapter_remove_connection(struct btd_adapter *adapter, - struct btd_device *device); struct btd_adapter *btd_adapter_ref(struct btd_adapter *adapter); void btd_adapter_unref(struct btd_adapter *adapter); diff --git a/src/mgmt.c b/src/mgmt.c index d5088b2fe..10f21d176 100644 --- a/src/mgmt.c +++ b/src/mgmt.c @@ -224,35 +224,6 @@ static void mgmt_device_connected(uint16_t index, void *buf, size_t len) eir_data_free(&eir_data); } -static void mgmt_device_disconnected(uint16_t index, void *buf, size_t len) -{ - struct mgmt_ev_device_disconnected *ev = buf; - struct btd_adapter *adapter; - struct btd_device *device; - char addr[18]; - uint8_t reason; - - if (len < sizeof(struct mgmt_addr_info)) { - error("Too small device_disconnected event"); - return; - } - - if (len < sizeof(*ev)) - reason = MGMT_DEV_DISCONN_UNKNOWN; - else - reason = ev->reason; - - ba2str(&ev->addr.bdaddr, addr); - - DBG("hci%u device %s disconnected reason %u", index, addr, reason); - - if (!get_adapter_and_device(index, &ev->addr, &adapter, &device, false)) - return; - - if (device) - adapter_remove_connection(adapter, device); -} - static void mgmt_connect_failed(uint16_t index, void *buf, size_t len) { struct mgmt_ev_connect_failed *ev = buf; @@ -544,38 +515,6 @@ static void mgmt_user_confirm_request(uint16_t index, void *buf, } } -static void disconnect_complete(uint16_t index, uint8_t status, - void *buf, size_t len) -{ - struct mgmt_rp_disconnect *rp = buf; - struct btd_adapter *adapter; - struct btd_device *device; - char addr[18]; - - if (len < sizeof(*rp)) { - error("Too small disconnect complete event"); - return; - } - - ba2str(&rp->addr.bdaddr, addr); - - if (status != 0) { - error("Disconnecting %s failed with status %u", addr, status); - return; - } - - DBG("hci%d %s disconnected", index, addr); - - if (!get_adapter_and_device(index, &rp->addr, &adapter, &device, false)) - return; - - if (device) - adapter_remove_connection(adapter, device); - - adapter_bonding_complete(adapter, &rp->addr.bdaddr, rp->addr.type, - MGMT_STATUS_DISCONNECTED); -} - static void pair_device_complete(uint16_t index, uint8_t status, void *buf, size_t len) { @@ -687,7 +626,7 @@ static void mgmt_cmd_complete(uint16_t index, void *buf, size_t len) DBG("unpair_device complete"); break; case MGMT_OP_DISCONNECT: - disconnect_complete(index, ev->status, ev->data, len); + DBG("disconnect complete event"); break; case MGMT_OP_GET_CONNECTIONS: DBG("get_connections complete"); @@ -1070,7 +1009,7 @@ static gboolean mgmt_event(GIOChannel *channel, GIOCondition cond, mgmt_device_connected(index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_DISCONNECTED: - mgmt_device_disconnected(index, buf + MGMT_HDR_SIZE, len); + DBG("device_disconnected event"); break; case MGMT_EV_CONNECT_FAILED: mgmt_connect_failed(index, buf + MGMT_HDR_SIZE, len); -- 2.47.3