Re: [PATCH v2 3/3] Bluetooth: btusb: mediatek: add MediaTek ISO data transmission function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux