Skip to content

Commit

Permalink
Bluetooth: hci_event: Fix setting of unicast qos interval
Browse files Browse the repository at this point in the history
qos->ucast interval reffers to the SDU interval, and should not
be set to the interval value reported by the LE CIS Established
event since the latter reffers to the ISO interval. These two
interval are not the same thing:

BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 6, Part G

Isochronous interval:
The time between two consecutive BIS or CIS events (designated
ISO_Interval in the Link Layer)

SDU interval:
The nominal time between two consecutive SDUs that are sent or
received by the upper layer.

So this instead uses the following formula from the spec to calculate
the resulting SDU interface:

BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 6, Part G
page 3075:

Transport_Latency_C_To_P = CIG_Sync_Delay + (FT_C_To_P) ×
ISO_Interval + SDU_Interval_C_To_P
Transport_Latency_P_To_C = CIG_Sync_Delay + (FT_P_To_C) ×
ISO_Interval + SDU_Interval_P_To_C

Link: bluez/bluez#823
Fixes: 2be22f1 ("Bluetooth: hci_event: Fix parsing of CIS Established Event")
Signed-off-by: Luiz Augusto von Dentz <[email protected]>
  • Loading branch information
Vudentz committed Jun 6, 2024
1 parent c5dd901 commit 9b70755
Showing 1 changed file with 19 additions and 3 deletions.
22 changes: 19 additions & 3 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -6667,6 +6667,7 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
struct bt_iso_qos *qos;
bool pending = false;
u16 handle = __le16_to_cpu(ev->handle);
u32 c_sdu_interval, p_sdu_interval;

bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);

Expand All @@ -6691,12 +6692,25 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,

pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, &conn->flags);

/* Convert ISO Interval (1.25 ms slots) to SDU Interval (us) */
qos->ucast.in.interval = le16_to_cpu(ev->interval) * 1250;
qos->ucast.out.interval = qos->ucast.in.interval;
/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 6, Part G
* page 3075:
* Transport_Latency_C_To_P = CIG_Sync_Delay + (FT_C_To_P) ×
* ISO_Interval + SDU_Interval_C_To_P
* ...
* SDU_Interval = (CIG_Sync_Delay + (FT) x ISO_Interval) -
* Transport_Latency
*/
c_sdu_interval = (get_unaligned_le24(ev->cig_sync_delay) +
(ev->c_ft * le16_to_cpu(ev->interval) * 1250)) -
get_unaligned_le24(ev->c_latency);
p_sdu_interval = (get_unaligned_le24(ev->cig_sync_delay) +
(ev->p_ft * le16_to_cpu(ev->interval) * 1250)) -
get_unaligned_le24(ev->p_latency);

switch (conn->role) {
case HCI_ROLE_SLAVE:
qos->ucast.in.interval = c_sdu_interval;
qos->ucast.out.interval = p_sdu_interval;
/* Convert Transport Latency (us) to Latency (msec) */
qos->ucast.in.latency =
DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency),
Expand All @@ -6710,6 +6724,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
qos->ucast.out.phy = ev->p_phy;
break;
case HCI_ROLE_MASTER:
qos->ucast.in.interval = p_sdu_interval;
qos->ucast.out.interval = c_sdu_interval;
/* Convert Transport Latency (us) to Latency (msec) */
qos->ucast.out.latency =
DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency),
Expand Down

0 comments on commit 9b70755

Please sign in to comment.