linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: btusb: Handling MSBC encoded Audio stream
@ 2018-08-20 12:19 Sathish Narasimman
  2018-08-20 12:19 ` [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints Sathish Narasimman
  0 siblings, 1 reply; 10+ messages in thread
From: Sathish Narasimman @ 2018-08-20 12:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Sathish Narasimman

Msbc encodec audio stream over USB transport should be directed
through alternate setting 6 as per Bluetooth core spec 5.0.
The patch is made keeping some part of discussion from the below
link.

https://www.spinics.net/lists/linux-bluetooth/msg64577.html

Sathish Narasimman (1):
  Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints

 drivers/bluetooth/btusb.c   | 95 +++++++++++++++++++++++++--------------------
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/hci_event.c   |  5 +++
 3 files changed, 59 insertions(+), 42 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
  2018-08-20 12:19 [PATCH] Bluetooth: btusb: Handling MSBC encoded Audio stream Sathish Narasimman
@ 2018-08-20 12:19 ` Sathish Narasimman
  0 siblings, 0 replies; 10+ messages in thread
From: Sathish Narasimman @ 2018-08-20 12:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Sathish Narasimman

For msbc encoded audio stream over usb transport, btusb driver
to be set to alternate settings 6 as per BT core spec 5.0. This
done from  hci_sync_conn_complete_evt. The type of air mode is known
during this event. For this reason the btusb is to be notifed
about the TRANSPARENT air mode and the ALT setting 6 is selected.
The changes are made considering some discussion over the similar
patch submitted earlier from Kuba Pawlak(link below)
https://www.spinics.net/lists/linux-bluetooth/msg64577.html

Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
---
 drivers/bluetooth/btusb.c   | 95 +++++++++++++++++++++++++--------------------
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/hci_event.c   |  5 +++
 3 files changed, 59 insertions(+), 42 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index cd2e5cf..ae924b6 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1390,18 +1390,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 	return -EILSEQ;
 }
 
-static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-
-	BT_DBG("%s evt %d", hdev->name, evt);
-
-	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
-		data->sco_num = hci_conn_num(hdev, SCO_LINK);
-		schedule_work(&data->work);
-	}
-}
-
 static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -1445,6 +1433,58 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 	return 0;
 }
 
+static void bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
+	if (data->isoc_altsetting != new_alts) {
+		unsigned long flags;
+
+		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		usb_kill_anchored_urbs(&data->isoc_anchor);
+
+		/* When isochronous alternate setting needs to be
+		 * changed, because SCO connection has been added
+		 * or removed, a packet fragment may be left in the
+		 * reassembling state. This could lead to wrongly
+		 * assembled fragments.
+		 *
+		 * Clear outstanding fragment when selecting a new
+		 * alternate setting.
+		 */
+		spin_lock_irqsave(&data->rxlock, flags);
+		kfree_skb(data->sco_skb);
+		data->sco_skb = NULL;
+		spin_unlock_irqrestore(&data->rxlock, flags);
+
+		if (__set_isoc_interface(hdev, new_alts) < 0)
+			return;
+	}
+	if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+		if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
+			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		else
+			btusb_submit_isoc_urb(hdev, GFP_KERNEL);
+	}
+}
+
+static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
+	BT_DBG("%s evt %d", hdev->name, evt);
+
+	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
+		data->sco_num = hci_conn_num(hdev, SCO_LINK);
+		schedule_work(&data->work);
+	}
+
+	if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
+		/* Alt setting 6 is for msbc encoded audio channel */
+		bt_switch_alt_setting(hdev, 6);
+	}
+}
+
 static void btusb_work(struct work_struct *work)
 {
 	struct btusb_data *data = container_of(work, struct btusb_data, work);
@@ -1472,36 +1512,7 @@ static void btusb_work(struct work_struct *work)
 			new_alts = data->sco_num;
 		}
 
-		if (data->isoc_altsetting != new_alts) {
-			unsigned long flags;
-
-			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
-			usb_kill_anchored_urbs(&data->isoc_anchor);
-
-			/* When isochronous alternate setting needs to be
-			 * changed, because SCO connection has been added
-			 * or removed, a packet fragment may be left in the
-			 * reassembling state. This could lead to wrongly
-			 * assembled fragments.
-			 *
-			 * Clear outstanding fragment when selecting a new
-			 * alternate setting.
-			 */
-			spin_lock_irqsave(&data->rxlock, flags);
-			kfree_skb(data->sco_skb);
-			data->sco_skb = NULL;
-			spin_unlock_irqrestore(&data->rxlock, flags);
-
-			if (__set_isoc_interface(hdev, new_alts) < 0)
-				return;
-		}
-
-		if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
-			if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
-				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
-			else
-				btusb_submit_isoc_urb(hdev, GFP_KERNEL);
-		}
+		bt_switch_alt_setting(hdev, new_alts);
 	} else {
 		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
 		usb_kill_anchored_urbs(&data->isoc_anchor);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index cdd9f1f..3498c6b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -52,6 +52,7 @@
 #define HCI_NOTIFY_CONN_ADD		1
 #define HCI_NOTIFY_CONN_DEL		2
 #define HCI_NOTIFY_VOICE_SETTING	3
+#define HCI_NOTIFY_AIR_MODE_TRANSP	4
 
 /* HCI bus types */
 #define HCI_VIRTUAL	0
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f12555f..8ef5220 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4100,6 +4100,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
 		break;
 	}
 
+	if (ev->air_mode == SCO_AIRMODE_TRANSP) {
+		if (hdev->notify)
+			hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
+	}
+
 	hci_connect_cfm(conn, ev->status);
 	if (ev->status)
 		hci_conn_del(conn);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
  2018-08-20 13:31 [PATCH] Bluetooth: btusb: Handling MSBC encoded Audio stream Sathish Narasimman
