Hi, ke, 2024-05-29 kello 14:29 +0800, Chris Lu kirjoitti: > This patch implement function for ISO data send and receive in btusb > driver for MediaTek Controller. > > MediaTek define a specific interrupt endpoint for ISO data > transmission because the characteristics of interrupt are > similar to the application of ISO data which can ensure bandwidth, > has enough data length and support error check. > > Driver setup ISO interface in btusb_mtk_setup after download patch and > submit interrtupt urb to handle ISO data send and receive. > > Signed-off-by: Chris Lu <chris.lu@xxxxxxxxxxxx> > Signed-off-by: Sean Wang <sean.wang@xxxxxxxxxxxx> > --- > drivers/bluetooth/btmtk.c | 35 +++++ > drivers/bluetooth/btmtk.h | 23 +++ > drivers/bluetooth/btusb.c | 295 +++++++++++++++++++++++++++++++++++++- > 3 files changed, 352 insertions(+), 1 deletion(-) > > diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c > index a27c251bf56e..f0aecd319911 100644 > --- a/drivers/bluetooth/btmtk.c > +++ b/drivers/bluetooth/btmtk.c [clip] > @@ -2122,7 +2358,10 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) > return submit_tx_urb(hdev, urb); > > case HCI_ISODATA_PKT: > - urb = alloc_bulk_urb(hdev, skb); > + if (btmtk_test_flag(hdev, BTMTK_ISOPKT_OVER_INTR)) The btmtk flag macros require hci_get_priv(hdev) contains struct btmediatek_data. Here this is code for generic hdev, so probably misbehaves with non- mediatek hdev. > + urb = alloc_mtk_intr_urb(hdev, skb); > + else > + urb = alloc_bulk_urb(hdev, skb); > if (IS_ERR(urb)) > return PTR_ERR(urb); > > @@ -2650,6 +2889,8 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) > #define MTK_BT_RESET_REG_CONNV3 0x70028610 > #define MTK_BT_READ_DEV_ID 0x70010200 > > +/* MediaTek ISO interface number */ > +#define MTK_ISO_IFNUM 2 > > static void btusb_mtk_wmt_recv(struct urb *urb) > { > @@ -3126,6 +3367,28 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) > return err; > } > > +static int btusb_mtk_claim_iso_intf(struct btusb_data *data, struct usb_interface *intf) > +{ > + int err; > + > + err = usb_driver_claim_interface(&btusb_driver, intf, data); > + if (err < 0) > + return err; > + > + __set_mtk_intr_interface(data->hdev, MTK_ISO_IFNUM); > + > + err = btusb_mtk_submit_intr_urb(data->hdev, GFP_KERNEL); > + if (err < 0) { > + usb_kill_anchored_urbs(&data->isopkt_anchor); > + bt_dev_err(data->hdev, "ISO intf not support (%d)", err); > + return err; > + } > + > + btmtk_set_flag(data->hdev, BTMTK_ISOPKT_OVER_INTR); > + > + return 0; > +} > + > static int btusb_mtk_setup(struct hci_dev *hdev) > { > struct btusb_data *data = hci_get_drvdata(hdev); > @@ -3210,6 +3473,12 @@ static int btusb_mtk_setup(struct hci_dev *hdev) > /* It's Device EndPoint Reset Option Register */ > btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); > > + /* Claim USB interface and EndPoint for ISO data */ > + mediatek->isopkt_info.isopkt_intf = usb_ifnum_to_if(data->udev, MTK_ISO_IFNUM); > + err = btusb_mtk_claim_iso_intf(data, mediatek->isopkt_info.isopkt_intf); > + if (err < 0) > + mediatek->isopkt_info.isopkt_intf = NULL; > + > /* Enable Bluetooth protocol */ > param = 1; > wmt_params.op = BTMTK_WMT_FUNC_CTRL; > @@ -3226,6 +3495,13 @@ static int btusb_mtk_setup(struct hci_dev *hdev) > > hci_set_msft_opcode(hdev, 0xFD30); > hci_set_aosp_capable(hdev); > + > + /* Setup ISO interface after protocol enabled */ > + if (btmtk_test_flag(hdev, BTMTK_ISOPKT_OVER_INTR)) { > + btmtk_isointf_setup(hdev); > + set_bit(BTUSB_ISOPKT_RUNNING, &data->flags); > + } > + > goto done; > default: > bt_dev_err(hdev, "Unsupported hardware variant (%08x)", > @@ -4347,6 +4623,7 @@ static int btusb_probe(struct usb_interface *intf, > init_usb_anchor(&data->isoc_anchor); > init_usb_anchor(&data->diag_anchor); > init_usb_anchor(&data->ctrl_anchor); > + init_usb_anchor(&data->isopkt_anchor); > spin_lock_init(&data->rxlock); > > priv_size = 0; > @@ -4663,6 +4940,17 @@ static void btusb_disconnect(struct usb_interface *intf) > if (data->diag) > usb_set_intfdata(data->diag, NULL); > > + if (btmtk_test_flag(hdev, BTMTK_ISOPKT_OVER_INTR)) { Same here, possibly also elsewhere. > + struct btmediatek_data *btmtk_data = hci_get_priv(hdev); > + > + if (btmtk_data->isopkt_info.isopkt_intf) { > + usb_set_intfdata(btmtk_data->isopkt_info.isopkt_intf, NULL); > + usb_driver_release_interface(&btusb_driver, > + btmtk_data->isopkt_info.isopkt_intf); > + } > + btmtk_clear_flag(hdev, BTMTK_ISOPKT_OVER_INTR); > + } > + > hci_unregister_dev(hdev); > > if (intf == data->intf) { > @@ -4818,6 +5106,11 @@ static int btusb_resume(struct usb_interface *intf) > btusb_submit_isoc_urb(hdev, GFP_NOIO); > } > > + if (test_bit(BTUSB_ISOPKT_RUNNING, &data->flags)) { > + if (btusb_mtk_submit_intr_urb(hdev, GFP_NOIO) < 0) > + clear_bit(BTUSB_ISOPKT_RUNNING, &data->flags); > + } > + > spin_lock_irq(&data->txlock); > play_deferred(data); > clear_bit(BTUSB_SUSPENDING, &data->flags); -- Pauli Virtanen