[PATCH v2 3/3] Bluetooth: btusb: mediatek: add MediaTek ISO data transmission function
Pauli Virtanen
pav at iki.fi
Wed May 29 08:39:52 PDT 2024
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 at mediatek.com>
> Signed-off-by: Sean Wang <sean.wang at mediatek.com>
> ---
> 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
More information about the Linux-mediatek
mailing list