The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: mgmt: Translate HCI reason in Device Disconnected event
@ 2026-07-10  9:47 Mikhail Gavrilov
  2026-07-10 20:10 ` patchwork-bot+bluetooth
  0 siblings, 1 reply; 2+ messages in thread
From: Mikhail Gavrilov @ 2026-07-10  9:47 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-kernel,
	Mikhail Gavrilov

MGMT_EV_DEVICE_DISCONNECTED carries a reason field which is defined to
be one of MGMT_DEV_DISCONN_* (0x00..0x05). hci_disconn_complete_evt()
converts the HCI error with hci_to_mgmt_reason(), but two other paths
pass the raw HCI error straight through:

  hci_cs_disconnect()   -> cp->reason
  mgmt_connect_failed() -> status

The latter is reached whenever the adapter is powered off or suspended:
hci_disconnect_all_sync() aborts every link with
HCI_ERROR_REMOTE_POWER_OFF, hci_disconnect_sync() deliberately does not
wait for HCI_EV_DISCONN_COMPLETE for that reason, so that
hci_abort_conn_sync() finishes the connection off through
hci_conn_failed() instead.

As a result userspace sees an out of range reason:

  @ MGMT Event: Device Disconnected (0x000c) plen 8
        BR/EDR Address: 8C:A9:6F:2C:51:46
        Reason: Reserved (0x15)

  bluetoothd: btd_bearer_disconnected() Unknown disconnection value: 21
  bluetoothd: device_disconnected() Unknown disconnection value: 21

Export hci_to_mgmt_reason() and use it in both places, so that a power
off is reported as MGMT_DEV_DISCONN_REMOTE rather than as the raw
HCI_ERROR_REMOTE_POWER_OFF (0x15).

Fixes: d47da6bd4cfa ("Bluetooth: hci_core: Fix sending MGMT_EV_CONNECT_FAILED")
Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier")
Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
---

Tested on 7.2.0-rc2 with an MT7922 controller and Denon PerL Pro
earbuds. Before the patch "systemctl stop bluetooth" produced

  @ MGMT Event: Device Disconnected  Reason: Reserved (0x15)
  bluetoothd: btd_bearer_disconnected() Unknown disconnection value: 21

and with it the event carries MGMT_DEV_DISCONN_REMOTE, with no
complaint from bluetoothd. Explicit disconnects, which take the
hci_disconn_complete_evt() path, are unchanged.

Note that the hci_cs_disconnect() call site is not reachable in
practice: it requires either hdev->suspended, in which case
mgmt_device_disconnected() overrides the reason with
MGMT_DEV_DISCONN_LOCAL_HOST_SUSPEND anyway, or a
HCI_ERROR_UNKNOWN_CONN_ID race. It is fixed for consistency only and
was not exercised by the above.

 include/net/bluetooth/hci_core.h |  1 +
 net/bluetooth/hci_event.c        | 18 +-----------------
 net/bluetooth/mgmt.c             | 19 ++++++++++++++++++-
 3 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4ca09298e11a..e7133ff87fbf 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -2430,6 +2430,7 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
 		       bool persistent);
 void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
 			   u8 *name, u8 name_len);
+u8 hci_to_mgmt_reason(u8 err);
 void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
 			      u8 link_type, u8 addr_type, u8 reason,
 			      bool mgmt_connected);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b6d963ce26d0..741d658e9630 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2763,7 +2763,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
 	}
 
 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
-				 cp->reason, mgmt_conn);
+				 hci_to_mgmt_reason(cp->reason), mgmt_conn);
 
 	hci_disconn_cfm(conn, cp->reason);
 
@@ -3381,22 +3381,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
 	hci_dev_unlock(hdev);
 }
 
-static u8 hci_to_mgmt_reason(u8 err)
-{
-	switch (err) {
-	case HCI_ERROR_CONNECTION_TIMEOUT:
-		return MGMT_DEV_DISCONN_TIMEOUT;
-	case HCI_ERROR_REMOTE_USER_TERM:
-	case HCI_ERROR_REMOTE_LOW_RESOURCES:
-	case HCI_ERROR_REMOTE_POWER_OFF:
-		return MGMT_DEV_DISCONN_REMOTE;
-	case HCI_ERROR_LOCAL_HOST_TERM:
-		return MGMT_DEV_DISCONN_LOCAL_HOST;
-	default:
-		return MGMT_DEV_DISCONN_UNKNOWN;
-	}
-}
-
 static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
 				     struct sk_buff *skb)
 {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 733a4b70e10c..1c1b64e651dc 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -9848,6 +9848,22 @@ bool mgmt_powering_down(struct hci_dev *hdev)
 	return false;
 }
 
+u8 hci_to_mgmt_reason(u8 err)
+{
+	switch (err) {
+	case HCI_ERROR_CONNECTION_TIMEOUT:
+		return MGMT_DEV_DISCONN_TIMEOUT;
+	case HCI_ERROR_REMOTE_USER_TERM:
+	case HCI_ERROR_REMOTE_LOW_RESOURCES:
+	case HCI_ERROR_REMOTE_POWER_OFF:
+		return MGMT_DEV_DISCONN_REMOTE;
+	case HCI_ERROR_LOCAL_HOST_TERM:
+		return MGMT_DEV_DISCONN_LOCAL_HOST;
+	default:
+		return MGMT_DEV_DISCONN_UNKNOWN;
+	}
+}
+
 void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
 			      u8 link_type, u8 addr_type, u8 reason,
 			      bool mgmt_connected)
@@ -9909,7 +9925,8 @@ void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn, u8 status)
 
 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
 		mgmt_device_disconnected(hdev, &conn->dst, conn->type,
-					 conn->dst_type, status, true);
+					 conn->dst_type,
+					 hci_to_mgmt_reason(status), true);
 		return;
 	}
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-10 20:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10  9:47 [PATCH] Bluetooth: mgmt: Translate HCI reason in Device Disconnected event Mikhail Gavrilov
2026-07-10 20:10 ` patchwork-bot+bluetooth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox