Commit 2be22f19 authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz Committed by Jakub Kicinski
Browse files

Bluetooth: hci_event: Fix parsing of CIS Established Event



The ISO Interval on CIS Established Event uses 1.25 ms slots:

    BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
    page 2304:

      Time = N * 1.25 ms

In addition to that this always update the QoS settings based on CIS
Established Event.

Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 5b6d345d
Loading
Loading
Loading
Loading
+34 −15
Original line number Diff line number Diff line
@@ -6786,6 +6786,7 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
{
	struct hci_evt_le_cis_established *ev = data;
	struct hci_conn *conn;
	struct bt_iso_qos *qos;
	u16 handle = __le16_to_cpu(ev->handle);

	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@@ -6807,21 +6808,39 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
		goto unlock;
	}

	if (conn->role == HCI_ROLE_SLAVE) {
		__le32 interval;

		memset(&interval, 0, sizeof(interval));

		memcpy(&interval, ev->c_latency, sizeof(ev->c_latency));
		conn->iso_qos.ucast.in.interval = le32_to_cpu(interval);
		memcpy(&interval, ev->p_latency, sizeof(ev->p_latency));
		conn->iso_qos.ucast.out.interval = le32_to_cpu(interval);
		conn->iso_qos.ucast.in.latency = le16_to_cpu(ev->interval);
		conn->iso_qos.ucast.out.latency = le16_to_cpu(ev->interval);
		conn->iso_qos.ucast.in.sdu = le16_to_cpu(ev->c_mtu);
		conn->iso_qos.ucast.out.sdu = le16_to_cpu(ev->p_mtu);
		conn->iso_qos.ucast.in.phy = ev->c_phy;
		conn->iso_qos.ucast.out.phy = ev->p_phy;
	qos = &conn->iso_qos;

	/* 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;

	switch (conn->role) {
	case HCI_ROLE_SLAVE:
		/* Convert Transport Latency (us) to Latency (msec) */
		qos->ucast.in.latency =
			DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency),
					  1000);
		qos->ucast.out.latency =
			DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency),
					  1000);
		qos->ucast.in.sdu = le16_to_cpu(ev->c_mtu);
		qos->ucast.out.sdu = le16_to_cpu(ev->p_mtu);
		qos->ucast.in.phy = ev->c_phy;
		qos->ucast.out.phy = ev->p_phy;
		break;
	case HCI_ROLE_MASTER:
		/* Convert Transport Latency (us) to Latency (msec) */
		qos->ucast.out.latency =
			DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency),
					  1000);
		qos->ucast.in.latency =
			DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency),
					  1000);
		qos->ucast.out.sdu = le16_to_cpu(ev->c_mtu);
		qos->ucast.in.sdu = le16_to_cpu(ev->p_mtu);
		qos->ucast.out.phy = ev->c_phy;
		qos->ucast.in.phy = ev->p_phy;
		break;
	}

	if (!ev->status) {