diff options
| -rw-r--r-- | include/net/bluetooth/hci.h | 6 | ||||
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 9 | ||||
| -rw-r--r-- | net/bluetooth/hci_conn.c | 31 | ||||
| -rw-r--r-- | net/bluetooth/hci_event.c | 4 |
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 |
| 301 | struct hci_cp_create_conn { | 302 | struct 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 | ||
| 312 | struct 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 |
| 311 | struct hci_cp_accept_conn_req { | 317 | struct 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 | ||
| 87 | static 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 | |||
| 87 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | 101 | void 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 | ||
| 100 | void hci_add_sco(struct hci_conn *conn, __u16 handle) | 115 | void 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 | ||
| 135 | static void hci_conn_idle(unsigned long arg) | 158 | static 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 | ||
