aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-10-10 10:38:27 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-10-11 02:30:58 -0400
commit53502d69be49e3dd5bc95ab0f2deeaea260bd617 (patch)
tree9a9318d66aa3c694e1428155dc8e43397db1e247
parent12d5978165944a9c5b059a8258685539387fcf90 (diff)
Bluetooth: AMP: Handle AMP_LINK timeout
When AMP_LINK timeouts execute HCI_OP_DISCONN_PHY_LINK as analog to HCI_OP_DISCONNECT for ACL_LINK. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--net/bluetooth/hci_conn.c32
2 files changed, 31 insertions, 3 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 90ae4f0a4fdc..dfa108c4abec 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -285,6 +285,8 @@ struct hci_dev {
285 int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); 285 int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
286}; 286};
287 287
288#define HCI_PHY_HANDLE(handle) (handle & 0xff)
289
288struct hci_conn { 290struct hci_conn {
289 struct list_head list; 291 struct list_head list;
290 292
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 53202f6733ae..64875794dd9b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -130,6 +130,20 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
130 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); 130 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
131} 131}
132 132
133static void hci_amp_disconn(struct hci_conn *conn, __u8 reason)
134{
135 struct hci_cp_disconn_phy_link cp;
136
137 BT_DBG("hcon %p", conn);
138
139 conn->state = BT_DISCONN;
140
141 cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
142 cp.reason = reason;
143 hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
144 sizeof(cp), &cp);
145}
146
133static void hci_add_sco(struct hci_conn *conn, __u16 handle) 147static void hci_add_sco(struct hci_conn *conn, __u16 handle)
134{ 148{
135 struct hci_dev *hdev = conn->hdev; 149 struct hci_dev *hdev = conn->hdev;
@@ -230,11 +244,24 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
230 } 244 }
231} 245}
232 246
247static void hci_conn_disconnect(struct hci_conn *conn)
248{
249 __u8 reason = hci_proto_disconn_ind(conn);
250
251 switch (conn->type) {
252 case ACL_LINK:
253 hci_acl_disconn(conn, reason);
254 break;
255 case AMP_LINK:
256 hci_amp_disconn(conn, reason);
257 break;
258 }
259}
260
233static void hci_conn_timeout(struct work_struct *work) 261static void hci_conn_timeout(struct work_struct *work)
234{ 262{
235 struct hci_conn *conn = container_of(work, struct hci_conn, 263 struct hci_conn *conn = container_of(work, struct hci_conn,
236 disc_work.work); 264 disc_work.work);
237 __u8 reason;
238 265
239 BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); 266 BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
240 267
@@ -253,8 +280,7 @@ static void hci_conn_timeout(struct work_struct *work)
253 break; 280 break;
254 case BT_CONFIG: 281 case BT_CONFIG:
255 case BT_CONNECTED: 282 case BT_CONNECTED:
256 reason = hci_proto_disconn_ind(conn); 283 hci_conn_disconnect(conn);
257 hci_acl_disconn(conn, reason);
258 break; 284 break;
259 default: 285 default:
260 conn->state = BT_CLOSED; 286 conn->state = BT_CLOSED;