aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-02-06 03:13:37 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:37 -0500
commitefc7688b557dd1be10eead7399b315efcb1dbc74 (patch)
treef51d32d047bbf27a106db679292c10a81b339836 /net/bluetooth
parent255c76014af74165428e7aa16414b857e2bdccf2 (diff)
Bluetooth: Add SCO fallback for eSCO connection attempts
When attempting to setup eSCO connections it can happen that some link manager implementations fail to properly negotiate the eSCO parameters and thus fail the eSCO setup. Normally the link manager is responsible for the negotiation of the parameters and actually fallback to SCO if no agreement can be reached. In cases where the link manager is just too stupid, then at least try to establish a SCO link if eSCO fails. For the Bluetooth devices with EDR support this includes handling packet types of EDR basebands. This is particular tricky since for the EDR the logic of enabling/disabling one specific packet type is turned around. This fix contains an extra bitmask to disable eSCO EDR packet when trying to fallback to a SCO connection. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_conn.c9
-rw-r--r--net/bluetooth/hci_event.c16
2 files changed, 23 insertions, 2 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 98f97a1e9bbb..2435e830ba60 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -123,6 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
123 conn->state = BT_CONNECT; 123 conn->state = BT_CONNECT;
124 conn->out = 1; 124 conn->out = 1;
125 125
126 conn->attempt++;
127
126 cp.handle = cpu_to_le16(handle); 128 cp.handle = cpu_to_le16(handle);
127 cp.pkt_type = cpu_to_le16(conn->pkt_type); 129 cp.pkt_type = cpu_to_le16(conn->pkt_type);
128 130
@@ -139,6 +141,8 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
139 conn->state = BT_CONNECT; 141 conn->state = BT_CONNECT;
140 conn->out = 1; 142 conn->out = 1;
141 143
144 conn->attempt++;
145
142 cp.handle = cpu_to_le16(handle); 146 cp.handle = cpu_to_le16(handle);
143 cp.pkt_type = cpu_to_le16(conn->pkt_type); 147 cp.pkt_type = cpu_to_le16(conn->pkt_type);
144 148
@@ -216,12 +220,13 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
216 break; 220 break;
217 case SCO_LINK: 221 case SCO_LINK:
218 if (lmp_esco_capable(hdev)) 222 if (lmp_esco_capable(hdev))
219 conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK; 223 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
224 (hdev->esco_type & EDR_ESCO_MASK);
220 else 225 else
221 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; 226 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
222 break; 227 break;
223 case ESCO_LINK: 228 case ESCO_LINK:
224 conn->pkt_type = hdev->esco_type; 229 conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
225 break; 230 break;
226 } 231 }
227 232
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 014fc8b320ba..899b8991a466 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -484,6 +484,15 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb
484 if (hdev->features[4] & LMP_EV5) 484 if (hdev->features[4] & LMP_EV5)
485 hdev->esco_type |= (ESCO_EV5); 485 hdev->esco_type |= (ESCO_EV5);
486 486
487 if (hdev->features[5] & LMP_EDR_ESCO_2M)
488 hdev->esco_type |= (ESCO_2EV3);
489
490 if (hdev->features[5] & LMP_EDR_ESCO_3M)
491 hdev->esco_type |= (ESCO_3EV3);
492
493 if (hdev->features[5] & LMP_EDR_3S_ESCO)
494 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
495
487 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 496 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
488 hdev->features[0], hdev->features[1], 497 hdev->features[0], hdev->features[1],
489 hdev->features[2], hdev->features[3], 498 hdev->features[2], hdev->features[3],
@@ -1639,6 +1648,13 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
1639 conn->type = SCO_LINK; 1648 conn->type = SCO_LINK;
1640 } 1649 }
1641 1650
1651 if (conn->out && ev->status == 0x1c && conn->attempt < 2) {
1652 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
1653 (hdev->esco_type & EDR_ESCO_MASK);
1654 hci_setup_sync(conn, conn->link->handle);
1655 goto unlock;
1656 }
1657
1642 if (!ev->status) { 1658 if (!ev->status) {
1643 conn->handle = __le16_to_cpu(ev->handle); 1659 conn->handle = __le16_to_cpu(ev->handle);
1644 conn->state = BT_CONNECTED; 1660 conn->state = BT_CONNECTED;