Skip to content

Commit 75ddcd5

Browse files
Hsin-chen ChuangVudentz
authored andcommitted
Bluetooth: btusb: Configure altsetting for HCI_USER_CHANNEL
Automatically configure the altsetting for HCI_USER_CHANNEL when a SCO is connected. The motivation is to enable the HCI_USER_CHANNEL user to send out SCO data through USB Bluetooth chips, which is mainly used for bidirectional audio transfer (voice call). This was not capable because: - Per Bluetooth Core Spec v5, Vol 4, Part B, 2.1, the corresponding alternate setting should be set based on the air mode in order to transfer SCO data, but - The Linux Bluetooth HCI_USER_CHANNEL exposes the Bluetooth Host Controller Interface to the user space, which is something above the USB layer. The user space is not able to configure the USB alt while keeping the channel open. This patch intercepts the HCI_EV_SYNC_CONN_COMPLETE packets in btusb, extracts the air mode, and configures the alt setting in btusb. This patch is tested on ChromeOS devices. The USB Bluetooth models (CVSD, TRANS alt3 and alt6) could work without a customized kernel. Fixes: b16b327 ("Bluetooth: btusb: add sysfs attribute to control USB alt setting") Signed-off-by: Hsin-chen Chuang <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent fc14f9c commit 75ddcd5

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

drivers/bluetooth/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ config BT_HCIBTUSB_POLL_SYNC
5656
Say Y here to enable USB poll_sync for Bluetooth USB devices by
5757
default.
5858

59+
config BT_HCIBTUSB_AUTO_ISOC_ALT
60+
bool "Automatically adjust alternate setting for Isoc endpoints"
61+
depends on BT_HCIBTUSB
62+
default y if CHROME_PLATFORMS
63+
help
64+
Say Y here to automatically adjusting the alternate setting for
65+
HCI_USER_CHANNEL whenever a SCO link is established.
66+
67+
When enabled, btusb intercepts the HCI_EV_SYNC_CONN_COMPLETE packets
68+
and configures isoc endpoint alternate setting automatically when
69+
HCI_USER_CHANNEL is in use.
70+
5971
config BT_HCIBTUSB_BCM
6072
bool "Broadcom protocol support"
6173
depends on BT_HCIBTUSB

drivers/bluetooth/btusb.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static bool force_scofix;
3434
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
3535
static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC);
3636
static bool reset = true;
37+
static bool auto_isoc_alt = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTO_ISOC_ALT);
3738

3839
static struct usb_driver btusb_driver;
3940

@@ -1085,13 +1086,53 @@ static inline void btusb_free_frags(struct btusb_data *data)
10851086
spin_unlock_irqrestore(&data->rxlock, flags);
10861087
}
10871088

1089+
static void btusb_sco_connected(struct btusb_data *data, struct sk_buff *skb)
1090+
{
1091+
struct hci_event_hdr *hdr = (void *) skb->data;
1092+
struct hci_ev_sync_conn_complete *ev =
1093+
(void *) skb->data + sizeof(*hdr);
1094+
struct hci_dev *hdev = data->hdev;
1095+
unsigned int notify_air_mode;
1096+
1097+
if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT)
1098+
return;
1099+
1100+
if (skb->len < sizeof(*hdr) || hdr->evt != HCI_EV_SYNC_CONN_COMPLETE)
1101+
return;
1102+
1103+
if (skb->len != sizeof(*hdr) + sizeof(*ev) || ev->status)
1104+
return;
1105+
1106+
switch (ev->air_mode) {
1107+
case BT_CODEC_CVSD:
1108+
notify_air_mode = HCI_NOTIFY_ENABLE_SCO_CVSD;
1109+
break;
1110+
1111+
case BT_CODEC_TRANSPARENT:
1112+
notify_air_mode = HCI_NOTIFY_ENABLE_SCO_TRANSP;
1113+
break;
1114+
1115+
default:
1116+
return;
1117+
}
1118+
1119+
bt_dev_info(hdev, "enabling SCO with air mode %u", ev->air_mode);
1120+
data->sco_num = 1;
1121+
data->air_mode = notify_air_mode;
1122+
schedule_work(&data->work);
1123+
}
1124+
10881125
static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
10891126
{
10901127
if (data->intr_interval) {
10911128
/* Trigger dequeue immediately if an event is received */
10921129
schedule_delayed_work(&data->rx_work, 0);
10931130
}
10941131

1132+
/* Configure altsetting for HCI_USER_CHANNEL on SCO connected */
1133+
if (auto_isoc_alt && hci_dev_test_flag(data->hdev, HCI_USER_CHANNEL))
1134+
btusb_sco_connected(data, skb);
1135+
10951136
return data->recv_event(data->hdev, skb);
10961137
}
10971138

0 commit comments

Comments
 (0)