]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: ISO: Support SCM_TIMESTAMPING for ISO TS
authorYang Li <yang.li@amlogic.com>
Mon, 7 Jul 2025 02:38:17 +0000 (10:38 +0800)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 23 Jul 2025 14:31:49 +0000 (10:31 -0400)
User-space applications (e.g. PipeWire) depend on
ISO-formatted timestamps for precise audio sync.

The ISO ts is based on the controller’s clock domain,
so hardware timestamping (hwtimestamp) must be used.

Ref: Documentation/networking/timestamping.rst,
section 3.1 Hardware Timestamping.

Signed-off-by: Yang Li <yang.li@amlogic.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/iso.c

index 2f229f2077e831750eeca6923298f82ed6a51355..2f45e46a9b6aeef62ad399d3424940c06ad6c47a 100644 (file)
@@ -2289,6 +2289,7 @@ 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 skb_shared_hwtstamps *hwts;
        __u16 pb, ts, len, sn;
 
        if (!conn)
@@ -2312,13 +2313,16 @@ 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;
                        }
 
+                       /*  Record the timestamp to skb */
+                       hwts = skb_hwtstamps(skb);
+                       hwts->hwtstamp = us_to_ktime(le32_to_cpu(hdr->ts));
+
                        sn = __le16_to_cpu(hdr->sn);
                        len = __le16_to_cpu(hdr->slen);
                } else {
@@ -2370,6 +2374,13 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
                                          skb->len);
                conn->rx_len = len - skb->len;
+
+               /* Copy hw timestamp from skb to rx_skb if present */
+               if (ts) {
+                       hwts = skb_hwtstamps(conn->rx_skb);
+                       hwts->hwtstamp = skb_hwtstamps(skb)->hwtstamp;
+               }
+
                break;
 
        case ISO_CONT: