aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
authorMikel Astiz <mikel.astiz@bmw-carit.de>2012-08-09 03:52:30 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-08-21 13:54:40 -0400
commitf0d6a0ea330617454032d6e2ed48759858a44427 (patch)
treed11edf124abaef7d14f39fb9d0678376800fac72 /net/bluetooth/hci_event.c
parentfa1bd91809d58b3c183611556219fafd93c08625 (diff)
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>
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index bfa9bcc0f5ef..48d730228c2f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -29,6 +29,7 @@
29 29
30#include <net/bluetooth/bluetooth.h> 30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h> 31#include <net/bluetooth/hci_core.h>
32#include <net/bluetooth/mgmt.h>
32 33
33/* Handle HCI Event packets */ 34/* Handle HCI Event packets */
34 35
@@ -1875,6 +1876,22 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1875 } 1876 }
1876} 1877}
1877 1878
1879static u8 hci_to_mgmt_reason(u8 err)
1880{
1881 switch (err) {
1882 case HCI_ERROR_CONNECTION_TIMEOUT:
1883 return MGMT_DEV_DISCONN_TIMEOUT;
1884 case HCI_ERROR_REMOTE_USER_TERM:
1885 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1886 case HCI_ERROR_REMOTE_POWER_OFF:
1887 return MGMT_DEV_DISCONN_REMOTE;
1888 case HCI_ERROR_LOCAL_HOST_TERM:
1889 return MGMT_DEV_DISCONN_LOCAL_HOST;
1890 default:
1891 return MGMT_DEV_DISCONN_UNKNOWN;
1892 }
1893}
1894
1878static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1895static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1879{ 1896{
1880 struct hci_ev_disconn_complete *ev = (void *) skb->data; 1897 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)
1893 1910
1894 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1911 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1895 (conn->type == ACL_LINK || conn->type == LE_LINK)) { 1912 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
1896 if (ev->status) 1913 if (ev->status) {
1897 mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 1914 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1898 conn->dst_type, ev->status); 1915 conn->dst_type, ev->status);
1899 else 1916 } else {
1917 u8 reason = hci_to_mgmt_reason(ev->reason);
1918
1900 mgmt_device_disconnected(hdev, &conn->dst, conn->type, 1919 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
1901 conn->dst_type); 1920 conn->dst_type, reason);
1921 }
1902 } 1922 }
1903 1923
1904 if (ev->status == 0) { 1924 if (ev->status == 0) {