Bluetooth: mgmt: Add device disconnect reason
MGMT_EV_DEVICE_DISCONNECTED will now expose the disconnection reason to userland, distinguishing four possible values: 0x00 Reason not known or unspecified 0x01 Connection timeout 0x02 Connection terminated by local host 0x03 Connection terminated by remote host Note that the local/remote distinction just determines which side terminated the low-level connection, regardless of the disconnection of the higher-level profiles. This can sometimes be misleading and thus must be used with care. For example, some hardware combinations would report a locally initiated disconnection even if the user turned Bluetooth off in the remote side. Signed-off-by: Mikel Astiz <mikel.astiz@bmw-carit.de> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
This commit is contained in:
Родитель
fa1bd91809
Коммит
f0d6a0ea33
|
@ -1002,7 +1002,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
u8 addr_type, u32 flags, u8 *name, u8 name_len,
|
||||
u8 *dev_class);
|
||||
int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
u8 link_type, u8 addr_type);
|
||||
u8 link_type, u8 addr_type, u8 reason);
|
||||
int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
u8 link_type, u8 addr_type, u8 status);
|
||||
int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
||||
|
|
|
@ -405,7 +405,16 @@ struct mgmt_ev_device_connected {
|
|||
__u8 eir[0];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_DEV_DISCONN_UNKNOWN 0x00
|
||||
#define MGMT_DEV_DISCONN_TIMEOUT 0x01
|
||||
#define MGMT_DEV_DISCONN_LOCAL_HOST 0x02
|
||||
#define MGMT_DEV_DISCONN_REMOTE 0x03
|
||||
|
||||
#define MGMT_EV_DEVICE_DISCONNECTED 0x000C
|
||||
struct mgmt_ev_device_disconnected {
|
||||
struct mgmt_addr_info addr;
|
||||
__u8 reason;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_CONNECT_FAILED 0x000D
|
||||
struct mgmt_ev_connect_failed {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <net/bluetooth/mgmt.h>
|
||||
|
||||
/* Handle HCI Event packets */
|
||||
|
||||
|
@ -1875,6 +1876,22 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
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, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_disconn_complete *ev = (void *) skb->data;
|
||||
|
@ -1893,12 +1910,15 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
|
||||
(conn->type == ACL_LINK || conn->type == LE_LINK)) {
|
||||
if (ev->status)
|
||||
if (ev->status) {
|
||||
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, ev->status);
|
||||
else
|
||||
} else {
|
||||
u8 reason = hci_to_mgmt_reason(ev->reason);
|
||||
|
||||
mgmt_device_disconnected(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type);
|
||||
conn->dst_type, reason);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev->status == 0) {
|
||||
|
|
|
@ -3077,16 +3077,17 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
|
|||
}
|
||||
|
||||
int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
u8 link_type, u8 addr_type)
|
||||
u8 link_type, u8 addr_type, u8 reason)
|
||||
{
|
||||
struct mgmt_addr_info ev;
|
||||
struct mgmt_ev_device_disconnected ev;
|
||||
struct sock *sk = NULL;
|
||||
int err;
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
|
||||
|
||||
bacpy(&ev.bdaddr, bdaddr);
|
||||
ev.type = link_to_bdaddr(link_type, addr_type);
|
||||
bacpy(&ev.addr.bdaddr, bdaddr);
|
||||
ev.addr.type = link_to_bdaddr(link_type, addr_type);
|
||||
ev.reason = reason;
|
||||
|
||||
err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev),
|
||||
sk);
|
||||
|
|
Загрузка…
Ссылка в новой задаче