Bluetooth: Set link Supervision timeout for a connection
authorSudha Bheemanna <b.sudha@samsung.com>
Thu, 8 Sep 2016 06:54:43 +0000 (12:24 +0530)
committerJunghoon Kim <jhoon20.kim@samsung.com>
Thu, 2 Apr 2020 04:09:06 +0000 (13:09 +0900)
This patch allows to set the supervision timeout for a connection
if the device role is master.

Change-Id: I7897167ec07803f3059f2ab4d3314b0b7a951533
Signed-off-by: Sudha Bheemanna <b.sudha@samsung.com>
Signed-off-by: Amit Purwar <amit.purwar@samsung.com>
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c

index d5f01e8..433892d 100644 (file)
@@ -198,6 +198,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
index bcce0e8..2296a22 100644 (file)
@@ -1018,6 +1018,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;
index 29d7b67..997c852 100644 (file)
@@ -672,6 +672,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_REAUTH_PEND,
@@ -972,6 +976,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);
 
@@ -1162,6 +1167,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,
index 79476c5..5573a4e 100644 (file)
@@ -1488,6 +1488,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)
 {
@@ -1545,7 +1568,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;
 
index 0b75655..21f2d62 100644 (file)
@@ -3123,12 +3123,18 @@ struct hci_dev *hci_alloc_dev(void)
        hdev->adv_instance_timeout = 0;
 
        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
index 78ce5f6..8388308 100644 (file)
@@ -2574,6 +2574,11 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                        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
        } else {
                conn->state = BT_CLOSED;
                if (conn->type == ACL_LINK)
@@ -3657,6 +3662,11 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
                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);