aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci.h6
-rw-r--r--include/net/bluetooth/hci_core.h9
-rw-r--r--net/bluetooth/hci_conn.c31
-rw-r--r--net/bluetooth/hci_event.c4
4 files changed, 43 insertions, 7 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 5f04181b8109..10a3eec191fd 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -297,6 +297,7 @@ struct hci_cp_host_buffer_size {
297 297
298/* Link Control */ 298/* Link Control */
299#define OGF_LINK_CTL 0x01 299#define OGF_LINK_CTL 0x01
300
300#define OCF_CREATE_CONN 0x0005 301#define OCF_CREATE_CONN 0x0005
301struct hci_cp_create_conn { 302struct hci_cp_create_conn {
302 bdaddr_t bdaddr; 303 bdaddr_t bdaddr;
@@ -307,6 +308,11 @@ struct hci_cp_create_conn {
307 __u8 role_switch; 308 __u8 role_switch;
308} __attribute__ ((packed)); 309} __attribute__ ((packed));
309 310
311#define OCF_CREATE_CONN_CANCEL 0x0008
312struct hci_cp_create_conn_cancel {
313 bdaddr_t bdaddr;
314} __attribute__ ((packed));
315
310#define OCF_ACCEPT_CONN_REQ 0x0009 316#define OCF_ACCEPT_CONN_REQ 0x0009
311struct hci_cp_accept_conn_req { 317struct hci_cp_accept_conn_req {
312 bdaddr_t bdaddr; 318 bdaddr_t bdaddr;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 7451a9c92d9d..df22efcfcc0b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -316,10 +316,13 @@ static inline void hci_conn_put(struct hci_conn *conn)
316 if (atomic_dec_and_test(&conn->refcnt)) { 316 if (atomic_dec_and_test(&conn->refcnt)) {
317 unsigned long timeo; 317 unsigned long timeo;
318 if (conn->type == ACL_LINK) { 318 if (conn->type == ACL_LINK) {
319 timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
320 if (!conn->out)
321 timeo *= 2;
322 del_timer(&conn->idle_timer); 319 del_timer(&conn->idle_timer);
320 if (conn->state == BT_CONNECTED) {
321 timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
322 if (!conn->out)
323 timeo *= 2;
324 } else
325 timeo = msecs_to_jiffies(10);
323 } else 326 } else
324 timeo = msecs_to_jiffies(10); 327 timeo = msecs_to_jiffies(10);
325 mod_timer(&conn->disc_timer, jiffies + timeo); 328 mod_timer(&conn->disc_timer, jiffies + timeo);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7e9515b41cc0..90e3a285a17e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -84,6 +84,20 @@ static void hci_acl_connect(struct hci_conn *conn)
84 hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp); 84 hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
85} 85}
86 86
87static void hci_acl_connect_cancel(struct hci_conn *conn)
88{
89 struct hci_cp_create_conn_cancel cp;
90
91 BT_DBG("%p", conn);
92
93 if (conn->hdev->hci_ver < 2)
94 return;
95
96 bacpy(&cp.bdaddr, &conn->dst);
97 hci_send_cmd(conn->hdev, OGF_LINK_CTL,
98 OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp);
99}
100
87void hci_acl_disconn(struct hci_conn *conn, __u8 reason) 101void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
88{ 102{
89 struct hci_cp_disconnect cp; 103 struct hci_cp_disconnect cp;
@@ -94,7 +108,8 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
94 108
95 cp.handle = __cpu_to_le16(conn->handle); 109 cp.handle = __cpu_to_le16(conn->handle);
96 cp.reason = reason; 110 cp.reason = reason;
97 hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT, sizeof(cp), &cp); 111 hci_send_cmd(conn->hdev, OGF_LINK_CTL,
112 OCF_DISCONNECT, sizeof(cp), &cp);
98} 113}
99 114
100void hci_add_sco(struct hci_conn *conn, __u16 handle) 115void hci_add_sco(struct hci_conn *conn, __u16 handle)
@@ -124,12 +139,20 @@ static void hci_conn_timeout(unsigned long arg)
124 return; 139 return;
125 140
126 hci_dev_lock(hdev); 141 hci_dev_lock(hdev);
127 if (conn->state == BT_CONNECTED) 142
143 switch (conn->state) {
144 case BT_CONNECT:
145 hci_acl_connect_cancel(conn);
146 break;
147 case BT_CONNECTED:
128 hci_acl_disconn(conn, 0x13); 148 hci_acl_disconn(conn, 0x13);
129 else 149 break;
150 default:
130 conn->state = BT_CLOSED; 151 conn->state = BT_CLOSED;
152 break;
153 }
154
131 hci_dev_unlock(hdev); 155 hci_dev_unlock(hdev);
132 return;
133} 156}
134 157
135static void hci_conn_idle(unsigned long arg) 158static void hci_conn_idle(unsigned long arg)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 7518bdbf34cd..bb25484b8747 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -750,6 +750,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
750 if (test_bit(HCI_ENCRYPT, &hdev->flags)) 750 if (test_bit(HCI_ENCRYPT, &hdev->flags))
751 conn->link_mode |= HCI_LM_ENCRYPT; 751 conn->link_mode |= HCI_LM_ENCRYPT;
752 752
753 hci_conn_hold(conn);
754
753 /* Get remote features */ 755 /* Get remote features */
754 if (conn->type == ACL_LINK) { 756 if (conn->type == ACL_LINK) {
755 struct hci_cp_read_remote_features cp; 757 struct hci_cp_read_remote_features cp;
@@ -778,6 +780,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
778 hci_send_cmd(hdev, OGF_LINK_CTL, 780 hci_send_cmd(hdev, OGF_LINK_CTL,
779 OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp); 781 OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
780 } 782 }
783
784 hci_conn_put(conn);
781 } else 785 } else
782 conn->state = BT_CLOSED; 786 conn->state = BT_CLOSED;
783 787