@ 2018-08-20 13:32 ` Sathish Narasimman
  2018-08-20 16:05   ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 10+ messages in thread
From: Sathish Narasimman @ 2018-08-20 13:32 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Sathish Narasimman

For msbc encoded audio stream over usb transport, btusb driver
to be set to alternate settings 6 as per BT core spec 5.0. This
done from  hci_sync_conn_complete_evt. The type of air mode is known
during this event. For this reason the btusb is to be notifed
about the TRANSPARENT air mode and the ALT setting 6 is selected.
The changes are made considering some discussion over the similar
patch submitted earlier from Kuba Pawlak(link below)
https://www.spinics.net/lists/linux-bluetooth/msg64577.html

Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
---
 drivers/bluetooth/btusb.c   | 95 +++++++++++++++++++++++++--------------------
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/hci_event.c   |  5 +++
 3 files changed, 59 insertions(+), 42 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index cd2e5cf..ae924b6 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1390,18 +1390,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 	return -EILSEQ;
 }
 
-static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-
-	BT_DBG("%s evt %d", hdev->name, evt);
-
-	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
-		data->sco_num = hci_conn_num(hdev, SCO_LINK);
-		schedule_work(&data->work);
-	}
-}
-
 static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -1445,6 +1433,58 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 	return 0;
 }
 
+static void bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
+	if (data->isoc_altsetting != new_alts) {
+		unsigned long flags;
+
+		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		usb_kill_anchored_urbs(&data->isoc_anchor);
+
+		/* When isochronous alternate setting needs to be
+		 * changed, because SCO connection has been added
+		 * or removed, a packet fragment may be left in the
+		 * reassembling state. This could lead to wrongly
+		 * assembled fragments.
+		 *
+		 * Clear outstanding fragment when selecting a new
+		 * alternate setting.
+		 */
+		spin_lock_irqsave(&data->rxlock, flags);
+		kfree_skb(data->sco_skb);
+		data->sco_skb = NULL;
+		spin_unlock_irqrestore(&data->rxlock, flags);
+
+		if (__set_isoc_interface(hdev, new_alts) < 0)
+			return;
+	}
+	if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+		if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
+			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		else
+			btusb_submit_isoc_urb(hdev, GFP_KERNEL);
+	}
+}
+
+static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
+	BT_DBG("%s evt %d", hdev->name, evt);
+
+	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
+		data->sco_num = hci_conn_num(hdev, SCO_LINK);
+		schedule_work(&data->work);
+	}
+
+	if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
+		/* Alt setting 6 is for msbc encoded audio channel */
+		bt_switch_alt_setting(hdev, 6);
+	}
+}
+
 static void btusb_work(struct work_struct *work)
 {
 	struct btusb_data *data = container_of(work, struct btusb_data, work);
@@ -1472,36 +1512,7 @@ static void btusb_work(struct work_struct *work)
 			new_alts = data->sco_num;
 		}
 
-		if (data->isoc_altsetting != new_alts) {
-			unsigned long flags;
-
-			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
-			usb_kill_anchored_urbs(&data->isoc_anchor);
-
-			/* When isochronous alternate setting needs to be
-			 * changed, because SCO connection has been added
-			 * or removed, a packet fragment may be left in the
-			 * reassembling state. This could lead to wrongly
-			 * assembled fragments.
-			 *
-			 * Clear outstanding fragment when selecting a new
-			 * alternate setting.
-			 */
-			spin_lock_irqsave(&data->rxlock, flags);
-			kfree_skb(data->sco_skb);
-			data->sco_skb = NULL;
-			spin_unlock_irqrestore(&data->rxlock, flags);
-
-			if (__set_isoc_interface(hdev, new_alts) < 0)
-				return;
-		}
-
-		if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
-			if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
-				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
-			else
-				btusb_submit_isoc_urb(hdev, GFP_KERNEL);
-		}
+		bt_switch_alt_setting(hdev, new_alts);
 	} else {
 		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
 		usb_kill_anchored_urbs(&data->isoc_anchor);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index cdd9f1f..3498c6b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -52,6 +52,7 @@
 #define HCI_NOTIFY_CONN_ADD		1
 #define HCI_NOTIFY_CONN_DEL		2
 #define HCI_NOTIFY_VOICE_SETTING	3
+#define HCI_NOTIFY_AIR_MODE_TRANSP	4
 
 /* HCI bus types */
 #define HCI_VIRTUAL	0
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f12555f..8ef5220 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4100,6 +4100,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
 		break;
 	}
 
+	if (ev->air_mode == SCO_AIRMODE_TRANSP) {
+		if (hdev->notify)
+			hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
+	}
+
 	hci_connect_cfm(conn, ev->status);
 	if (ev->status)
 		hci_conn_del(conn);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
  2018-08-20 13:32 ` [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints Sathish Narasimman
@ 2018-08-20 16:05   ` Luiz Augusto von Dentz
       [not found]     ` <CAOVXEJ+CLxgr-eZ-98U_U=JFCCu6eiVnuv=R_VwewiOE=PXsmg@mail.gmail.com>
  0 siblings, 1 reply; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-08-20 16:05 UTC (permalink / raw)
  To: Sathish Narasimman; +Cc: linux-bluetooth@vger.kernel.org, Sathish Narasimman

Hi Sathish,

On Mon, Aug 20, 2018 at 4:32 PM, Sathish Narasimman
<nsathish41@gmail.com> wrote:
> For msbc encoded audio stream over usb transport, btusb driver
> to be set to alternate settings 6 as per BT core spec 5.0. This
> done from  hci_sync_conn_complete_evt. The type of air mode is known
> during this event. For this reason the btusb is to be notifed
> about the TRANSPARENT air mode and the ALT setting 6 is selected.
> The changes are made considering some discussion over the similar
> patch submitted earlier from Kuba Pawlak(link below)
> https://www.spinics.net/lists/linux-bluetooth/msg64577.html
>
> Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
> ---
>  drivers/bluetooth/btusb.c   | 95 +++++++++++++++++++++++++--------------------
>  include/net/bluetooth/hci.h |  1 +
>  net/bluetooth/hci_event.c   |  5 +++
>  3 files changed, 59 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index cd2e5cf..ae924b6 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -1390,18 +1390,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
>         return -EILSEQ;
>  }
>
> -static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> -{
> -       struct btusb_data *data = hci_get_drvdata(hdev);
> -
> -       BT_DBG("%s evt %d", hdev->name, evt);
> -
> -       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> -               data->sco_num = hci_conn_num(hdev, SCO_LINK);
> -               schedule_work(&data->work);
> -       }
> -}
> -
>  static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
>  {
>         struct btusb_data *data = hci_get_drvdata(hdev);
> @@ -1445,6 +1433,58 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
>         return 0;
>  }
>
> +static void bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
> +{
> +       struct btusb_data *data = hci_get_drvdata(hdev);
> +
> +       if (data->isoc_altsetting != new_alts) {
> +               unsigned long flags;
> +
> +               clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> +               usb_kill_anchored_urbs(&data->isoc_anchor);
> +
> +               /* When isochronous alternate setting needs to be
> +                * changed, because SCO connection has been added
> +                * or removed, a packet fragment may be left in the
> +                * reassembling state. This could lead to wrongly
> +                * assembled fragments.
> +                *
> +                * Clear outstanding fragment when selecting a new
> +                * alternate setting.
> +                */
> +               spin_lock_irqsave(&data->rxlock, flags);
> +               kfree_skb(data->sco_skb);
> +               data->sco_skb = NULL;
> +               spin_unlock_irqrestore(&data->rxlock, flags);
> +
> +               if (__set_isoc_interface(hdev, new_alts) < 0)
> +                       return;
> +       }
> +       if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
> +               if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> +                       clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> +               else
> +                       btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> +       }
> +}
> +
> +static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> +{
> +       struct btusb_data *data = hci_get_drvdata(hdev);
> +
> +       BT_DBG("%s evt %d", hdev->name, evt);
> +
> +       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> +               data->sco_num = hci_conn_num(hdev, SCO_LINK);
> +               schedule_work(&data->work);
> +       }
> +
> +       if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
> +               /* Alt setting 6 is for msbc encoded audio channel */
> +               bt_switch_alt_setting(hdev, 6);

Have you checked that this works on older controllers? I suppose those
don't have alt_set 6.

> +       }
> +}
> +
>  static void btusb_work(struct work_struct *work)
>  {
>         struct btusb_data *data = container_of(work, struct btusb_data, work);
> @@ -1472,36 +1512,7 @@ static void btusb_work(struct work_struct *work)
>                         new_alts = data->sco_num;
>                 }
>
> -               if (data->isoc_altsetting != new_alts) {
> -                       unsigned long flags;
> -
> -                       clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> -                       usb_kill_anchored_urbs(&data->isoc_anchor);
> -
> -                       /* When isochronous alternate setting needs to be
> -                        * changed, because SCO connection has been added
> -                        * or removed, a packet fragment may be left in the
> -                        * reassembling state. This could lead to wrongly
> -                        * assembled fragments.
> -                        *
> -                        * Clear outstanding fragment when selecting a new
> -                        * alternate setting.
> -                        */
> -                       spin_lock_irqsave(&data->rxlock, flags);
> -                       kfree_skb(data->sco_skb);
> -                       data->sco_skb = NULL;
> -                       spin_unlock_irqrestore(&data->rxlock, flags);
> -
> -                       if (__set_isoc_interface(hdev, new_alts) < 0)
> -                               return;
> -               }
> -
> -               if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
> -                       if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> -                               clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> -                       else
> -                               btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> -               }
> +               bt_switch_alt_setting(hdev, new_alts);
>         } else {
>                 clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>                 usb_kill_anchored_urbs(&data->isoc_anchor);
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index cdd9f1f..3498c6b 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -52,6 +52,7 @@
>  #define HCI_NOTIFY_CONN_ADD            1
>  #define HCI_NOTIFY_CONN_DEL            2
>  #define HCI_NOTIFY_VOICE_SETTING       3
> +#define HCI_NOTIFY_AIR_MODE_TRANSP     4
>
>  /* HCI bus types */
>  #define HCI_VIRTUAL    0
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index f12555f..8ef5220 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -4100,6 +4100,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
>                 break;
>         }
>
> +       if (ev->air_mode == SCO_AIRMODE_TRANSP) {
> +               if (hdev->notify)
> +                       hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
> +       }
> +
>         hci_connect_cfm(conn, ev->status);
>         if (ev->status)
>                 hci_conn_del(conn);
> --
> 2.7.4
>



