From 6bb1125a577724d2da4cbb7a23f85185efa955a4 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 12:24:43 +0530 Subject: [PATCH] Bluetooth: Set link Supervision timeout for a connection This patch allows to set the supervision timeout for a connection if the device role is master. Change-Id: I204ebea960235ab4f858c9b57d57989e4426740e Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar Signed-off-by: Wootak Jung Signed-off-by: Jaehoon Chung --- include/net/bluetooth/bluetooth.h | 7 +++++++ include/net/bluetooth/hci.h | 15 +++++++++++++++ include/net/bluetooth/hci_core.h | 8 ++++++++ net/bluetooth/hci_conn.c | 27 +++++++++++++++++++++++++++ net/bluetooth/hci_core.c | 8 +++++++- net/bluetooth/hci_event.c | 11 +++++++++++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 5a3d66e..bbc7571 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -330,6 +330,13 @@ typedef struct { __u8 b[6]; } __packed bdaddr_t; +#ifdef TIZEN_BT +/* Automatically enable sniff mode for connection. + * In case of normal phone this timeout would be 5 seconds + */ +#define TIZEN_SNIFF_TIMEOUT 5 /* 5 seconds */ +#endif + /* BD Address type */ #define BDADDR_BREDR 0x00 #define BDADDR_LE_PUBLIC 0x01 diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 4b9df2d..eb1a3ba9 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1233,6 +1233,21 @@ struct hci_cp_host_buffer_size { __le16 sco_max_pkt; } __packed; +#ifdef TIZEN_BT +/* Set Link supervision timeout */ +#define HCI_OP_WRITE_LINK_SUPERVISION_TIMEOUT 0x0c37 +struct hci_cp_write_link_supervision_timeout { + __le16 handle; + __le16 timeout; +} __packed; + +struct hci_rp_write_link_supervision_timeout { + __u8 status; + __le16 handle; +} __packed; +/* Set Link supervision timeout */ +#endif /* TIZEN_BT */ + #define HCI_OP_READ_NUM_SUPPORTED_IAC 0x0c38 struct hci_rp_read_num_supported_iac { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 8258305..fc9ad74 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -974,6 +974,10 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, void hci_inquiry_cache_flush(struct hci_dev *hdev); /* ----- HCI Connections ----- */ +#ifdef TIZEN_BT +#define LINK_SUPERVISION_TIMEOUT 0x1F40 /* n * 0.625 = 5 seconds */ +#endif /* TIZEN_BT */ + enum { HCI_CONN_AUTH_PEND, HCI_CONN_ENCRYPT_PEND, @@ -1529,6 +1533,7 @@ static inline int hci_conn_hash_lookup_rssi_count(struct hci_dev *hdev) return count; } +int hci_conn_change_supervision_timeout(struct hci_conn *conn, __u16 timeout); bool hci_le_discovery_active(struct hci_dev *hdev); void hci_le_discovery_set_state(struct hci_dev *hdev, int state); @@ -1782,6 +1787,9 @@ int hci_get_dev_info(void __user *arg); int hci_get_conn_list(void __user *arg); int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); +#ifdef TIZEN_BT +u32 get_link_mode(struct hci_conn *conn); +#endif int hci_inquiry(void __user *arg); struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *list, diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 66e6a128..f22d277 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -2546,6 +2546,29 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role) } EXPORT_SYMBOL(hci_conn_switch_role); +#ifdef TIZEN_BT +int hci_conn_change_supervision_timeout(struct hci_conn *conn, __u16 timeout) +{ + struct hci_cp_write_link_supervision_timeout cp; + + if (!((get_link_mode(conn)) & HCI_LM_MASTER)) + return 1; + + if (conn->handle == 0) + return 1; + + memset(&cp, 0, sizeof(cp)); + cp.handle = cpu_to_le16(conn->handle); + cp.timeout = cpu_to_le16(timeout); + + if (hci_send_cmd(conn->hdev, HCI_OP_WRITE_LINK_SUPERVISION_TIMEOUT, + sizeof(cp), &cp) < 0) + BT_ERR("HCI_OP_WRITE_LINK_SUPERVISION_TIMEOUT is failed"); + + return 0; +} +#endif + /* Enter active mode */ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) { @@ -2608,7 +2631,11 @@ void hci_conn_check_pending(struct hci_dev *hdev) hci_dev_unlock(hdev); } +#ifndef TIZEN_BT static u32 get_link_mode(struct hci_conn *conn) +#else +u32 get_link_mode(struct hci_conn *conn) +#endif { u32 link_mode = 0; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 3a87f4f..df0025a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2541,12 +2541,18 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv) hdev->enable_advmon_interleave_scan = 0x00; /* Default to disable */ hdev->sniff_max_interval = 800; +#ifdef TIZEN_BT + hdev->sniff_min_interval = 400; +#else hdev->sniff_min_interval = 80; - +#endif hdev->le_adv_channel_map = 0x07; hdev->le_adv_min_interval = 0x0800; hdev->le_adv_max_interval = 0x0800; #ifdef TIZEN_BT + /* automatically enable sniff mode for connection */ + hdev->idle_timeout = TIZEN_SNIFF_TIMEOUT * 1000; + hdev->adv_filter_policy = 0x00; hdev->adv_type = 0x00; #endif diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8368ea0..8a49704 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3370,6 +3370,12 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), &cp); } + +#ifdef TIZEN_BT + if (get_link_mode(conn) & HCI_LM_MASTER) + hci_conn_change_supervision_timeout(conn, + LINK_SUPERVISION_TIMEOUT); +#endif } if (conn->type == ACL_LINK) @@ -4579,6 +4585,11 @@ static void hci_role_change_evt(struct hci_dev *hdev, void *data, clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); hci_role_switch_cfm(conn, ev->status, ev->role); +#ifdef TIZEN_BT + if (!ev->status && (get_link_mode(conn) & HCI_LM_MASTER)) + hci_conn_change_supervision_timeout(conn, + LINK_SUPERVISION_TIMEOUT); +#endif } hci_dev_unlock(hdev); -- 2.7.4