aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h9
-rw-r--r--net/bluetooth/hci_core.c11
-rw-r--r--net/bluetooth/hci_event.c18
3 files changed, 33 insertions, 5 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 617cf495a449..b159810f67a6 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -402,6 +402,12 @@ struct hci_conn_params {
402 402
403 u16 conn_min_interval; 403 u16 conn_min_interval;
404 u16 conn_max_interval; 404 u16 conn_max_interval;
405
406 enum {
407 HCI_AUTO_CONN_DISABLED,
408 HCI_AUTO_CONN_ALWAYS,
409 HCI_AUTO_CONN_LINK_LOSS,
410 } auto_connect;
405}; 411};
406 412
407extern struct list_head hci_dev_list; 413extern struct list_head hci_dev_list;
@@ -796,7 +802,8 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
796struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, 802struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
797 bdaddr_t *addr, u8 addr_type); 803 bdaddr_t *addr, u8 addr_type);
798void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, 804void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
799 u16 conn_min_interval, u16 conn_max_interval); 805 u8 auto_connect, u16 conn_min_interval,
806 u16 conn_max_interval);
800void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); 807void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
801void hci_conn_params_clear(struct hci_dev *hdev); 808void hci_conn_params_clear(struct hci_dev *hdev);
802 809
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9a08f341f0a4..f4224dc58e4d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3202,7 +3202,8 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
3202 3202
3203/* This function requires the caller holds hdev->lock */ 3203/* This function requires the caller holds hdev->lock */
3204void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, 3204void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
3205 u16 conn_min_interval, u16 conn_max_interval) 3205 u8 auto_connect, u16 conn_min_interval,
3206 u16 conn_max_interval)
3206{ 3207{
3207 struct hci_conn_params *params; 3208 struct hci_conn_params *params;
3208 3209
@@ -3210,6 +3211,7 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
3210 if (params) { 3211 if (params) {
3211 params->conn_min_interval = conn_min_interval; 3212 params->conn_min_interval = conn_min_interval;
3212 params->conn_max_interval = conn_max_interval; 3213 params->conn_max_interval = conn_max_interval;
3214 params->auto_connect = auto_connect;
3213 return; 3215 return;
3214 } 3216 }
3215 3217
@@ -3223,12 +3225,13 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
3223 params->addr_type = addr_type; 3225 params->addr_type = addr_type;
3224 params->conn_min_interval = conn_min_interval; 3226 params->conn_min_interval = conn_min_interval;
3225 params->conn_max_interval = conn_max_interval; 3227 params->conn_max_interval = conn_max_interval;
3228 params->auto_connect = auto_connect;
3226 3229
3227 list_add(&params->list, &hdev->le_conn_params); 3230 list_add(&params->list, &hdev->le_conn_params);
3228 3231
3229 BT_DBG("addr %pMR (type %u) conn_min_interval 0x%.4x " 3232 BT_DBG("addr %pMR (type %u) auto_connect %u conn_min_interval 0x%.4x "
3230 "conn_max_interval 0x%.4x", addr, addr_type, conn_min_interval, 3233 "conn_max_interval 0x%.4x", addr, addr_type, auto_connect,
3231 conn_max_interval); 3234 conn_min_interval, conn_max_interval);
3232} 3235}
3233 3236
3234/* This function requires the caller holds hdev->lock */ 3237/* This function requires the caller holds hdev->lock */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b6631d7e2ddf..46da8b6f4368 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1841,6 +1841,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1841{ 1841{
1842 struct hci_ev_disconn_complete *ev = (void *) skb->data; 1842 struct hci_ev_disconn_complete *ev = (void *) skb->data;
1843 u8 reason = hci_to_mgmt_reason(ev->reason); 1843 u8 reason = hci_to_mgmt_reason(ev->reason);
1844 struct hci_conn_params *params;
1844 struct hci_conn *conn; 1845 struct hci_conn *conn;
1845 bool mgmt_connected; 1846 bool mgmt_connected;
1846 u8 type; 1847 u8 type;
@@ -1868,6 +1869,23 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1868 if (conn->type == ACL_LINK && conn->flush_key) 1869 if (conn->type == ACL_LINK && conn->flush_key)
1869 hci_remove_link_key(hdev, &conn->dst); 1870 hci_remove_link_key(hdev, &conn->dst);
1870 1871
1872 params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
1873 if (params) {
1874 switch (params->auto_connect) {
1875 case HCI_AUTO_CONN_LINK_LOSS:
1876 if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
1877 break;
1878 /* Fall through */
1879
1880 case HCI_AUTO_CONN_ALWAYS:
1881 hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type);
1882 break;
1883
1884 default:
1885 break;
1886 }
1887 }
1888
1871 type = conn->type; 1889 type = conn->type;
1872 1890
1873 hci_proto_disconn_cfm(conn, ev->reason); 1891 hci_proto_disconn_cfm(conn, ev->reason);