-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
       [not found]     ` <CAOVXEJ+CLxgr-eZ-98U_U=JFCCu6eiVnuv=R_VwewiOE=PXsmg@mail.gmail.com>
@ 2018-08-21  8:12       ` Luiz Augusto von Dentz
  2018-08-21  9:49         ` Sathish Narasimman
  0 siblings, 1 reply; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2018-08-21  8:12 UTC (permalink / raw)
  To: Sathish Narasimman; +Cc: linux-bluetooth@vger.kernel.org, Sathish Narasimman

Hi Sathish,

On Tue, Aug 21, 2018 at 8:58 AM, Sathish Narasimman
<nsathish41@gmail.com> wrote:
> Hi Luiz,
>
> On Mon, Aug 20, 2018 at 9:35 PM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>>
>> Hi Sathish,
>>
>> On Mon, Aug 20, 2018 at 4:32 PM, Sathish Narasimman
>> <nsathish41@gmail.com> wrote:
>> > For msbc encoded audio stream over usb transport, btusb driver
>> > to be set to alternate settings 6 as per BT core spec 5.0. This
>> > done from  hci_sync_conn_complete_evt. The type of air mode is known
>> > during this event. For this reason the btusb is to be notifed
>> > about the TRANSPARENT air mode and the ALT setting 6 is selected.
>> > The changes are made considering some discussion over the similar
>> > patch submitted earlier from Kuba Pawlak(link below)
>> > https://www.spinics.net/lists/linux-bluetooth/msg64577.html
>> >
>> > Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
>> > ---
>> >  drivers/bluetooth/btusb.c   | 95
>> > +++++++++++++++++++++++++--------------------
>> >  include/net/bluetooth/hci.h |  1 +
>> >  net/bluetooth/hci_event.c   |  5 +++
>> >  3 files changed, 59 insertions(+), 42 deletions(-)
>> >
>> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
>> > index cd2e5cf..ae924b6 100644
>> > --- a/drivers/bluetooth/btusb.c
>> > +++ b/drivers/bluetooth/btusb.c
>> > @@ -1390,18 +1390,6 @@ static int btusb_send_frame(struct hci_dev *hdev,
>> > struct sk_buff *skb)
>> >         return -EILSEQ;
>> >  }
>> >
>> > -static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
>> > -{
>> > -       struct btusb_data *data = hci_get_drvdata(hdev);
>> > -
>> > -       BT_DBG("%s evt %d", hdev->name, evt);
>> > -
>> > -       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
>> > -               data->sco_num = hci_conn_num(hdev, SCO_LINK);
>> > -               schedule_work(&data->work);
>> > -       }
>> > -}
>> > -
>> >  static inline int __set_isoc_interface(struct hci_dev *hdev, int
>> > altsetting)
>> >  {
>> >         struct btusb_data *data = hci_get_drvdata(hdev);
>> > @@ -1445,6 +1433,58 @@ static inline int __set_isoc_interface(struct
>> > hci_dev *hdev, int altsetting)
>> >         return 0;
>> >  }
>> >
>> > +static void bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
>> > +{
>> > +       struct btusb_data *data = hci_get_drvdata(hdev);
>> > +
>> > +       if (data->isoc_altsetting != new_alts) {
>> > +               unsigned long flags;
>> > +
>> > +               clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>> > +               usb_kill_anchored_urbs(&data->isoc_anchor);
>> > +
>> > +               /* When isochronous alternate setting needs to be
>> > +                * changed, because SCO connection has been added
>> > +                * or removed, a packet fragment may be left in the
>> > +                * reassembling state. This could lead to wrongly
>> > +                * assembled fragments.
>> > +                *
>> > +                * Clear outstanding fragment when selecting a new
>> > +                * alternate setting.
>> > +                */
>> > +               spin_lock_irqsave(&data->rxlock, flags);
>> > +               kfree_skb(data->sco_skb);
>> > +               data->sco_skb = NULL;
>> > +               spin_unlock_irqrestore(&data->rxlock, flags);
>> > +
>> > +               if (__set_isoc_interface(hdev, new_alts) < 0)
>> > +                       return;
>> > +       }
>> > +       if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
>> > +               if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
>> > +                       clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>> > +               else
>> > +                       btusb_submit_isoc_urb(hdev, GFP_KERNEL);
>> > +       }
>> > +}
>> > +
>> > +static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
>> > +{
>> > +       struct btusb_data *data = hci_get_drvdata(hdev);
>> > +
>> > +       BT_DBG("%s evt %d", hdev->name, evt);
>> > +
>> > +       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
>> > +               data->sco_num = hci_conn_num(hdev, SCO_LINK);
>> > +               schedule_work(&data->work);
>> > +       }
>> > +
>> > +       if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
>> > +               /* Alt setting 6 is for msbc encoded audio channel */
>> > +               bt_switch_alt_setting(hdev, 6);
>>
>> Have you checked that this works on older controllers? I suppose those
>> don't have alt_set 6.
>
> I took the reference from the core spec 5, Vol 4, Part B, Table 2.1
> For USB transport the ALT setting 6 should be used for one msbc voice
> channel.
> Yes, for the controllers that does not support ALT setting 6. this patch
> will not work.

It _must_ keep working with controller that don't support such
setting, there is no option on that, so there should be a way to just
read what supported alt settings that are supported and fallback if 6
is not supported.

> Also, I failed to submit a small part of the patch to maintain 7.5ms HCI
> packet intervel in ALT 6 setting i will submitt the next set with that
> patch.
> Table 2.1: USB Primary firmware interface and endpoint settings
>>
>> > +       }
>> > +}
>> > +
>> >  static void btusb_work(struct work_struct *work)
>> >  {
>> >         struct btusb_data *data = container_of(work, struct btusb_data,
>> > work);
>> > @@ -1472,36 +1512,7 @@ static void btusb_work(struct work_struct *work)
>> >                         new_alts = data->sco_num;
>> >                 }
>> >
>> > -               if (data->isoc_altsetting != new_alts) {
>> > -                       unsigned long flags;
>> > -
>> > -                       clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>> > -                       usb_kill_anchored_urbs(&data->isoc_anchor);
>> > -
>> > -                       /* When isochronous alternate setting needs to
>> > be
>> > -                        * changed, because SCO connection has been
>> > added
>> > -                        * or removed, a packet fragment may be left in
>> > the
>> > -                        * reassembling state. This could lead to
>> > wrongly
>> > -                        * assembled fragments.
>> > -                        *
>> > -                        * Clear outstanding fragment when selecting a
>> > new
>> > -                        * alternate setting.
>> > -                        */
>> > -                       spin_lock_irqsave(&data->rxlock, flags);
>> > -                       kfree_skb(data->sco_skb);
>> > -                       data->sco_skb = NULL;
>> > -                       spin_unlock_irqrestore(&data->rxlock, flags);
>> > -
>> > -                       if (__set_isoc_interface(hdev, new_alts) < 0)
>> > -                               return;
>> > -               }
>> > -
>> > -               if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags))
>> > {
>> > -                       if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
>> > -                               clear_bit(BTUSB_ISOC_RUNNING,
>> > &data->flags);
>> > -                       else
>> > -                               btusb_submit_isoc_urb(hdev, GFP_KERNEL);
>> > -               }
>> > +               bt_switch_alt_setting(hdev, new_alts);
>> >         } else {
>> >                 clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>> >                 usb_kill_anchored_urbs(&data->isoc_anchor);
>> > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> > index cdd9f1f..3498c6b 100644
>> > --- a/include/net/bluetooth/hci.h
>> > +++ b/include/net/bluetooth/hci.h
>> > @@ -52,6 +52,7 @@
>> >  #define HCI_NOTIFY_CONN_ADD            1
>> >  #define HCI_NOTIFY_CONN_DEL            2
>> >  #define HCI_NOTIFY_VOICE_SETTING       3
>> > +#define HCI_NOTIFY_AIR_MODE_TRANSP     4
>> >
>> >  /* HCI bus types */
>> >  #define HCI_VIRTUAL    0
>> > diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> > index f12555f..8ef5220 100644
>> > --- a/net/bluetooth/hci_event.c
>> > +++ b/net/bluetooth/hci_event.c
>> > @@ -4100,6 +4100,11 @@ static void hci_sync_conn_complete_evt(struct
>> > hci_dev *hdev,
>> >                 break;
>> >         }
>> >
>> > +       if (ev->air_mode == SCO_AIRMODE_TRANSP) {
>> > +               if (hdev->notify)
>> > +                       hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
>> > +       }
>> > +
>> >         hci_connect_cfm(conn, ev->status);
>> >         if (ev->status)
>> >                 hci_conn_del(conn);
>> > --
>> > 2.7.4
>> >
>>
>>
>>
>> --
>> Luiz Augusto von Dentz
>
>
> Thanks,
> Sathish N



-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
  2018-08-21  8:12       ` Luiz Augusto von Dentz
@ 2018-08-21  9:49         ` Sathish Narasimman
  2018-08-21 13:58           ` Marcel Holtmann
  0 siblings, 1 reply; 10+ messages in thread
From: Sathish Narasimman @ 2018-08-21  9:49 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Sathish Narasimman

Hi Luiz,

