Skip to content

Commit

Permalink
Bluetooth: Add SCO fallback for eSCO connection attempts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marcel Holtmann committed Feb 27, 2009
1 parent 255c760 commit efc7688
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
8 changes: 8 additions & 0 deletions include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,13 @@ enum {
#define ESCO_EV3 0x0008
#define ESCO_EV4 0x0010
#define ESCO_EV5 0x0020
#define ESCO_2EV3 0x0040
#define ESCO_3EV3 0x0080
#define ESCO_2EV5 0x0100
#define ESCO_3EV5 0x0200

#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
#define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)

/* ACL flags */
#define ACL_CONT 0x01
Expand Down Expand Up @@ -176,6 +181,9 @@ enum {
#define LMP_EV5 0x02

#define LMP_SNIFF_SUBR 0x02
#define LMP_EDR_ESCO_2M 0x20
#define LMP_EDR_ESCO_3M 0x40
#define LMP_EDR_3S_ESCO 0x80

#define LMP_SIMPLE_PAIR 0x08

Expand Down
9 changes: 7 additions & 2 deletions net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
conn->state = BT_CONNECT;
conn->out = 1;

conn->attempt++;

cp.handle = cpu_to_le16(handle);
cp.pkt_type = cpu_to_le16(conn->pkt_type);

Expand All @@ -139,6 +141,8 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
conn->state = BT_CONNECT;
conn->out = 1;

conn->attempt++;

cp.handle = cpu_to_le16(handle);
cp.pkt_type = cpu_to_le16(conn->pkt_type);

Expand Down Expand Up @@ -216,12 +220,13 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
break;
case SCO_LINK:
if (lmp_esco_capable(hdev))
conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK;
conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
(hdev->esco_type & EDR_ESCO_MASK);
else
conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
break;
case ESCO_LINK:
conn->pkt_type = hdev->esco_type;
conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
break;
}

Expand Down
16 changes: 16 additions & 0 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,15 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb
if (hdev->features[4] & LMP_EV5)
hdev->esco_type |= (ESCO_EV5);

if (hdev->features[5] & LMP_EDR_ESCO_2M)
hdev->esco_type |= (ESCO_2EV3);

if (hdev->features[5] & LMP_EDR_ESCO_3M)
hdev->esco_type |= (ESCO_3EV3);

if (hdev->features[5] & LMP_EDR_3S_ESCO)
hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);

BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
hdev->features[0], hdev->features[1],
hdev->features[2], hdev->features[3],
Expand Down Expand Up @@ -1639,6 +1648,13 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
conn->type = SCO_LINK;
}

if (conn->out && ev->status == 0x1c && conn->attempt < 2) {
conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
(hdev->esco_type & EDR_ESCO_MASK);
hci_setup_sync(conn, conn->link->handle);
goto unlock;
}

if (!ev->status) {
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
Expand Down

0 comments on commit efc7688

Please sign in to comment.