Commit efc7688b557dd1be10eead7399b315efcb1dbc74

Authored by Marcel Holtmann
1 parent 255c76014a

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>

Showing 3 changed files with 31 additions and 2 deletions Side-by-side Diff

include/net/bluetooth/hci.h
... ... @@ -133,8 +133,13 @@
133 133 #define ESCO_EV3 0x0008
134 134 #define ESCO_EV4 0x0010
135 135 #define ESCO_EV5 0x0020
  136 +#define ESCO_2EV3 0x0040
  137 +#define ESCO_3EV3 0x0080
  138 +#define ESCO_2EV5 0x0100
  139 +#define ESCO_3EV5 0x0200
136 140  
137 141 #define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
  142 +#define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)
138 143  
139 144 /* ACL flags */
140 145 #define ACL_CONT 0x01
... ... @@ -176,6 +181,9 @@
176 181 #define LMP_EV5 0x02
177 182  
178 183 #define LMP_SNIFF_SUBR 0x02
  184 +#define LMP_EDR_ESCO_2M 0x20
  185 +#define LMP_EDR_ESCO_3M 0x40
  186 +#define LMP_EDR_3S_ESCO 0x80
179 187  
180 188 #define LMP_SIMPLE_PAIR 0x08
181 189  
net/bluetooth/hci_conn.c
... ... @@ -123,6 +123,8 @@
123 123 conn->state = BT_CONNECT;
124 124 conn->out = 1;
125 125  
  126 + conn->attempt++;
  127 +
126 128 cp.handle = cpu_to_le16(handle);
127 129 cp.pkt_type = cpu_to_le16(conn->pkt_type);
128 130  
... ... @@ -139,6 +141,8 @@
139 141 conn->state = BT_CONNECT;
140 142 conn->out = 1;
141 143  
  144 + conn->attempt++;
  145 +
142 146 cp.handle = cpu_to_le16(handle);
143 147 cp.pkt_type = cpu_to_le16(conn->pkt_type);
144 148  
145 149  
... ... @@ -216,12 +220,13 @@
216 220 break;
217 221 case SCO_LINK:
218 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 225 else
221 226 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
222 227 break;
223 228 case ESCO_LINK:
224   - conn->pkt_type = hdev->esco_type;
  229 + conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
225 230 break;
226 231 }
227 232  
net/bluetooth/hci_event.c
... ... @@ -484,6 +484,15 @@
484 484 if (hdev->features[4] & LMP_EV5)
485 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 496 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
488 497 hdev->features[0], hdev->features[1],
489 498 hdev->features[2], hdev->features[3],
... ... @@ -1637,6 +1646,13 @@
1637 1646 goto unlock;
1638 1647  
1639 1648 conn->type = SCO_LINK;
  1649 + }
  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;
1640 1656 }
1641 1657  
1642 1658 if (!ev->status) {