On Tue, Aug 21, 2018 at 1:42 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Sathish,
>
> On Tue, Aug 21, 2018 at 8:58 AM, Sathish Narasimman
> <nsathish41@gmail.com> wrote:
> > Hi Luiz,
> >
> > On Mon, Aug 20, 2018 at 9:35 PM Luiz Augusto von Dentz
> > <luiz.dentz@gmail.com> wrote:
> >>
> >> Hi Sathish,
> >>
> >> On Mon, Aug 20, 2018 at 4:32 PM, Sathish Narasimman
> >> <nsathish41@gmail.com> wrote:
> >> > For msbc encoded audio stream over usb transport, btusb driver
> >> > to be set to alternate settings 6 as per BT core spec 5.0. This
> >> > done from  hci_sync_conn_complete_evt. The type of air mode is known
> >> > during this event. For this reason the btusb is to be notifed
> >> > about the TRANSPARENT air mode and the ALT setting 6 is selected.
> >> > The changes are made considering some discussion over the similar
> >> > patch submitted earlier from Kuba Pawlak(link below)
> >> > https://www.spinics.net/lists/linux-bluetooth/msg64577.html
> >> >
> >> > Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
> >> > ---
> >> >  drivers/bluetooth/btusb.c   | 95
> >> > +++++++++++++++++++++++++--------------------
> >> >  include/net/bluetooth/hci.h |  1 +
> >> >  net/bluetooth/hci_event.c   |  5 +++
> >> >  3 files changed, 59 insertions(+), 42 deletions(-)
> >> >
> >> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> >> > index cd2e5cf..ae924b6 100644
> >> > --- a/drivers/bluetooth/btusb.c
> >> > +++ b/drivers/bluetooth/btusb.c
> >> > @@ -1390,18 +1390,6 @@ static int btusb_send_frame(struct hci_dev *hdev,
> >> > struct sk_buff *skb)
> >> >         return -EILSEQ;
> >> >  }
> >> >
> >> > -static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> >> > -{
> >> > -       struct btusb_data *data = hci_get_drvdata(hdev);
> >> > -
> >> > -       BT_DBG("%s evt %d", hdev->name, evt);
> >> > -
> >> > -       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> >> > -               data->sco_num = hci_conn_num(hdev, SCO_LINK);
> >> > -               schedule_work(&data->work);
> >> > -       }
> >> > -}
> >> > -
> >> >  static inline int __set_isoc_interface(struct hci_dev *hdev, int
> >> > altsetting)
> >> >  {
> >> >         struct btusb_data *data = hci_get_drvdata(hdev);
> >> > @@ -1445,6 +1433,58 @@ static inline int __set_isoc_interface(struct
> >> > hci_dev *hdev, int altsetting)
> >> >         return 0;
> >> >  }
> >> >
> >> > +static void bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
> >> > +{
> >> > +       struct btusb_data *data = hci_get_drvdata(hdev);
> >> > +
> >> > +       if (data->isoc_altsetting != new_alts) {
> >> > +               unsigned long flags;
> >> > +
> >> > +               clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> >> > +               usb_kill_anchored_urbs(&data->isoc_anchor);
> >> > +
> >> > +               /* When isochronous alternate setting needs to be
> >> > +                * changed, because SCO connection has been added
> >> > +                * or removed, a packet fragment may be left in the
> >> > +                * reassembling state. This could lead to wrongly
> >> > +                * assembled fragments.
> >> > +                *
> >> > +                * Clear outstanding fragment when selecting a new
> >> > +                * alternate setting.
> >> > +                */
> >> > +               spin_lock_irqsave(&data->rxlock, flags);
> >> > +               kfree_skb(data->sco_skb);
> >> > +               data->sco_skb = NULL;
> >> > +               spin_unlock_irqrestore(&data->rxlock, flags);
> >> > +
> >> > +               if (__set_isoc_interface(hdev, new_alts) < 0)
> >> > +                       return;
If controller does not support ALT 6. above function will return negative.
will take care of falling back to ALT 2.
> >> > +       }
> >> > +       if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
> >> > +               if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> >> > +                       clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> >> > +               else
> >> > +                       btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> >> > +       }
> >> > +}
> >> > +
> >> > +static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> >> > +{
> >> > +       struct btusb_data *data = hci_get_drvdata(hdev);
> >> > +
> >> > +       BT_DBG("%s evt %d", hdev->name, evt);
> >> > +
> >> > +       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> >> > +               data->sco_num = hci_conn_num(hdev, SCO_LINK);
> >> > +               schedule_work(&data->work);
> >> > +       }
> >> > +
> >> > +       if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
> >> > +               /* Alt setting 6 is for msbc encoded audio channel */
> >> > +               bt_switch_alt_setting(hdev, 6);
> >>
> >> Have you checked that this works on older controllers? I suppose those
> >> don't have alt_set 6.
> >
> > I took the reference from the core spec 5, Vol 4, Part B, Table 2.1
> > For USB transport the ALT setting 6 should be used for one msbc voice
> > channel.
> > Yes, for the controllers that does not support ALT setting 6. this patch
> > will not work.
>
> It _must_ keep working with controller that don't support such
> setting, there is no option on that, so there should be a way to just
> read what supported alt settings that are supported and fallback if 6
> is not supported.
>
If we trying to set to ALT SET 6 and controller does not support. in
btusb.c __set_isoc_interface function
will through error and returns negative if fails to set. So the error
check was available already.
I need to take care of returning to ALT Setting 2 if controller fails
to set ALT 6.
This can be done. will update the patch. please take a look into patch
v2 where the 7.5ms time interval is maintained.

