netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
@ 2025-04-29  3:35 Yang Li via B4 Relay
  2025-04-29 14:26 ` Pauli Virtanen
  2025-05-07  6:19 ` kernel test robot
  0 siblings, 2 replies; 9+ messages in thread
From: Yang Li via B4 Relay @ 2025-04-29  3:35 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-bluetooth, netdev, linux-kernel, Yang Li

From: Yang Li <yang.li@amlogic.com>

Application layer programs (like pipewire) need to use
iso timestamp information for audio synchronization.

Signed-off-by: Yang Li <yang.li@amlogic.com>
---
 include/net/bluetooth/bluetooth.h |  4 ++-
 net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
 2 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index bbefde319f95..a102bd76647c 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -242,6 +242,7 @@ struct bt_codecs {
 #define BT_CODEC_MSBC		0x05
 
 #define BT_ISO_BASE		20
+#define BT_ISO_TS		21
 
 __printf(1, 2)
 void bt_info(const char *fmt, ...);
@@ -390,7 +391,8 @@ struct bt_sock {
 enum {
 	BT_SK_DEFER_SETUP,
 	BT_SK_SUSPEND,
-	BT_SK_PKT_STATUS
+	BT_SK_PKT_STATUS,
+	BT_SK_ISO_TS
 };
 
 struct bt_sock_list {
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index 2f348f48e99d..2c1fdea4b8c1 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
 		iso_pi(sk)->base_len = optlen;
 
 		break;
+	case BT_ISO_TS:
+		if (optlen != sizeof(opt)) {
+			err = -EINVAL;
+			break;
+		}
 
+		err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+		if (err)
+			break;
+
+		if (opt)
+			set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
+		else
+			clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
+		break;
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
 			err = -EFAULT;
 
 		break;
+	case BT_ISO_TS:
+		if (len < sizeof(u32)) {
+			err = -EINVAL;
+			break;
+		}
 
+		if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
+			    (u32 __user *)optval))
+			err = -EFAULT;
+		break;
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
 void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
 	struct iso_conn *conn = hcon->iso_data;
+	struct sock *sk;
 	__u16 pb, ts, len;
 
 	if (!conn)
 		goto drop;
 
-	pb     = hci_iso_flags_pb(flags);
-	ts     = hci_iso_flags_ts(flags);
+	iso_conn_lock(conn);
+	sk = conn->sk;
+	iso_conn_unlock(conn);
+
+	if (!sk)
+		goto drop;
+
+	pb = hci_iso_flags_pb(flags);
+	ts = hci_iso_flags_ts(flags);
 
 	BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
 
@@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 		if (ts) {
 			struct hci_iso_ts_data_hdr *hdr;
 
-			/* TODO: add timestamp to the packet? */
-			hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
-			if (!hdr) {
-				BT_ERR("Frame is too short (len %d)", skb->len);
-				goto drop;
-			}
+			if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
+				hdr = (struct hci_iso_ts_data_hdr *)skb->data;
+				len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
+			} else {
+				hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
+				if (!hdr) {
+					BT_ERR("Frame is too short (len %d)", skb->len);
+					goto drop;
+				}
 
-			len = __le16_to_cpu(hdr->slen);
+				len = __le16_to_cpu(hdr->slen);
+			}
 		} else {
 			struct hci_iso_data_hdr *hdr;
 
+			if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
+				BT_ERR("Invalid option BT_SK_ISO_TS");
+				clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
+			}
+
 			hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
 			if (!hdr) {
 				BT_ERR("Frame is too short (len %d)", skb->len);

---
base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
change-id: 20250421-iso_ts-c82a300ae784

Best regards,
-- 
Yang Li <yang.li@amlogic.com>



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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29  3:35 [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp Yang Li via B4 Relay
@ 2025-04-29 14:26 ` Pauli Virtanen
  2025-04-29 14:29   ` Pauli Virtanen
  2025-04-29 14:30   ` Luiz Augusto von Dentz
  2025-05-07  6:19 ` kernel test robot
  1 sibling, 2 replies; 9+ messages in thread
From: Pauli Virtanen @ 2025-04-29 14:26 UTC (permalink / raw)
  To: yang.li; +Cc: linux-bluetooth, netdev, Luiz Augusto von Dentz

Hi,

ti, 2025-04-29 kello 11:35 +0800, Yang Li via B4 Relay kirjoitti:
> From: Yang Li <yang.li@amlogic.com>
> 
> Application layer programs (like pipewire) need to use
> iso timestamp information for audio synchronization.

I think the timestamp should be put into CMSG, same ways as packet
status is. The packet body should then always contain only the payload.

> 
> Signed-off-by: Yang Li <yang.li@amlogic.com>
> ---
>  include/net/bluetooth/bluetooth.h |  4 ++-
>  net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
>  2 files changed, 52 insertions(+), 10 deletions(-)
> 
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index bbefde319f95..a102bd76647c 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -242,6 +242,7 @@ struct bt_codecs {
>  #define BT_CODEC_MSBC		0x05
>  
>  #define BT_ISO_BASE		20
> +#define BT_ISO_TS		21
>  
>  __printf(1, 2)
>  void bt_info(const char *fmt, ...);
> @@ -390,7 +391,8 @@ struct bt_sock {
>  enum {
>  	BT_SK_DEFER_SETUP,
>  	BT_SK_SUSPEND,
> -	BT_SK_PKT_STATUS
> +	BT_SK_PKT_STATUS,
> +	BT_SK_ISO_TS
>  };
>  
>  struct bt_sock_list {
> diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> index 2f348f48e99d..2c1fdea4b8c1 100644
> --- a/net/bluetooth/iso.c
> +++ b/net/bluetooth/iso.c
> @@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
>  		iso_pi(sk)->base_len = optlen;
>  
>  		break;
> +	case BT_ISO_TS:
> +		if (optlen != sizeof(opt)) {
> +			err = -EINVAL;
> +			break;
> +		}
>  
> +		err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
> +		if (err)
> +			break;
> +
> +		if (opt)
> +			set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> +		else
> +			clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> +		break;
>  	default:
>  		err = -ENOPROTOOPT;
>  		break;
> @@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
>  			err = -EFAULT;
>  
>  		break;
> +	case BT_ISO_TS:
> +		if (len < sizeof(u32)) {
> +			err = -EINVAL;
> +			break;
> +		}
>  
> +		if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
> +			    (u32 __user *)optval))
> +			err = -EFAULT;
> +		break;
>  	default:
>  		err = -ENOPROTOOPT;
>  		break;
> @@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
>  void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>  {
>  	struct iso_conn *conn = hcon->iso_data;
> +	struct sock *sk;
>  	__u16 pb, ts, len;
>  
>  	if (!conn)
>  		goto drop;
>  
> -	pb     = hci_iso_flags_pb(flags);
> -	ts     = hci_iso_flags_ts(flags);
> +	iso_conn_lock(conn);
> +	sk = conn->sk;
> +	iso_conn_unlock(conn);
> +
> +	if (!sk)
> +		goto drop;
> +
> +	pb = hci_iso_flags_pb(flags);
> +	ts = hci_iso_flags_ts(flags);
>  
>  	BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
>  
> @@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>  		if (ts) {
>  			struct hci_iso_ts_data_hdr *hdr;
>  
> -			/* TODO: add timestamp to the packet? */
> -			hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> -			if (!hdr) {
> -				BT_ERR("Frame is too short (len %d)", skb->len);
> -				goto drop;
> -			}
> +			if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> +				hdr = (struct hci_iso_ts_data_hdr *)skb->data;
> +				len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
> +			} else {
> +				hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> +				if (!hdr) {
> +					BT_ERR("Frame is too short (len %d)", skb->len);
> +					goto drop;
> +				}
>  
> -			len = __le16_to_cpu(hdr->slen);
> +				len = __le16_to_cpu(hdr->slen);
> +			}
>  		} else {
>  			struct hci_iso_data_hdr *hdr;
>  
> +			if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> +				BT_ERR("Invalid option BT_SK_ISO_TS");
> +				clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> +			}
> +
>  			hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
>  			if (!hdr) {
>  				BT_ERR("Frame is too short (len %d)", skb->len);
> 
> ---
> base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
> change-id: 20250421-iso_ts-c82a300ae784
> 
> Best regards,

-- 
Pauli Virtanen

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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29 14:26 ` Pauli Virtanen
@ 2025-04-29 14:29   ` Pauli Virtanen
  2025-04-29 14:31     ` Luiz Augusto von Dentz
  2025-04-29 14:30   ` Luiz Augusto von Dentz
  1 sibling, 1 reply; 9+ messages in thread
From: Pauli Virtanen @ 2025-04-29 14:29 UTC (permalink / raw)
  To: yang.li; +Cc: linux-bluetooth, netdev, Luiz Augusto von Dentz

ti, 2025-04-29 kello 17:26 +0300, Pauli Virtanen kirjoitti:
> Hi,
> 
> ti, 2025-04-29 kello 11:35 +0800, Yang Li via B4 Relay kirjoitti:
> > From: Yang Li <yang.li@amlogic.com>
> > 
> > Application layer programs (like pipewire) need to use
> > iso timestamp information for audio synchronization.
> 
> I think the timestamp should be put into CMSG, same ways as packet
> status is. The packet body should then always contain only the payload.

Or, this maybe should instead use the SOF_TIMESTAMPING_RX_HARDWARE
mechanism, which would avoid adding a new API.

> > 
> > Signed-off-by: Yang Li <yang.li@amlogic.com>
> > ---
> >  include/net/bluetooth/bluetooth.h |  4 ++-
> >  net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
> >  2 files changed, 52 insertions(+), 10 deletions(-)
> > 
> > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> > index bbefde319f95..a102bd76647c 100644
> > --- a/include/net/bluetooth/bluetooth.h
> > +++ b/include/net/bluetooth/bluetooth.h
> > @@ -242,6 +242,7 @@ struct bt_codecs {
> >  #define BT_CODEC_MSBC		0x05
> >  
> >  #define BT_ISO_BASE		20
> > +#define BT_ISO_TS		21
> >  
> >  __printf(1, 2)
> >  void bt_info(const char *fmt, ...);
> > @@ -390,7 +391,8 @@ struct bt_sock {
> >  enum {
> >  	BT_SK_DEFER_SETUP,
> >  	BT_SK_SUSPEND,
> > -	BT_SK_PKT_STATUS
> > +	BT_SK_PKT_STATUS,
> > +	BT_SK_ISO_TS
> >  };
> >  
> >  struct bt_sock_list {
> > diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> > index 2f348f48e99d..2c1fdea4b8c1 100644
> > --- a/net/bluetooth/iso.c
> > +++ b/net/bluetooth/iso.c
> > @@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
> >  		iso_pi(sk)->base_len = optlen;
> >  
> >  		break;
> > +	case BT_ISO_TS:
> > +		if (optlen != sizeof(opt)) {
> > +			err = -EINVAL;
> > +			break;
> > +		}
> >  
> > +		err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
> > +		if (err)
> > +			break;
> > +
> > +		if (opt)
> > +			set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > +		else
> > +			clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > +		break;
> >  	default:
> >  		err = -ENOPROTOOPT;
> >  		break;
> > @@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
> >  			err = -EFAULT;
> >  
> >  		break;
> > +	case BT_ISO_TS:
> > +		if (len < sizeof(u32)) {
> > +			err = -EINVAL;
> > +			break;
> > +		}
> >  
> > +		if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
> > +			    (u32 __user *)optval))
> > +			err = -EFAULT;
> > +		break;
> >  	default:
> >  		err = -ENOPROTOOPT;
> >  		break;
> > @@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
> >  void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >  {
> >  	struct iso_conn *conn = hcon->iso_data;
> > +	struct sock *sk;
> >  	__u16 pb, ts, len;
> >  
> >  	if (!conn)
> >  		goto drop;
> >  
> > -	pb     = hci_iso_flags_pb(flags);
> > -	ts     = hci_iso_flags_ts(flags);
> > +	iso_conn_lock(conn);
> > +	sk = conn->sk;
> > +	iso_conn_unlock(conn);
> > +
> > +	if (!sk)
> > +		goto drop;
> > +
> > +	pb = hci_iso_flags_pb(flags);
> > +	ts = hci_iso_flags_ts(flags);
> >  
> >  	BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
> >  
> > @@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >  		if (ts) {
> >  			struct hci_iso_ts_data_hdr *hdr;
> >  
> > -			/* TODO: add timestamp to the packet? */
> > -			hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> > -			if (!hdr) {
> > -				BT_ERR("Frame is too short (len %d)", skb->len);
> > -				goto drop;
> > -			}
> > +			if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> > +				hdr = (struct hci_iso_ts_data_hdr *)skb->data;
> > +				len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
> > +			} else {
> > +				hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> > +				if (!hdr) {
> > +					BT_ERR("Frame is too short (len %d)", skb->len);
> > +					goto drop;
> > +				}
> >  
> > -			len = __le16_to_cpu(hdr->slen);
> > +				len = __le16_to_cpu(hdr->slen);
> > +			}
> >  		} else {
> >  			struct hci_iso_data_hdr *hdr;
> >  
> > +			if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> > +				BT_ERR("Invalid option BT_SK_ISO_TS");
> > +				clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > +			}
> > +
> >  			hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
> >  			if (!hdr) {
> >  				BT_ERR("Frame is too short (len %d)", skb->len);
> > 
> > ---
> > base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
> > change-id: 20250421-iso_ts-c82a300ae784
> > 
> > Best regards,

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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29 14:26 ` Pauli Virtanen
  2025-04-29 14:29   ` Pauli Virtanen
@ 2025-04-29 14:30   ` Luiz Augusto von Dentz
  1 sibling, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2025-04-29 14:30 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: yang.li, linux-bluetooth, netdev

Hi Pauli,

On Tue, Apr 29, 2025 at 10:26 AM Pauli Virtanen <pav@iki.fi> wrote:
>
> Hi,
>
> ti, 2025-04-29 kello 11:35 +0800, Yang Li via B4 Relay kirjoitti:
> > From: Yang Li <yang.li@amlogic.com>
> >
> > Application layer programs (like pipewire) need to use
> > iso timestamp information for audio synchronization.
>
> I think the timestamp should be put into CMSG, same ways as packet
> status is. The packet body should then always contain only the payload.

Yes, we shall not have headers being sent to the application as part
of the payload.

> >
> > Signed-off-by: Yang Li <yang.li@amlogic.com>
> > ---
> >  include/net/bluetooth/bluetooth.h |  4 ++-
> >  net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
> >  2 files changed, 52 insertions(+), 10 deletions(-)
> >
> > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> > index bbefde319f95..a102bd76647c 100644
> > --- a/include/net/bluetooth/bluetooth.h
> > +++ b/include/net/bluetooth/bluetooth.h
> > @@ -242,6 +242,7 @@ struct bt_codecs {
> >  #define BT_CODEC_MSBC                0x05
> >
> >  #define BT_ISO_BASE          20
> > +#define BT_ISO_TS            21
> >
> >  __printf(1, 2)
> >  void bt_info(const char *fmt, ...);
> > @@ -390,7 +391,8 @@ struct bt_sock {
> >  enum {
> >       BT_SK_DEFER_SETUP,
> >       BT_SK_SUSPEND,
> > -     BT_SK_PKT_STATUS
> > +     BT_SK_PKT_STATUS,
> > +     BT_SK_ISO_TS
> >  };
> >
> >  struct bt_sock_list {
> > diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> > index 2f348f48e99d..2c1fdea4b8c1 100644
> > --- a/net/bluetooth/iso.c
> > +++ b/net/bluetooth/iso.c
> > @@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
> >               iso_pi(sk)->base_len = optlen;
> >
> >               break;
> > +     case BT_ISO_TS:
> > +             if (optlen != sizeof(opt)) {
> > +                     err = -EINVAL;
> > +                     break;
> > +             }
> >
> > +             err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
> > +             if (err)
> > +                     break;
> > +
> > +             if (opt)
> > +                     set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > +             else
> > +                     clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > +             break;
> >       default:
> >               err = -ENOPROTOOPT;
> >               break;
> > @@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
> >                       err = -EFAULT;
> >
> >               break;
> > +     case BT_ISO_TS:
> > +             if (len < sizeof(u32)) {
> > +                     err = -EINVAL;
> > +                     break;
> > +             }
> >
> > +             if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
> > +                         (u32 __user *)optval))
> > +                     err = -EFAULT;
> > +             break;
> >       default:
> >               err = -ENOPROTOOPT;
> >               break;
> > @@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
> >  void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >  {
> >       struct iso_conn *conn = hcon->iso_data;
> > +     struct sock *sk;
> >       __u16 pb, ts, len;
> >
> >       if (!conn)
> >               goto drop;
> >
> > -     pb     = hci_iso_flags_pb(flags);
> > -     ts     = hci_iso_flags_ts(flags);
> > +     iso_conn_lock(conn);
> > +     sk = conn->sk;
> > +     iso_conn_unlock(conn);
> > +
> > +     if (!sk)
> > +             goto drop;
> > +
> > +     pb = hci_iso_flags_pb(flags);
> > +     ts = hci_iso_flags_ts(flags);
> >
> >       BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
> >
> > @@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >               if (ts) {
> >                       struct hci_iso_ts_data_hdr *hdr;
> >
> > -                     /* TODO: add timestamp to the packet? */
> > -                     hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> > -                     if (!hdr) {
> > -                             BT_ERR("Frame is too short (len %d)", skb->len);
> > -                             goto drop;
> > -                     }
> > +                     if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> > +                             hdr = (struct hci_iso_ts_data_hdr *)skb->data;
> > +                             len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
> > +                     } else {
> > +                             hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> > +                             if (!hdr) {
> > +                                     BT_ERR("Frame is too short (len %d)", skb->len);
> > +                                     goto drop;
> > +                             }
> >
> > -                     len = __le16_to_cpu(hdr->slen);
> > +                             len = __le16_to_cpu(hdr->slen);
> > +                     }
> >               } else {
> >                       struct hci_iso_data_hdr *hdr;
> >
> > +                     if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> > +                             BT_ERR("Invalid option BT_SK_ISO_TS");
> > +                             clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > +                     }
> > +
> >                       hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
> >                       if (!hdr) {
> >                               BT_ERR("Frame is too short (len %d)", skb->len);
> >
> > ---
> > base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
> > change-id: 20250421-iso_ts-c82a300ae784
> >
> > Best regards,
>
> --
> Pauli Virtanen



-- 
Luiz Augusto von Dentz

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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29 14:29   ` Pauli Virtanen
@ 2025-04-29 14:31     ` Luiz Augusto von Dentz
  2025-04-29 14:35       ` Pauli Virtanen
  0 siblings, 1 reply; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2025-04-29 14:31 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: yang.li, linux-bluetooth, netdev

Hi Pauli,

On Tue, Apr 29, 2025 at 10:29 AM Pauli Virtanen <pav@iki.fi> wrote:
>
> ti, 2025-04-29 kello 17:26 +0300, Pauli Virtanen kirjoitti:
> > Hi,
> >
> > ti, 2025-04-29 kello 11:35 +0800, Yang Li via B4 Relay kirjoitti:
> > > From: Yang Li <yang.li@amlogic.com>
> > >
> > > Application layer programs (like pipewire) need to use
> > > iso timestamp information for audio synchronization.
> >
> > I think the timestamp should be put into CMSG, same ways as packet
> > status is. The packet body should then always contain only the payload.
>
> Or, this maybe should instead use the SOF_TIMESTAMPING_RX_HARDWARE
> mechanism, which would avoid adding a new API.

Either that or we use BT_PKT_STATUS, does SOF_TIMESTAMPING_RX_HARDWARE
requires the use of errqueue?

> > >
> > > Signed-off-by: Yang Li <yang.li@amlogic.com>
> > > ---
> > >  include/net/bluetooth/bluetooth.h |  4 ++-
> > >  net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
> > >  2 files changed, 52 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> > > index bbefde319f95..a102bd76647c 100644
> > > --- a/include/net/bluetooth/bluetooth.h
> > > +++ b/include/net/bluetooth/bluetooth.h
> > > @@ -242,6 +242,7 @@ struct bt_codecs {
> > >  #define BT_CODEC_MSBC              0x05
> > >
> > >  #define BT_ISO_BASE                20
> > > +#define BT_ISO_TS          21
> > >
> > >  __printf(1, 2)
> > >  void bt_info(const char *fmt, ...);
> > > @@ -390,7 +391,8 @@ struct bt_sock {
> > >  enum {
> > >     BT_SK_DEFER_SETUP,
> > >     BT_SK_SUSPEND,
> > > -   BT_SK_PKT_STATUS
> > > +   BT_SK_PKT_STATUS,
> > > +   BT_SK_ISO_TS
> > >  };
> > >
> > >  struct bt_sock_list {
> > > diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> > > index 2f348f48e99d..2c1fdea4b8c1 100644
> > > --- a/net/bluetooth/iso.c
> > > +++ b/net/bluetooth/iso.c
> > > @@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
> > >             iso_pi(sk)->base_len = optlen;
> > >
> > >             break;
> > > +   case BT_ISO_TS:
> > > +           if (optlen != sizeof(opt)) {
> > > +                   err = -EINVAL;
> > > +                   break;
> > > +           }
> > >
> > > +           err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
> > > +           if (err)
> > > +                   break;
> > > +
> > > +           if (opt)
> > > +                   set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > > +           else
> > > +                   clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > > +           break;
> > >     default:
> > >             err = -ENOPROTOOPT;
> > >             break;
> > > @@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
> > >                     err = -EFAULT;
> > >
> > >             break;
> > > +   case BT_ISO_TS:
> > > +           if (len < sizeof(u32)) {
> > > +                   err = -EINVAL;
> > > +                   break;
> > > +           }
> > >
> > > +           if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
> > > +                       (u32 __user *)optval))
> > > +                   err = -EFAULT;
> > > +           break;
> > >     default:
> > >             err = -ENOPROTOOPT;
> > >             break;
> > > @@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
> > >  void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> > >  {
> > >     struct iso_conn *conn = hcon->iso_data;
> > > +   struct sock *sk;
> > >     __u16 pb, ts, len;
> > >
> > >     if (!conn)
> > >             goto drop;
> > >
> > > -   pb     = hci_iso_flags_pb(flags);
> > > -   ts     = hci_iso_flags_ts(flags);
> > > +   iso_conn_lock(conn);
> > > +   sk = conn->sk;
> > > +   iso_conn_unlock(conn);
> > > +
> > > +   if (!sk)
> > > +           goto drop;
> > > +
> > > +   pb = hci_iso_flags_pb(flags);
> > > +   ts = hci_iso_flags_ts(flags);
> > >
> > >     BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
> > >
> > > @@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> > >             if (ts) {
> > >                     struct hci_iso_ts_data_hdr *hdr;
> > >
> > > -                   /* TODO: add timestamp to the packet? */
> > > -                   hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> > > -                   if (!hdr) {
> > > -                           BT_ERR("Frame is too short (len %d)", skb->len);
> > > -                           goto drop;
> > > -                   }
> > > +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> > > +                           hdr = (struct hci_iso_ts_data_hdr *)skb->data;
> > > +                           len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
> > > +                   } else {
> > > +                           hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> > > +                           if (!hdr) {
> > > +                                   BT_ERR("Frame is too short (len %d)", skb->len);
> > > +                                   goto drop;
> > > +                           }
> > >
> > > -                   len = __le16_to_cpu(hdr->slen);
> > > +                           len = __le16_to_cpu(hdr->slen);
> > > +                   }
> > >             } else {
> > >                     struct hci_iso_data_hdr *hdr;
> > >
> > > +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> > > +                           BT_ERR("Invalid option BT_SK_ISO_TS");
> > > +                           clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> > > +                   }
> > > +
> > >                     hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
> > >                     if (!hdr) {
> > >                             BT_ERR("Frame is too short (len %d)", skb->len);
> > >
> > > ---
> > > base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
> > > change-id: 20250421-iso_ts-c82a300ae784
> > >
> > > Best regards,



-- 
Luiz Augusto von Dentz

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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29 14:31     ` Luiz Augusto von Dentz
@ 2025-04-29 14:35       ` Pauli Virtanen
  2025-04-29 14:38         ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 9+ messages in thread
From: Pauli Virtanen @ 2025-04-29 14:35 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: yang.li, linux-bluetooth, netdev

Hi,

29. huhtikuuta 2025 17.31.25 GMT+03:00 Luiz Augusto von Dentz <luiz.dentz@gmail.com> kirjoitti:
>Hi Pauli,
>
>On Tue, Apr 29, 2025 at 10:29 AM Pauli Virtanen <pav@iki.fi> wrote:
>>
>> ti, 2025-04-29 kello 17:26 +0300, Pauli Virtanen kirjoitti:
>> > Hi,
>> >
>> > ti, 2025-04-29 kello 11:35 +0800, Yang Li via B4 Relay kirjoitti:
>> > > From: Yang Li <yang.li@amlogic.com>
>> > >
>> > > Application layer programs (like pipewire) need to use
>> > > iso timestamp information for audio synchronization.
>> >
>> > I think the timestamp should be put into CMSG, same ways as packet
>> > status is. The packet body should then always contain only the payload.
>>
>> Or, this maybe should instead use the SOF_TIMESTAMPING_RX_HARDWARE
>> mechanism, which would avoid adding a new API.
>
>Either that or we use BT_PKT_STATUS, does SOF_TIMESTAMPING_RX_HARDWARE
>requires the use of errqueue?

No, it just adds a CMSG, similar to the RX software tstamp.

>
>> > >
>> > > Signed-off-by: Yang Li <yang.li@amlogic.com>
>> > > ---
>> > >  include/net/bluetooth/bluetooth.h |  4 ++-
>> > >  net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
>> > >  2 files changed, 52 insertions(+), 10 deletions(-)
>> > >
>> > > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
>> > > index bbefde319f95..a102bd76647c 100644
>> > > --- a/include/net/bluetooth/bluetooth.h
>> > > +++ b/include/net/bluetooth/bluetooth.h
>> > > @@ -242,6 +242,7 @@ struct bt_codecs {
>> > >  #define BT_CODEC_MSBC              0x05
>> > >
>> > >  #define BT_ISO_BASE                20
>> > > +#define BT_ISO_TS          21
>> > >
>> > >  __printf(1, 2)
>> > >  void bt_info(const char *fmt, ...);
>> > > @@ -390,7 +391,8 @@ struct bt_sock {
>> > >  enum {
>> > >     BT_SK_DEFER_SETUP,
>> > >     BT_SK_SUSPEND,
>> > > -   BT_SK_PKT_STATUS
>> > > +   BT_SK_PKT_STATUS,
>> > > +   BT_SK_ISO_TS
>> > >  };
>> > >
>> > >  struct bt_sock_list {
>> > > diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
>> > > index 2f348f48e99d..2c1fdea4b8c1 100644
>> > > --- a/net/bluetooth/iso.c
>> > > +++ b/net/bluetooth/iso.c
>> > > @@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
>> > >             iso_pi(sk)->base_len = optlen;
>> > >
>> > >             break;
>> > > +   case BT_ISO_TS:
>> > > +           if (optlen != sizeof(opt)) {
>> > > +                   err = -EINVAL;
>> > > +                   break;
>> > > +           }
>> > >
>> > > +           err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
>> > > +           if (err)
>> > > +                   break;
>> > > +
>> > > +           if (opt)
>> > > +                   set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
>> > > +           else
>> > > +                   clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
>> > > +           break;
>> > >     default:
>> > >             err = -ENOPROTOOPT;
>> > >             break;
>> > > @@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
>> > >                     err = -EFAULT;
>> > >
>> > >             break;
>> > > +   case BT_ISO_TS:
>> > > +           if (len < sizeof(u32)) {
>> > > +                   err = -EINVAL;
>> > > +                   break;
>> > > +           }
>> > >
>> > > +           if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
>> > > +                       (u32 __user *)optval))
>> > > +                   err = -EFAULT;
>> > > +           break;
>> > >     default:
>> > >             err = -ENOPROTOOPT;
>> > >             break;
>> > > @@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
>> > >  void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>> > >  {
>> > >     struct iso_conn *conn = hcon->iso_data;
>> > > +   struct sock *sk;
>> > >     __u16 pb, ts, len;
>> > >
>> > >     if (!conn)
>> > >             goto drop;
>> > >
>> > > -   pb     = hci_iso_flags_pb(flags);
>> > > -   ts     = hci_iso_flags_ts(flags);
>> > > +   iso_conn_lock(conn);
>> > > +   sk = conn->sk;
>> > > +   iso_conn_unlock(conn);
>> > > +
>> > > +   if (!sk)
>> > > +           goto drop;
>> > > +
>> > > +   pb = hci_iso_flags_pb(flags);
>> > > +   ts = hci_iso_flags_ts(flags);
>> > >
>> > >     BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
>> > >
>> > > @@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>> > >             if (ts) {
>> > >                     struct hci_iso_ts_data_hdr *hdr;
>> > >
>> > > -                   /* TODO: add timestamp to the packet? */
>> > > -                   hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
>> > > -                   if (!hdr) {
>> > > -                           BT_ERR("Frame is too short (len %d)", skb->len);
>> > > -                           goto drop;
>> > > -                   }
>> > > +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
>> > > +                           hdr = (struct hci_iso_ts_data_hdr *)skb->data;
>> > > +                           len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
>> > > +                   } else {
>> > > +                           hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
>> > > +                           if (!hdr) {
>> > > +                                   BT_ERR("Frame is too short (len %d)", skb->len);
>> > > +                                   goto drop;
>> > > +                           }
>> > >
>> > > -                   len = __le16_to_cpu(hdr->slen);
>> > > +                           len = __le16_to_cpu(hdr->slen);
>> > > +                   }
>> > >             } else {
>> > >                     struct hci_iso_data_hdr *hdr;
>> > >
>> > > +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
>> > > +                           BT_ERR("Invalid option BT_SK_ISO_TS");
>> > > +                           clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
>> > > +                   }
>> > > +
>> > >                     hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
>> > >                     if (!hdr) {
>> > >                             BT_ERR("Frame is too short (len %d)", skb->len);
>> > >
>> > > ---
>> > > base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
>> > > change-id: 20250421-iso_ts-c82a300ae784
>> > >
>> > > Best regards,
>
>
>

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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29 14:35       ` Pauli Virtanen
@ 2025-04-29 14:38         ` Luiz Augusto von Dentz
  2025-04-30  7:45           ` Yang Li
  0 siblings, 1 reply; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2025-04-29 14:38 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: yang.li, linux-bluetooth, netdev

Hi Pauli,

On Tue, Apr 29, 2025 at 10:35 AM Pauli Virtanen <pav@iki.fi> wrote:
>
> Hi,
>
> 29. huhtikuuta 2025 17.31.25 GMT+03:00 Luiz Augusto von Dentz <luiz.dentz@gmail.com> kirjoitti:
> >Hi Pauli,
> >
> >On Tue, Apr 29, 2025 at 10:29 AM Pauli Virtanen <pav@iki.fi> wrote:
> >>
> >> ti, 2025-04-29 kello 17:26 +0300, Pauli Virtanen kirjoitti:
> >> > Hi,
> >> >
> >> > ti, 2025-04-29 kello 11:35 +0800, Yang Li via B4 Relay kirjoitti:
> >> > > From: Yang Li <yang.li@amlogic.com>
> >> > >
> >> > > Application layer programs (like pipewire) need to use
> >> > > iso timestamp information for audio synchronization.
> >> >
> >> > I think the timestamp should be put into CMSG, same ways as packet
> >> > status is. The packet body should then always contain only the payload.
> >>
> >> Or, this maybe should instead use the SOF_TIMESTAMPING_RX_HARDWARE
> >> mechanism, which would avoid adding a new API.
> >
> >Either that or we use BT_PKT_STATUS, does SOF_TIMESTAMPING_RX_HARDWARE
> >requires the use of errqueue?
>
> No, it just adds a CMSG, similar to the RX software tstamp.

Perfect, then there should be no problem going with that, we might
want to introduce some tests for it and perhaps have the emulator
adding timestamps headers so we can test this with the likes of
iso-tester.

> >
> >> > >
> >> > > Signed-off-by: Yang Li <yang.li@amlogic.com>
> >> > > ---
> >> > >  include/net/bluetooth/bluetooth.h |  4 ++-
> >> > >  net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
> >> > >  2 files changed, 52 insertions(+), 10 deletions(-)
> >> > >
> >> > > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> >> > > index bbefde319f95..a102bd76647c 100644
> >> > > --- a/include/net/bluetooth/bluetooth.h
> >> > > +++ b/include/net/bluetooth/bluetooth.h
> >> > > @@ -242,6 +242,7 @@ struct bt_codecs {
> >> > >  #define BT_CODEC_MSBC              0x05
> >> > >
> >> > >  #define BT_ISO_BASE                20
> >> > > +#define BT_ISO_TS          21
> >> > >
> >> > >  __printf(1, 2)
> >> > >  void bt_info(const char *fmt, ...);
> >> > > @@ -390,7 +391,8 @@ struct bt_sock {
> >> > >  enum {
> >> > >     BT_SK_DEFER_SETUP,
> >> > >     BT_SK_SUSPEND,
> >> > > -   BT_SK_PKT_STATUS
> >> > > +   BT_SK_PKT_STATUS,
> >> > > +   BT_SK_ISO_TS
> >> > >  };
> >> > >
> >> > >  struct bt_sock_list {
> >> > > diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> >> > > index 2f348f48e99d..2c1fdea4b8c1 100644
> >> > > --- a/net/bluetooth/iso.c
> >> > > +++ b/net/bluetooth/iso.c
> >> > > @@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
> >> > >             iso_pi(sk)->base_len = optlen;
> >> > >
> >> > >             break;
> >> > > +   case BT_ISO_TS:
> >> > > +           if (optlen != sizeof(opt)) {
> >> > > +                   err = -EINVAL;
> >> > > +                   break;
> >> > > +           }
> >> > >
> >> > > +           err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
> >> > > +           if (err)
> >> > > +                   break;
> >> > > +
> >> > > +           if (opt)
> >> > > +                   set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> >> > > +           else
> >> > > +                   clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> >> > > +           break;
> >> > >     default:
> >> > >             err = -ENOPROTOOPT;
> >> > >             break;
> >> > > @@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
> >> > >                     err = -EFAULT;
> >> > >
> >> > >             break;
> >> > > +   case BT_ISO_TS:
> >> > > +           if (len < sizeof(u32)) {
> >> > > +                   err = -EINVAL;
> >> > > +                   break;
> >> > > +           }
> >> > >
> >> > > +           if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
> >> > > +                       (u32 __user *)optval))
> >> > > +                   err = -EFAULT;
> >> > > +           break;
> >> > >     default:
> >> > >             err = -ENOPROTOOPT;
> >> > >             break;
> >> > > @@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
> >> > >  void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >> > >  {
> >> > >     struct iso_conn *conn = hcon->iso_data;
> >> > > +   struct sock *sk;
> >> > >     __u16 pb, ts, len;
> >> > >
> >> > >     if (!conn)
> >> > >             goto drop;
> >> > >
> >> > > -   pb     = hci_iso_flags_pb(flags);
> >> > > -   ts     = hci_iso_flags_ts(flags);
> >> > > +   iso_conn_lock(conn);
> >> > > +   sk = conn->sk;
> >> > > +   iso_conn_unlock(conn);
> >> > > +
> >> > > +   if (!sk)
> >> > > +           goto drop;
> >> > > +
> >> > > +   pb = hci_iso_flags_pb(flags);
> >> > > +   ts = hci_iso_flags_ts(flags);
> >> > >
> >> > >     BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
> >> > >
> >> > > @@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >> > >             if (ts) {
> >> > >                     struct hci_iso_ts_data_hdr *hdr;
> >> > >
> >> > > -                   /* TODO: add timestamp to the packet? */
> >> > > -                   hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> >> > > -                   if (!hdr) {
> >> > > -                           BT_ERR("Frame is too short (len %d)", skb->len);
> >> > > -                           goto drop;
> >> > > -                   }
> >> > > +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> >> > > +                           hdr = (struct hci_iso_ts_data_hdr *)skb->data;
> >> > > +                           len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
> >> > > +                   } else {
> >> > > +                           hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
> >> > > +                           if (!hdr) {
> >> > > +                                   BT_ERR("Frame is too short (len %d)", skb->len);
> >> > > +                                   goto drop;
> >> > > +                           }
> >> > >
> >> > > -                   len = __le16_to_cpu(hdr->slen);
> >> > > +                           len = __le16_to_cpu(hdr->slen);
> >> > > +                   }
> >> > >             } else {
> >> > >                     struct hci_iso_data_hdr *hdr;
> >> > >
> >> > > +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
> >> > > +                           BT_ERR("Invalid option BT_SK_ISO_TS");
> >> > > +                           clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
> >> > > +                   }
> >> > > +
> >> > >                     hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
> >> > >                     if (!hdr) {
> >> > >                             BT_ERR("Frame is too short (len %d)", skb->len);
> >> > >
> >> > > ---
> >> > > base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
> >> > > change-id: 20250421-iso_ts-c82a300ae784
> >> > >
> >> > > Best regards,
> >
> >
> >



-- 
Luiz Augusto von Dentz

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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29 14:38         ` Luiz Augusto von Dentz
@ 2025-04-30  7:45           ` Yang Li
  0 siblings, 0 replies; 9+ messages in thread
From: Yang Li @ 2025-04-30  7:45 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, Pauli Virtanen; +Cc: linux-bluetooth, netdev

Hi Luiz, Pauli
>
> Hi Pauli,
>
> On Tue, Apr 29, 2025 at 10:35 AM Pauli Virtanen <pav@iki.fi> wrote:
>> Hi,
>>
>> 29. huhtikuuta 2025 17.31.25 GMT+03:00 Luiz Augusto von Dentz <luiz.dentz@gmail.com> kirjoitti:
>>> Hi Pauli,
>>>
>>> On Tue, Apr 29, 2025 at 10:29 AM Pauli Virtanen <pav@iki.fi> wrote:
>>>> ti, 2025-04-29 kello 17:26 +0300, Pauli Virtanen kirjoitti:
>>>>> Hi,
>>>>>
>>>>> ti, 2025-04-29 kello 11:35 +0800, Yang Li via B4 Relay kirjoitti:
>>>>>> From: Yang Li <yang.li@amlogic.com>
>>>>>>
>>>>>> Application layer programs (like pipewire) need to use
>>>>>> iso timestamp information for audio synchronization.
>>>>> I think the timestamp should be put into CMSG, same ways as packet
>>>>> status is. The packet body should then always contain only the payload.
>>>> Or, this maybe should instead use the SOF_TIMESTAMPING_RX_HARDWARE
>>>> mechanism, which would avoid adding a new API.
>>> Either that or we use BT_PKT_STATUS, does SOF_TIMESTAMPING_RX_HARDWARE
>>> requires the use of errqueue?
>> No, it just adds a CMSG, similar to the RX software tstamp.
> Perfect, then there should be no problem going with that, we might
> want to introduce some tests for it and perhaps have the emulator
> adding timestamps headers so we can test this with the likes of
> iso-tester.
Okay, let me try.
>
>>>>>> Signed-off-by: Yang Li <yang.li@amlogic.com>
>>>>>> ---
>>>>>>   include/net/bluetooth/bluetooth.h |  4 ++-
>>>>>>   net/bluetooth/iso.c               | 58 +++++++++++++++++++++++++++++++++------
>>>>>>   2 files changed, 52 insertions(+), 10 deletions(-)
>>>>>>
>>>>>> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
>>>>>> index bbefde319f95..a102bd76647c 100644
>>>>>> --- a/include/net/bluetooth/bluetooth.h
>>>>>> +++ b/include/net/bluetooth/bluetooth.h
>>>>>> @@ -242,6 +242,7 @@ struct bt_codecs {
>>>>>>   #define BT_CODEC_MSBC              0x05
>>>>>>
>>>>>>   #define BT_ISO_BASE                20
>>>>>> +#define BT_ISO_TS          21
>>>>>>
>>>>>>   __printf(1, 2)
>>>>>>   void bt_info(const char *fmt, ...);
>>>>>> @@ -390,7 +391,8 @@ struct bt_sock {
>>>>>>   enum {
>>>>>>      BT_SK_DEFER_SETUP,
>>>>>>      BT_SK_SUSPEND,
>>>>>> -   BT_SK_PKT_STATUS
>>>>>> +   BT_SK_PKT_STATUS,
>>>>>> +   BT_SK_ISO_TS
>>>>>>   };
>>>>>>
>>>>>>   struct bt_sock_list {
>>>>>> diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
>>>>>> index 2f348f48e99d..2c1fdea4b8c1 100644
>>>>>> --- a/net/bluetooth/iso.c
>>>>>> +++ b/net/bluetooth/iso.c
>>>>>> @@ -1718,7 +1718,21 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
>>>>>>              iso_pi(sk)->base_len = optlen;
>>>>>>
>>>>>>              break;
>>>>>> +   case BT_ISO_TS:
>>>>>> +           if (optlen != sizeof(opt)) {
>>>>>> +                   err = -EINVAL;
>>>>>> +                   break;
>>>>>> +           }
>>>>>>
>>>>>> +           err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
>>>>>> +           if (err)
>>>>>> +                   break;
>>>>>> +
>>>>>> +           if (opt)
>>>>>> +                   set_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
>>>>>> +           else
>>>>>> +                   clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
>>>>>> +           break;
>>>>>>      default:
>>>>>>              err = -ENOPROTOOPT;
>>>>>>              break;
>>>>>> @@ -1789,7 +1803,16 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
>>>>>>                      err = -EFAULT;
>>>>>>
>>>>>>              break;
>>>>>> +   case BT_ISO_TS:
>>>>>> +           if (len < sizeof(u32)) {
>>>>>> +                   err = -EINVAL;
>>>>>> +                   break;
>>>>>> +           }
>>>>>>
>>>>>> +           if (put_user(test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags),
>>>>>> +                       (u32 __user *)optval))
>>>>>> +                   err = -EFAULT;
>>>>>> +           break;
>>>>>>      default:
>>>>>>              err = -ENOPROTOOPT;
>>>>>>              break;
>>>>>> @@ -2271,13 +2294,21 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
>>>>>>   void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>>>>>>   {
>>>>>>      struct iso_conn *conn = hcon->iso_data;
>>>>>> +   struct sock *sk;
>>>>>>      __u16 pb, ts, len;
>>>>>>
>>>>>>      if (!conn)
>>>>>>              goto drop;
>>>>>>
>>>>>> -   pb     = hci_iso_flags_pb(flags);
>>>>>> -   ts     = hci_iso_flags_ts(flags);
>>>>>> +   iso_conn_lock(conn);
>>>>>> +   sk = conn->sk;
>>>>>> +   iso_conn_unlock(conn);
>>>>>> +
>>>>>> +   if (!sk)
>>>>>> +           goto drop;
>>>>>> +
>>>>>> +   pb = hci_iso_flags_pb(flags);
>>>>>> +   ts = hci_iso_flags_ts(flags);
>>>>>>
>>>>>>      BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
>>>>>>
>>>>>> @@ -2294,17 +2325,26 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>>>>>>              if (ts) {
>>>>>>                      struct hci_iso_ts_data_hdr *hdr;
>>>>>>
>>>>>> -                   /* TODO: add timestamp to the packet? */
>>>>>> -                   hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
>>>>>> -                   if (!hdr) {
>>>>>> -                           BT_ERR("Frame is too short (len %d)", skb->len);
>>>>>> -                           goto drop;
>>>>>> -                   }
>>>>>> +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
>>>>>> +                           hdr = (struct hci_iso_ts_data_hdr *)skb->data;
>>>>>> +                           len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
>>>>>> +                   } else {
>>>>>> +                           hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
>>>>>> +                           if (!hdr) {
>>>>>> +                                   BT_ERR("Frame is too short (len %d)", skb->len);
>>>>>> +                                   goto drop;
>>>>>> +                           }
>>>>>>
>>>>>> -                   len = __le16_to_cpu(hdr->slen);
>>>>>> +                           len = __le16_to_cpu(hdr->slen);
>>>>>> +                   }
>>>>>>              } else {
>>>>>>                      struct hci_iso_data_hdr *hdr;
>>>>>>
>>>>>> +                   if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
>>>>>> +                           BT_ERR("Invalid option BT_SK_ISO_TS");
>>>>>> +                           clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
>>>>>> +                   }
>>>>>> +
>>>>>>                      hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
>>>>>>                      if (!hdr) {
>>>>>>                              BT_ERR("Frame is too short (len %d)", skb->len);
>>>>>>
>>>>>> ---
>>>>>> base-commit: 16b4f97defefd93cfaea017a7c3e8849322f7dde
>>>>>> change-id: 20250421-iso_ts-c82a300ae784
>>>>>>
>>>>>> Best regards,
>>>
>>>
>
>
> --
> Luiz Augusto von Dentz

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

* Re: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
  2025-04-29  3:35 [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp Yang Li via B4 Relay
  2025-04-29 14:26 ` Pauli Virtanen
@ 2025-05-07  6:19 ` kernel test robot
  1 sibling, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-05-07  6:19 UTC (permalink / raw)
  To: Yang Li via B4 Relay, Marcel Holtmann, Johan Hedberg,
	Luiz Augusto von Dentz, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman
  Cc: oe-kbuild-all, netdev, linux-bluetooth, linux-kernel, Yang Li

Hi Yang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 16b4f97defefd93cfaea017a7c3e8849322f7dde]

url:    https://github.com/intel-lab-lkp/linux/commits/Yang-Li-via-B4-Relay/iso-add-BT_ISO_TS-optional-to-enable-ISO-timestamp/20250429-113716
base:   16b4f97defefd93cfaea017a7c3e8849322f7dde
patch link:    https://lore.kernel.org/r/20250429-iso_ts-v1-1-e586f30de6cb%40amlogic.com
patch subject: [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp
config: x86_64-randconfig-123-20250502 (https://download.01.org/0day-ci/archive/20250507/202505071336.tWe4dbxi-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250507/202505071336.tWe4dbxi-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505071336.tWe4dbxi-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> net/bluetooth/iso.c:2330:42: sparse: sparse: restricted __le16 degrades to integer

vim +2330 net/bluetooth/iso.c

  2293	
  2294	void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
  2295	{
  2296		struct iso_conn *conn = hcon->iso_data;
  2297		struct sock *sk;
  2298		__u16 pb, ts, len;
  2299	
  2300		if (!conn)
  2301			goto drop;
  2302	
  2303		iso_conn_lock(conn);
  2304		sk = conn->sk;
  2305		iso_conn_unlock(conn);
  2306	
  2307		if (!sk)
  2308			goto drop;
  2309	
  2310		pb = hci_iso_flags_pb(flags);
  2311		ts = hci_iso_flags_ts(flags);
  2312	
  2313		BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
  2314	
  2315		switch (pb) {
  2316		case ISO_START:
  2317		case ISO_SINGLE:
  2318			if (conn->rx_len) {
  2319				BT_ERR("Unexpected start frame (len %d)", skb->len);
  2320				kfree_skb(conn->rx_skb);
  2321				conn->rx_skb = NULL;
  2322				conn->rx_len = 0;
  2323			}
  2324	
  2325			if (ts) {
  2326				struct hci_iso_ts_data_hdr *hdr;
  2327	
  2328				if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
  2329					hdr = (struct hci_iso_ts_data_hdr *)skb->data;
> 2330					len = hdr->slen + HCI_ISO_TS_DATA_HDR_SIZE;
  2331				} else {
  2332					hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
  2333					if (!hdr) {
  2334						BT_ERR("Frame is too short (len %d)", skb->len);
  2335						goto drop;
  2336					}
  2337	
  2338					len = __le16_to_cpu(hdr->slen);
  2339				}
  2340			} else {
  2341				struct hci_iso_data_hdr *hdr;
  2342	
  2343				if (test_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags)) {
  2344					BT_ERR("Invalid option BT_SK_ISO_TS");
  2345					clear_bit(BT_SK_ISO_TS, &bt_sk(sk)->flags);
  2346				}
  2347	
  2348				hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
  2349				if (!hdr) {
  2350					BT_ERR("Frame is too short (len %d)", skb->len);
  2351					goto drop;
  2352				}
  2353	
  2354				len = __le16_to_cpu(hdr->slen);
  2355			}
  2356	
  2357			flags  = hci_iso_data_flags(len);
  2358			len    = hci_iso_data_len(len);
  2359	
  2360			BT_DBG("Start: total len %d, frag len %d flags 0x%4.4x", len,
  2361			       skb->len, flags);
  2362	
  2363			if (len == skb->len) {
  2364				/* Complete frame received */
  2365				hci_skb_pkt_status(skb) = flags & 0x03;
  2366				iso_recv_frame(conn, skb);
  2367				return;
  2368			}
  2369	
  2370			if (pb == ISO_SINGLE) {
  2371				BT_ERR("Frame malformed (len %d, expected len %d)",
  2372				       skb->len, len);
  2373				goto drop;
  2374			}
  2375	
  2376			if (skb->len > len) {
  2377				BT_ERR("Frame is too long (len %d, expected len %d)",
  2378				       skb->len, len);
  2379				goto drop;
  2380			}
  2381	
  2382			/* Allocate skb for the complete frame (with header) */
  2383			conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
  2384			if (!conn->rx_skb)
  2385				goto drop;
  2386	
  2387			hci_skb_pkt_status(conn->rx_skb) = flags & 0x03;
  2388			skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
  2389						  skb->len);
  2390			conn->rx_len = len - skb->len;
  2391			break;
  2392	
  2393		case ISO_CONT:
  2394			BT_DBG("Cont: frag len %d (expecting %d)", skb->len,
  2395			       conn->rx_len);
  2396	
  2397			if (!conn->rx_len) {
  2398				BT_ERR("Unexpected continuation frame (len %d)",
  2399				       skb->len);
  2400				goto drop;
  2401			}
  2402	
  2403			if (skb->len > conn->rx_len) {
  2404				BT_ERR("Fragment is too long (len %d, expected %d)",
  2405				       skb->len, conn->rx_len);
  2406				kfree_skb(conn->rx_skb);
  2407				conn->rx_skb = NULL;
  2408				conn->rx_len = 0;
  2409				goto drop;
  2410			}
  2411	
  2412			skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
  2413						  skb->len);
  2414			conn->rx_len -= skb->len;
  2415			return;
  2416	
  2417		case ISO_END:
  2418			skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
  2419						  skb->len);
  2420			conn->rx_len -= skb->len;
  2421	
  2422			if (!conn->rx_len) {
  2423				struct sk_buff *rx_skb = conn->rx_skb;
  2424	
  2425				/* Complete frame received. iso_recv_frame
  2426				 * takes ownership of the skb so set the global
  2427				 * rx_skb pointer to NULL first.
  2428				 */
  2429				conn->rx_skb = NULL;
  2430				iso_recv_frame(conn, rx_skb);
  2431			}
  2432			break;
  2433		}
  2434	
  2435	drop:
  2436		kfree_skb(skb);
  2437	}
  2438	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2025-05-07  6:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-29  3:35 [PATCH] iso: add BT_ISO_TS optional to enable ISO timestamp Yang Li via B4 Relay
2025-04-29 14:26 ` Pauli Virtanen
2025-04-29 14:29   ` Pauli Virtanen
2025-04-29 14:31     ` Luiz Augusto von Dentz
2025-04-29 14:35       ` Pauli Virtanen
2025-04-29 14:38         ` Luiz Augusto von Dentz
2025-04-30  7:45           ` Yang Li
2025-04-29 14:30   ` Luiz Augusto von Dentz
2025-05-07  6:19 ` kernel test robot

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).