Diff between cb2169a0abbcc90dc4df3c2d5828af097db88e86 and 67a60317056c82fe94d059c21d327215aa5de1e4

Changed Files

File Additions Deletions Status
src/adapter.c +117 -42 modified
src/adapter.h +0 -2 modified
src/mgmt.c +2 -63 modified

Full Patch

diff --git a/src/adapter.c b/src/adapter.c
index 536edb1..d596e48 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 8f0276b..944364b 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 d5088b2..10f21d1 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);