> > Also, I failed to submit a small part of the patch to maintain 7.5ms HCI
> > packet intervel in ALT 6 setting i will submitt the next set with that
> > patch.
> > Table 2.1: USB Primary firmware interface and endpoint settings
> >>
> >> > +       }
> >> > +}
> >> > +
> >> >  static void btusb_work(struct work_struct *work)
> >> >  {
> >> >         struct btusb_data *data = container_of(work, struct btusb_data,
> >> > work);
> >> > @@ -1472,36 +1512,7 @@ static void btusb_work(struct work_struct *work)
> >> >                         new_alts = data->sco_num;
> >> >                 }
> >> >
> >> > -               if (data->isoc_altsetting != new_alts) {
> >> > -                       unsigned long flags;
> >> > -
> >> > -                       clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> >> > -                       usb_kill_anchored_urbs(&data->isoc_anchor);
> >> > -
> >> > -                       /* When isochronous alternate setting needs to
> >> > be
> >> > -                        * changed, because SCO connection has been
> >> > added
> >> > -                        * or removed, a packet fragment may be left in
> >> > the
> >> > -                        * reassembling state. This could lead to
> >> > wrongly
> >> > -                        * assembled fragments.
> >> > -                        *
> >> > -                        * Clear outstanding fragment when selecting a
> >> > new
> >> > -                        * alternate setting.
> >> > -                        */
> >> > -                       spin_lock_irqsave(&data->rxlock, flags);
> >> > -                       kfree_skb(data->sco_skb);
> >> > -                       data->sco_skb = NULL;
> >> > -                       spin_unlock_irqrestore(&data->rxlock, flags);
> >> > -
> >> > -                       if (__set_isoc_interface(hdev, new_alts) < 0)
> >> > -                               return;
> >> > -               }
> >> > -
> >> > -               if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags))
> >> > {
> >> > -                       if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> >> > -                               clear_bit(BTUSB_ISOC_RUNNING,
> >> > &data->flags);
> >> > -                       else
> >> > -                               btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> >> > -               }
> >> > +               bt_switch_alt_setting(hdev, new_alts);
> >> >         } else {
> >> >                 clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> >> >                 usb_kill_anchored_urbs(&data->isoc_anchor);
> >> > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> >> > index cdd9f1f..3498c6b 100644
> >> > --- a/include/net/bluetooth/hci.h
> >> > +++ b/include/net/bluetooth/hci.h
> >> > @@ -52,6 +52,7 @@
> >> >  #define HCI_NOTIFY_CONN_ADD            1
> >> >  #define HCI_NOTIFY_CONN_DEL            2
> >> >  #define HCI_NOTIFY_VOICE_SETTING       3
> >> > +#define HCI_NOTIFY_AIR_MODE_TRANSP     4
> >> >
> >> >  /* HCI bus types */
> >> >  #define HCI_VIRTUAL    0
> >> > diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> >> > index f12555f..8ef5220 100644
> >> > --- a/net/bluetooth/hci_event.c
> >> > +++ b/net/bluetooth/hci_event.c
> >> > @@ -4100,6 +4100,11 @@ static void hci_sync_conn_complete_evt(struct
> >> > hci_dev *hdev,
> >> >                 break;
> >> >         }
> >> >
> >> > +       if (ev->air_mode == SCO_AIRMODE_TRANSP) {
> >> > +               if (hdev->notify)
> >> > +                       hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
> >> > +       }
> >> > +
> >> >         hci_connect_cfm(conn, ev->status);
> >> >         if (ev->status)
> >> >                 hci_conn_del(conn);
> >> > --
> >> > 2.7.4
> >> >
> >>
> >>
> >>
> >> --
> >> Luiz Augusto von Dentz
> >
> >
> > Thanks,
> > Sathish N
>
>
>
> --
> Luiz Augusto von Dentz

Thanks,
Sathish N

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
  2018-08-21  9:49         ` Sathish Narasimman
@ 2018-08-21 13:58           ` Marcel Holtmann
  0 siblings, 0 replies; 10+ messages in thread
From: Marcel Holtmann @ 2018-08-21 13:58 UTC (permalink / raw)
  To: Sathish Narasimman
  Cc: Luiz Augusto von Dentz, Bluez mailing list, Sathish Narasimman

Hi Sathish,

>>>>> For msbc encoded audio stream over usb transport, btusb driver
>>>>> to be set to alternate settings 6 as per BT core spec 5.0. This
>>>>> done from  hci_sync_conn_complete_evt. The type of air mode is known
>>>>> during this event. For this reason the btusb is to be notifed
>>>>> about the TRANSPARENT air mode and the ALT setting 6 is selected.
>>>>> The changes are made considering some discussion over the similar
>>>>> patch submitted earlier from Kuba Pawlak(link below)
>>>>> https://www.spinics.net/lists/linux-bluetooth/msg64577.html
>>>>> 
>>>>> Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
>>>>> ---
>>>>> drivers/bluetooth/btusb.c   | 95
>>>>> +++++++++++++++++++++++++--------------------
>>>>> include/net/bluetooth/hci.h |  1 +
>>>>> net/bluetooth/hci_event.c   |  5 +++
>>>>> 3 files changed, 59 insertions(+), 42 deletions(-)
>>>>> 
>>>>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
>>>>> index cd2e5cf..ae924b6 100644
>>>>> --- a/drivers/bluetooth/btusb.c
>>>>> +++ b/drivers/bluetooth/btusb.c
>>>>> @@ -1390,18 +1390,6 @@ static int btusb_send_frame(struct hci_dev *hdev,
>>>>> struct sk_buff *skb)
>>>>>        return -EILSEQ;
>>>>> }
>>>>> 
>>>>> -static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
>>>>> -{
>>>>> -       struct btusb_data *data = hci_get_drvdata(hdev);
>>>>> -
>>>>> -       BT_DBG("%s evt %d", hdev->name, evt);
>>>>> -
>>>>> -       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
>>>>> -               data->sco_num = hci_conn_num(hdev, SCO_LINK);
>>>>> -               schedule_work(&data->work);
>>>>> -       }
>>>>> -}
>>>>> -
>>>>> static inline int __set_isoc_interface(struct hci_dev *hdev, int
>>>>> altsetting)
>>>>> {
>>>>>        struct btusb_data *data = hci_get_drvdata(hdev);
>>>>> @@ -1445,6 +1433,58 @@ static inline int __set_isoc_interface(struct
>>>>> hci_dev *hdev, int altsetting)
>>>>>        return 0;
>>>>> }
>>>>> 
>>>>> +static void bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
>>>>> +{
>>>>> +       struct btusb_data *data = hci_get_drvdata(hdev);
>>>>> +
>>>>> +       if (data->isoc_altsetting != new_alts) {
>>>>> +               unsigned long flags;
>>>>> +
>>>>> +               clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>>>>> +               usb_kill_anchored_urbs(&data->isoc_anchor);
>>>>> +
>>>>> +               /* When isochronous alternate setting needs to be
>>>>> +                * changed, because SCO connection has been added
>>>>> +                * or removed, a packet fragment may be left in the
>>>>> +                * reassembling state. This could lead to wrongly
>>>>> +                * assembled fragments.
>>>>> +                *
>>>>> +                * Clear outstanding fragment when selecting a new
>>>>> +                * alternate setting.
>>>>> +                */
>>>>> +               spin_lock_irqsave(&data->rxlock, flags);
>>>>> +               kfree_skb(data->sco_skb);
>>>>> +               data->sco_skb = NULL;
>>>>> +               spin_unlock_irqrestore(&data->rxlock, flags);
>>>>> +
>>>>> +               if (__set_isoc_interface(hdev, new_alts) < 0)
>>>>> +                       return;
> If controller does not support ALT 6. above function will return negative.
> will take care of falling back to ALT 2.
>>>>> +       }
>>>>> +       if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
>>>>> +               if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
>>>>> +                       clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>>>>> +               else
>>>>> +                       btusb_submit_isoc_urb(hdev, GFP_KERNEL);
>>>>> +       }
>>>>> +}
>>>>> +
>>>>> +static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
>>>>> +{
>>>>> +       struct btusb_data *data = hci_get_drvdata(hdev);
>>>>> +
>>>>> +       BT_DBG("%s evt %d", hdev->name, evt);
>>>>> +
>>>>> +       if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
>>>>> +               data->sco_num = hci_conn_num(hdev, SCO_LINK);
>>>>> +               schedule_work(&data->work);
>>>>> +       }
>>>>> +
>>>>> +       if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
>>>>> +               /* Alt setting 6 is for msbc encoded audio channel */
>>>>> +               bt_switch_alt_setting(hdev, 6);
>>>> 
>>>> Have you checked that this works on older controllers? I suppose those
>>>> don't have alt_set 6.
>>> 
>>> I took the reference from the core spec 5, Vol 4, Part B, Table 2.1
>>> For USB transport the ALT setting 6 should be used for one msbc voice
>>> channel.
>>> Yes, for the controllers that does not support ALT setting 6. this patch
>>> will not work.
>> 
>> It _must_ keep working with controller that don't support such
>> setting, there is no option on that, so there should be a way to just
>> read what supported alt settings that are supported and fallback if 6
>> is not supported.
>> 
> If we trying to set to ALT SET 6 and controller does not support. in
> btusb.c __set_isoc_interface function
> will through error and returns negative if fails to set. So the error
> check was available already.
> I need to take care of returning to ALT Setting 2 if controller fails
> to set ALT 6.
> This can be done. will update the patch. please take a look into patch
> v2 where the 7.5ms time interval is maintained.

we are not doing try-and-error here. In probe() do a proper enumeration of the alternate settings and check if setting 6 is available.

Regards

