summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-04-19 19:14:14 +0200
committerMarcel Holtmann <marcel@holtmann.org>2009-04-19 19:14:14 +0200
commit732547f96ea2442965a24e0ed529d285321a0fff (patch)
tree315350b2dfafd90f06d28163e8f3cf4807e4a6a3
parente2139b32726e5dd184974c785ea3f62026590801 (diff)
Bluetooth: Fallback from eSCO to SCO on unspecified error
Some Bluetooth chips (like the ones from Texas Instruments) don't do proper eSCO negotiations inside the Link Manager. They just return an error code and in case of the Kyocera ED-8800 headset it is just a random error. < HCI Command: Setup Synchronous Connection 0x01|0x0028) plen 17 handle 1 voice setting 0x0060 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1f handle 257 bdaddr 00:14:0A:xx:xx:xx type eSCO Error: Unspecified Error In these cases it is up to the host stack to fallback to a SCO setup and so retry with SCO parameters. Based on a report by Nick Pelly <npelly@google.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--net/bluetooth/hci_event.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 55534244c3a0..963f9662eaa8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1646,20 +1646,28 @@ 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) {
+ switch (ev->status) {
+ case 0x00:
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
hci_conn_add_sysfs(conn);
- } else
+ break;
+
+ case 0x1c: /* SCO interval rejected */
+ case 0x1f: /* Unspecified error */
+ if (conn->out && 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;
+ }
+ /* fall through */
+
+ default:
conn->state = BT_CLOSED;
+ break;
+ }
hci_proto_connect_cfm(conn, ev->status);
if (ev->status)