aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAndre Guedes <andre.guedes@openbossa.org>2014-02-26 18:21:48 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-02-26 22:41:34 -0500
commit9fcb18ef3acb51e54b6bca6d2d803676ac86813d (patch)
treec19f7f9d5fcca619785894898fb08522bb2b95e0 /net
parenta4790dbd43d1617b09d57e96494fde5a4b01980a (diff)
Bluetooth: Introduce LE auto connect options
This patch introduces the LE auto connection options: HCI_AUTO_CONN_ ALWAYS and HCI_AUTO_CONN_LINK_LOSS. Their working mechanism are described as follows: The HCI_AUTO_CONN_ALWAYS option configures the kernel to always re- establish the connection, no matter the reason the connection was terminated. This feature is required by some LE profiles such as HID over GATT, Health Thermometer and Blood Pressure. These profiles require the host autonomously connect to the device as soon as it enters in connectable mode (start advertising) so the device is able to delivery notifications or indications. The BT_AUTO_CONN_LINK_LOSS option configures the kernel to re- establish the connection in case the connection was terminated due to a link loss. This feature is required by the majority of LE profiles such as Proximity, Find Me, Cycling Speed and Cadence and Time. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c11
-rw-r--r--net/bluetooth/hci_event.c18
2 files changed, 25 insertions, 4 deletions
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);