Marcel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
@ 2019-09-26  5:35 Amit K Bag
  2019-09-26  6:24 ` Marcel Holtmann
  0 siblings, 1 reply; 10+ messages in thread
From: Amit K Bag @ 2019-09-26  5:35 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: ravishankar.srivatsa, chethan.tumkur.narayan, Amit K Bag,
	Sathish Narasimman, Raghuram Hegde, Hsin-Yu Chao

For msbc encoded audio stream over usb transport, btusb driver
to be set to alternate settings 6 as per BT core spec 5.0. This
done from  hci_sync_conn_complete_evt.  The type of air mode is known
during this event.  For this reason the btusb is to be notifed
about the TRANSPARENT air mode and the ALT setting 6 is selected.
The changes are made considering some discussion over the similar
patch submitted earlier from Kuba Pawlak(link below)
https://www.spinics.net/lists/linux-bluetooth/msg64577.html

(am from https://www.spinics.net/lists/linux-bluetooth/msg76982.html)

Signed-off-by: Chethan T N <chethan.tumkur.narayan@intel.com>
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
Signed-off-by: Raghuram Hegde <raghuram.hegde@intel.com>
Signed-off-by: Hsin-Yu Chao <hychao@chromium.org>
Signed-off-by: Amit K Bag <amit.k.bag@intel.com>
---
 drivers/bluetooth/btusb.c   | 145 ++++++++++++++++++++++++++++++--------------
 include/net/bluetooth/hci.h |   1 +
 net/bluetooth/hci_event.c   |   5 ++
 3 files changed, 106 insertions(+), 45 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index a9c35ebb30f8..368cc93cb17e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -57,6 +57,9 @@ static struct usb_driver btusb_driver;
 #define BTUSB_IFNUM_2		0x80000
 #define BTUSB_CW6622		0x100000
 #define BTUSB_MEDIATEK		0x200000
+#define BTUSB_ALT6_FLOW_CNTRL	6
+
+static int set_hci_packet_interval_flow = BTUSB_ALT6_FLOW_CNTRL;
 
 static const struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -974,6 +977,38 @@ static void btusb_isoc_complete(struct urb *urb)
 	}
 }
 
+static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
+					       int mtu)
+{
+	int i, offset = 0;
+
+	/* For msbc ALT 6 setting the host will send the packet at continuous
+	 * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
+	 * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
+	 * To maintain the rate we send 63bytes of usb packets alternatively for
+	 * 7ms and 8ms to maintain the rate as 7.5ms.
+	 */
+	if (set_hci_packet_interval_flow == 6)
+		set_hci_packet_interval_flow = 7;
+	else if (set_hci_packet_interval_flow == 7)
+		set_hci_packet_interval_flow = 6;
+
+	BT_DBG("len %d mtu %d", len, mtu);
+
+	for (i = 0; i < set_hci_packet_interval_flow; i++) {
+		urb->iso_frame_desc[i].offset = offset;
+		urb->iso_frame_desc[i].length = offset;
+	}
+
+	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
+		urb->iso_frame_desc[i].offset = offset;
+		urb->iso_frame_desc[i].length = len;
+		i++;
+	}
+
+	urb->number_of_packets = i;
+}
+
 static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
 {
 	int i, offset = 0;
@@ -1376,9 +1411,12 @@ static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
 
 	urb->transfer_flags  = URB_ISO_ASAP;
 
-	__fill_isoc_descriptor(urb, skb->len,
+	if (data->isoc_altsetting == 6)
+		__fill_isoc_descriptor_msbc(urb, skb->len,
+			       le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
+	else
+		__fill_isoc_descriptor(urb, skb->len,
 			       le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
-
 	skb->dev = (void *)hdev;
 
 	return urb;
@@ -1466,18 +1504,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 	return -EILSEQ;
 }
 
-static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-
-	BT_DBG("%s evt %d", hdev->name, evt);
-
-	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
-		data->sco_num = hci_conn_num(hdev, SCO_LINK);
-		schedule_work(&data->work);
-	}
-}
-
 static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -1521,6 +1547,65 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 	return 0;
 }
 
+static int bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+	int err;
+
+	if (data->isoc_altsetting != new_alts) {
+		unsigned long flags;
+
+		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		usb_kill_anchored_urbs(&data->isoc_anchor);
+
+		/* When isochronous alternate setting needs to be
+		 * changed, because SCO connection has been added
+		 * or removed, a packet fragment may be left in the
+		 * reassembling state. This could lead to wrongly
+		 * assembled fragments.
+		 *
+		 * Clear outstanding fragment when selecting a new
+		 * alternate setting.
+		 */
+		spin_lock_irqsave(&data->rxlock, flags);
+		kfree_skb(data->sco_skb);
+		data->sco_skb = NULL;
+		spin_unlock_irqrestore(&data->rxlock, flags);
+
+		err = __set_isoc_interface(hdev, new_alts);
+		if (err < 0)
+			return err;
+	}
+	if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+		if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
+			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		else
+			btusb_submit_isoc_urb(hdev, GFP_KERNEL);
+	}
+
+	return 0;
+}
+
+static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
+	BT_DBG("%s evt %d", hdev->name, evt);
+
+	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
+		data->sco_num = hci_conn_num(hdev, SCO_LINK);
+		schedule_work(&data->work);
+	}
+
+	if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
+		/* Alt setting 6 is used for msbc encoded
+		 * audio channel
+		 */
+		if (bt_switch_alt_setting(hdev, 6) < 0)
+			BT_ERR("%s Set USB Alt6 failed", hdev->name);
+	}
+}
+
 static void btusb_work(struct work_struct *work)
 {
 	struct btusb_data *data = container_of(work, struct btusb_data, work);
@@ -1547,37 +1632,7 @@ static void btusb_work(struct work_struct *work)
 		} else {
 			new_alts = data->sco_num;
 		}
-
-		if (data->isoc_altsetting != new_alts) {
-			unsigned long flags;
-
-			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
-			usb_kill_anchored_urbs(&data->isoc_anchor);
-
-			/* When isochronous alternate setting needs to be
-			 * changed, because SCO connection has been added
-			 * or removed, a packet fragment may be left in the
-			 * reassembling state. This could lead to wrongly
-			 * assembled fragments.
-			 *
-			 * Clear outstanding fragment when selecting a new
-			 * alternate setting.
-			 */
-			spin_lock_irqsave(&data->rxlock, flags);
-			kfree_skb(data->sco_skb);
-			data->sco_skb = NULL;
-			spin_unlock_irqrestore(&data->rxlock, flags);
-
-			if (__set_isoc_interface(hdev, new_alts) < 0)
-				return;
-		}
-
-		if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
-			if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
-				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
-			else
-				btusb_submit_isoc_urb(hdev, GFP_KERNEL);
-		}
+		bt_switch_alt_setting(hdev, new_alts);
 	} else {
 		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
 		usb_kill_anchored_urbs(&data->isoc_anchor);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 5bc1e30dedde..89ac29f1dffa 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -52,6 +52,7 @@
 #define HCI_NOTIFY_CONN_ADD		1
 #define HCI_NOTIFY_CONN_DEL		2
 #define HCI_NOTIFY_VOICE_SETTING	3
+#define HCI_NOTIFY_AIR_MODE_TRANSP	4
 
 /* HCI bus types */
 #define HCI_VIRTUAL	0
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c1d3a303d97f..1c268932422c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4231,6 +4231,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
 		break;
 	}
 
+	if (ev->air_mode == SCO_AIRMODE_TRANSP) {
+		if (hdev->notify)
+			hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
+	}
+
 	hci_connect_cfm(conn, ev->status);
 	if (ev->status)
 		hci_conn_del(conn);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
  2019-09-26  5:35 Amit K Bag
@ 2019-09-26  6:24 ` Marcel Holtmann
  2019-11-11 11:04   ` Sathish Narasimman
  0 siblings, 1 reply; 10+ messages in thread
From: Marcel Holtmann @ 2019-09-26  6:24 UTC (permalink / raw)
  To: Amit K Bag
  Cc: Bluez mailing list, ravishankar.srivatsa, chethan.tumkur.narayan,
	Sathish Narasimman, Raghuram Hegde, Hsin-Yu Chao

Hi Amit,

> For msbc encoded audio stream over usb transport, btusb driver
> to be set to alternate settings 6 as per BT core spec 5.0. This
> done from  hci_sync_conn_complete_evt.  The type of air mode is known
> during this event.  For this reason the btusb is to be notifed
> about the TRANSPARENT air mode and the ALT setting 6 is selected.
> The changes are made considering some discussion over the similar
> patch submitted earlier from Kuba Pawlak(link below)
> https://www.spinics.net/lists/linux-bluetooth/msg64577.html
> 
> (am from https://www.spinics.net/lists/linux-bluetooth/msg76982.html)
> 
> Signed-off-by: Chethan T N <chethan.tumkur.narayan@intel.com>
> Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
> Signed-off-by: Raghuram Hegde <raghuram.hegde@intel.com>
> Signed-off-by: Hsin-Yu Chao <hychao@chromium.org>
> Signed-off-by: Amit K Bag <amit.k.bag@intel.com>
> ---
> drivers/bluetooth/btusb.c   | 145 ++++++++++++++++++++++++++++++--------------
> include/net/bluetooth/hci.h |   1 +
> net/bluetooth/hci_event.c   |   5 ++
> 3 files changed, 106 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index a9c35ebb30f8..368cc93cb17e 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -57,6 +57,9 @@ static struct usb_driver btusb_driver;
> #define BTUSB_IFNUM_2		0x80000
> #define BTUSB_CW6622		0x100000
> #define BTUSB_MEDIATEK		0x200000
> +#define BTUSB_ALT6_FLOW_CNTRL	6
> +
> +static int set_hci_packet_interval_flow = BTUSB_ALT6_FLOW_CNTRL;

this can never be a global variable. We allow multiple devices be attached to the same host. You need to move this into btusb_data struct.

> 
> static const struct usb_device_id btusb_table[] = {
> 	/* Generic Bluetooth USB device */
> @@ -974,6 +977,38 @@ static void btusb_isoc_complete(struct urb *urb)
> 	}
> }
> 
> +static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
> +					       int mtu)
> +{
> +	int i, offset = 0;
> +
> +	/* For msbc ALT 6 setting the host will send the packet at continuous
> +	 * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
> +	 * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
> +	 * To maintain the rate we send 63bytes of usb packets alternatively for
> +	 * 7ms and 8ms to maintain the rate as 7.5ms.
> +	 */
> +	if (set_hci_packet_interval_flow == 6)
> +		set_hci_packet_interval_flow = 7;
> +	else if (set_hci_packet_interval_flow == 7)
> +		set_hci_packet_interval_flow = 6;

can’t this just be a bool that you just toggle.

> +
> +	BT_DBG("len %d mtu %d", len, mtu);
> +
> +	for (i = 0; i < set_hci_packet_interval_flow; i++) {
> +		urb->iso_frame_desc[i].offset = offset;
> +		urb->iso_frame_desc[i].length = offset;
> +	}
> +
> +	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
> +		urb->iso_frame_desc[i].offset = offset;
> +		urb->iso_frame_desc[i].length = len;
> +		i++;
> +	}
> +
> +	urb->number_of_packets = i;
> +}
> +
> static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
> {
> 	int i, offset = 0;
> @@ -1376,9 +1411,12 @@ static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
> 
> 	urb->transfer_flags  = URB_ISO_ASAP;
> 
> -	__fill_isoc_descriptor(urb, skb->len,
> +	if (data->isoc_altsetting == 6)
> +		__fill_isoc_descriptor_msbc(urb, skb->len,
> +			       le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
> +	else
> +		__fill_isoc_descriptor(urb, skb->len,
> 			       le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
> -
> 	skb->dev = (void *)hdev;
> 
> 	return urb;
> @@ -1466,18 +1504,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
> 	return -EILSEQ;
> }
> 
> -static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> -{
> -	struct btusb_data *data = hci_get_drvdata(hdev);
> -
> -	BT_DBG("%s evt %d", hdev->name, evt);
> -
> -	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> -		data->sco_num = hci_conn_num(hdev, SCO_LINK);
> -		schedule_work(&data->work);
> -	}
> -}
> -
> static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
> {
> 	struct btusb_data *data = hci_get_drvdata(hdev);
> @@ -1521,6 +1547,65 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
> 	return 0;
> }
> 
> +static int bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
> +{
> +	struct btusb_data *data = hci_get_drvdata(hdev);
> +	int err;
> +
> +	if (data->isoc_altsetting != new_alts) {
> +		unsigned long flags;
> +
> +		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> +		usb_kill_anchored_urbs(&data->isoc_anchor);
> +
> +		/* When isochronous alternate setting needs to be
> +		 * changed, because SCO connection has been added
> +		 * or removed, a packet fragment may be left in the
> +		 * reassembling state. This could lead to wrongly
> +		 * assembled fragments.
> +		 *
> +		 * Clear outstanding fragment when selecting a new
> +		 * alternate setting.
> +		 */
> +		spin_lock_irqsave(&data->rxlock, flags);
> +		kfree_skb(data->sco_skb);
> +		data->sco_skb = NULL;
> +		spin_unlock_irqrestore(&data->rxlock, flags);
> +
> +		err = __set_isoc_interface(hdev, new_alts);
> +		if (err < 0)
> +			return err;
> +	}
> +	if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
> +		if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> +			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> +		else
> +			btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> +	}
> +
> +	return 0;
> +}
> +
> +static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> +{
> +	struct btusb_data *data = hci_get_drvdata(hdev);
> +
> +	BT_DBG("%s evt %d", hdev->name, evt);
> +
> +	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> +		data->sco_num = hci_conn_num(hdev, SCO_LINK);
> +		schedule_work(&data->work);
> +	}

Since the internal processing of packets moved from a tasklet to a workqueue, I think the extra workqueue inside btusb can be actually removed. So I would get rid of this also for the non-mSBC case.

> +
> +	if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
> +		/* Alt setting 6 is used for msbc encoded
> +		 * audio channel
> +		 */
> +		if (bt_switch_alt_setting(hdev, 6) < 0)
> +			BT_ERR("%s Set USB Alt6 failed", hdev->name);
> +	}
> +}
> +

I think this is really a one or the other. If the controller supports alternate setting 6 (which you actually have to check first) and it is air mode transparent then switch to alternate setting 6. Otherwise do what we have done before.

> static void btusb_work(struct work_struct *work)
> {
> 	struct btusb_data *data = container_of(work, struct btusb_data, work);
> @@ -1547,37 +1632,7 @@ static void btusb_work(struct work_struct *work)
> 		} else {
> 			new_alts = data->sco_num;
> 		}
> -
> -		if (data->isoc_altsetting != new_alts) {
> -			unsigned long flags;
> -
> -			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> -			usb_kill_anchored_urbs(&data->isoc_anchor);
> -
> -			/* When isochronous alternate setting needs to be
> -			 * changed, because SCO connection has been added
> -			 * or removed, a packet fragment may be left in the
> -			 * reassembling state. This could lead to wrongly
> -			 * assembled fragments.
> -			 *
> -			 * Clear outstanding fragment when selecting a new
> -			 * alternate setting.
> -			 */
> -			spin_lock_irqsave(&data->rxlock, flags);
> -			kfree_skb(data->sco_skb);
> -			data->sco_skb = NULL;
> -			spin_unlock_irqrestore(&data->rxlock, flags);
> -
> -			if (__set_isoc_interface(hdev, new_alts) < 0)
> -				return;
> -		}
> -
> -		if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
> -			if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> -				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> -			else
> -				btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> -		}
> +		bt_switch_alt_setting(hdev, new_alts);
> 	} else {
> 		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> 		usb_kill_anchored_urbs(&data->isoc_anchor);
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 5bc1e30dedde..89ac29f1dffa 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -52,6 +52,7 @@
> #define HCI_NOTIFY_CONN_ADD		1
> #define HCI_NOTIFY_CONN_DEL		2
> #define HCI_NOTIFY_VOICE_SETTING	3
> +#define HCI_NOTIFY_AIR_MODE_TRANSP	4
> 
> /* HCI bus types */
> #define HCI_VIRTUAL	0
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index c1d3a303d97f..1c268932422c 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -4231,6 +4231,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
> 		break;
> 	}
> 
> +	if (ev->air_mode == SCO_AIRMODE_TRANSP) {
> +		if (hdev->notify)
> +			hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
> +	}
> +

So this might work, but causes the USB subsystem to change the alternate setting twice. Once for CONN_ADD and once for SCO_AIRMODE_TRANSP. I prefer we just change the alternate setting once.

Maybe it is better to change CONN_ADD and CONN_DEL to an explicit ENABLE_SCO_CVSD and ENABLE_SCO_TRANSP and DISABLE_SCO.

Regards

Marcel


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints
  2019-09-26  6:24 ` Marcel Holtmann
@ 2019-11-11 11:04   ` Sathish Narasimman
  0 siblings, 0 replies; 10+ messages in thread
From: Sathish Narasimman @ 2019-11-11 11:04 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Amit K Bag, Bluez mailing list, ravishankar.srivatsa,
	chethan.tumkur.narayan, Sathish Narasimman, Raghuram Hegde,
	Hsin-Yu Chao

Hi Marcel,

I will submit the next version of the patch and tried to fix all your comments.
Please check the same.

On Thu, Sep 26, 2019 at 3:52 PM Marcel Holtmann <marcel@holtmann.org> wrote:
>
> Hi Amit,
>
> > For msbc encoded audio stream over usb transport, btusb driver
> > to be set to alternate settings 6 as per BT core spec 5.0. This
> > done from  hci_sync_conn_complete_evt.  The type of air mode is known
> > during this event.  For this reason the btusb is to be notifed
> > about the TRANSPARENT air mode and the ALT setting 6 is selected.
> > The changes are made considering some discussion over the similar
> > patch submitted earlier from Kuba Pawlak(link below)
> > https://www.spinics.net/lists/linux-bluetooth/msg64577.html
> >
> > (am from https://www.spinics.net/lists/linux-bluetooth/msg76982.html)
> >
> > Signed-off-by: Chethan T N <chethan.tumkur.narayan@intel.com>
> > Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
> > Signed-off-by: Raghuram Hegde <raghuram.hegde@intel.com>
> > Signed-off-by: Hsin-Yu Chao <hychao@chromium.org>
> > Signed-off-by: Amit K Bag <amit.k.bag@intel.com>
> > ---
> > drivers/bluetooth/btusb.c   | 145 ++++++++++++++++++++++++++++++--------------
> > include/net/bluetooth/hci.h |   1 +
> > net/bluetooth/hci_event.c   |   5 ++
> > 3 files changed, 106 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> > index a9c35ebb30f8..368cc93cb17e 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
> > @@ -57,6 +57,9 @@ static struct usb_driver btusb_driver;
> > #define BTUSB_IFNUM_2         0x80000
> > #define BTUSB_CW6622          0x100000
> > #define BTUSB_MEDIATEK                0x200000
> > +#define BTUSB_ALT6_FLOW_CNTRL        6
> > +
> > +static int set_hci_packet_interval_flow = BTUSB_ALT6_FLOW_CNTRL;
>
> this can never be a global variable. We allow multiple devices be attached to the same host. You need to move this into btusb_data struct.
>
> >
> > static const struct usb_device_id btusb_table[] = {
> >       /* Generic Bluetooth USB device */
> > @@ -974,6 +977,38 @@ static void btusb_isoc_complete(struct urb *urb)
> >       }
> > }
> >
> > +static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
> > +                                            int mtu)
> > +{
> > +     int i, offset = 0;
> > +
> > +     /* For msbc ALT 6 setting the host will send the packet at continuous
> > +      * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
> > +      * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
> > +      * To maintain the rate we send 63bytes of usb packets alternatively for
> > +      * 7ms and 8ms to maintain the rate as 7.5ms.
> > +      */
> > +     if (set_hci_packet_interval_flow == 6)
> > +             set_hci_packet_interval_flow = 7;
> > +     else if (set_hci_packet_interval_flow == 7)
> > +             set_hci_packet_interval_flow = 6;
>
> can’t this just be a bool that you just toggle.
Done.
>
> > +
> > +     BT_DBG("len %d mtu %d", len, mtu);
> > +
> > +     for (i = 0; i < set_hci_packet_interval_flow; i++) {
> > +             urb->iso_frame_desc[i].offset = offset;
> > +             urb->iso_frame_desc[i].length = offset;
> > +     }
> > +
> > +     if (len && i < BTUSB_MAX_ISOC_FRAMES) {
> > +             urb->iso_frame_desc[i].offset = offset;
> > +             urb->iso_frame_desc[i].length = len;
> > +             i++;
> > +     }
> > +
> > +     urb->number_of_packets = i;
> > +}
> > +
> > static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
> > {
> >       int i, offset = 0;
> > @@ -1376,9 +1411,12 @@ static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
> >
> >       urb->transfer_flags  = URB_ISO_ASAP;
> >
> > -     __fill_isoc_descriptor(urb, skb->len,
> > +     if (data->isoc_altsetting == 6)
> > +             __fill_isoc_descriptor_msbc(urb, skb->len,
> > +                            le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
> > +     else
> > +             __fill_isoc_descriptor(urb, skb->len,
> >                              le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
> > -
> >       skb->dev = (void *)hdev;
> >
> >       return urb;
> > @@ -1466,18 +1504,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
> >       return -EILSEQ;
> > }
> >
> > -static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> > -{
> > -     struct btusb_data *data = hci_get_drvdata(hdev);
> > -
> > -     BT_DBG("%s evt %d", hdev->name, evt);
> > -
> > -     if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> > -             data->sco_num = hci_conn_num(hdev, SCO_LINK);
> > -             schedule_work(&data->work);
> > -     }
> > -}
> > -
> > static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
> > {
> >       struct btusb_data *data = hci_get_drvdata(hdev);
> > @@ -1521,6 +1547,65 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
> >       return 0;
> > }
> >
> > +static int bt_switch_alt_setting(struct hci_dev *hdev, int new_alts)
> > +{
> > +     struct btusb_data *data = hci_get_drvdata(hdev);
> > +     int err;
> > +
> > +     if (data->isoc_altsetting != new_alts) {
> > +             unsigned long flags;
> > +
> > +             clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> > +             usb_kill_anchored_urbs(&data->isoc_anchor);
> > +
> > +             /* When isochronous alternate setting needs to be
> > +              * changed, because SCO connection has been added
> > +              * or removed, a packet fragment may be left in the
> > +              * reassembling state. This could lead to wrongly
> > +              * assembled fragments.
> > +              *
> > +              * Clear outstanding fragment when selecting a new
> > +              * alternate setting.
> > +              */
> > +             spin_lock_irqsave(&data->rxlock, flags);
> > +             kfree_skb(data->sco_skb);
> > +             data->sco_skb = NULL;
> > +             spin_unlock_irqrestore(&data->rxlock, flags);
> > +
> > +             err = __set_isoc_interface(hdev, new_alts);
> > +             if (err < 0)
> > +                     return err;
> > +     }
> > +     if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
> > +             if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> > +                     clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> > +             else
> > +                     btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
> > +{
> > +     struct btusb_data *data = hci_get_drvdata(hdev);
> > +
> > +     BT_DBG("%s evt %d", hdev->name, evt);
> > +
> > +     if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
> > +             data->sco_num = hci_conn_num(hdev, SCO_LINK);
> > +             schedule_work(&data->work);
> > +     }
>
> Since the internal processing of packets moved from a tasklet to a workqueue, I think the extra workqueue inside btusb can be actually removed. So I would get rid of this also for the non-mSBC case.
Have left as it is. Expecting you will change this.
>
> > +
> > +     if (evt == HCI_NOTIFY_AIR_MODE_TRANSP) {
> > +             /* Alt setting 6 is used for msbc encoded
> > +              * audio channel
> > +              */
> > +             if (bt_switch_alt_setting(hdev, 6) < 0)
> > +                     BT_ERR("%s Set USB Alt6 failed", hdev->name);
> > +     }
> > +}
> > +
>
> I think this is really a one or the other. If the controller supports alternate setting 6 (which you actually have to check first) and it is air mode transparent then switch to alternate setting 6. Otherwise do what we have done before.
Done.
>
> > static void btusb_work(struct work_struct *work)
> > {
> >       struct btusb_data *data = container_of(work, struct btusb_data, work);
> > @@ -1547,37 +1632,7 @@ static void btusb_work(struct work_struct *work)
> >               } else {
> >                       new_alts = data->sco_num;
> >               }
> > -
> > -             if (data->isoc_altsetting != new_alts) {
> > -                     unsigned long flags;
> > -
> > -                     clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> > -                     usb_kill_anchored_urbs(&data->isoc_anchor);
> > -
> > -                     /* When isochronous alternate setting needs to be
> > -                      * changed, because SCO connection has been added
> > -                      * or removed, a packet fragment may be left in the
> > -                      * reassembling state. This could lead to wrongly
> > -                      * assembled fragments.
> > -                      *
> > -                      * Clear outstanding fragment when selecting a new
> > -                      * alternate setting.
> > -                      */
> > -                     spin_lock_irqsave(&data->rxlock, flags);
> > -                     kfree_skb(data->sco_skb);
> > -                     data->sco_skb = NULL;
> > -                     spin_unlock_irqrestore(&data->rxlock, flags);
> > -
> > -                     if (__set_isoc_interface(hdev, new_alts) < 0)
> > -                             return;
> > -             }
> > -
> > -             if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
> > -                     if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
> > -                             clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> > -                     else
> > -                             btusb_submit_isoc_urb(hdev, GFP_KERNEL);
> > -             }
> > +             bt_switch_alt_setting(hdev, new_alts);
> >       } else {
> >               clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
> >               usb_kill_anchored_urbs(&data->isoc_anchor);
> > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> > index 5bc1e30dedde..89ac29f1dffa 100644
> > --- a/include/net/bluetooth/hci.h
> > +++ b/include/net/bluetooth/hci.h
> > @@ -52,6 +52,7 @@
> > #define HCI_NOTIFY_CONN_ADD           1
> > #define HCI_NOTIFY_CONN_DEL           2
> > #define HCI_NOTIFY_VOICE_SETTING      3
> > +#define HCI_NOTIFY_AIR_MODE_TRANSP   4
> >
> > /* HCI bus types */
> > #define HCI_VIRTUAL   0
> > diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> > index c1d3a303d97f..1c268932422c 100644
> > --- a/net/bluetooth/hci_event.c
> > +++ b/net/bluetooth/hci_event.c
> > @@ -4231,6 +4231,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
> >               break;
> >       }
> >
> > +     if (ev->air_mode == SCO_AIRMODE_TRANSP) {
> > +             if (hdev->notify)
> > +                     hdev->notify(hdev, HCI_NOTIFY_AIR_MODE_TRANSP);
> > +     }
> > +
>
> So this might work, but causes the USB subsystem to change the alternate setting twice. Once for CONN_ADD and once for SCO_AIRMODE_TRANSP. I prefer we just change the alternate setting once.

> Maybe it is better to change CONN_ADD and CONN_DEL to an explicit ENABLE_SCO_CVSD and ENABLE_SCO_TRANSP and DISABLE_SCO.

Done.

>
> Regards
>
> Marcel
>

Regards
Sathish N

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-11-11 11:04 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-20 12:19 [PATCH] Bluetooth: btusb: Handling MSBC encoded Audio stream Sathish Narasimman
2018-08-20 12:19 ` [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints Sathish Narasimman
  -- strict thread matches above, loose matches on Subject: below --
2018-08-20 13:31 [PATCH] Bluetooth: btusb: Handling MSBC encoded Audio stream Sathish Narasimman
2018-08-20 13:32 ` [PATCH] Bluetooth: btusb: hci_event: handle msbc audio over USB Endpoints Sathish Narasimman
2018-08-20 16:05   ` Luiz Augusto von Dentz
     [not found]     ` <CAOVXEJ+CLxgr-eZ-98U_U=JFCCu6eiVnuv=R_VwewiOE=PXsmg@mail.gmail.com>
2018-08-21  8:12       ` Luiz Augusto von Dentz
2018-08-21  9:49         ` Sathish Narasimman
2018-08-21 13:58           ` Marcel Holtmann
2019-09-26  5:35 Amit K Bag
2019-09-26  6:24 ` Marcel Holtmann
2019-11-11 11:04   ` Sathish Narasimman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).