[PATCH v2 1/2] Bluetooth: hci_conn: Fix SCO/eSCO Transport_Unit_Size for HCI data path

From: Zijun Hu

Date: Tue Nov 03 2026 - 02:01:11 EST


Correct (Input|Output)_Transport_Unit_Size based on Core spec v6.3,
Vol 4, Part E, 7.1.45:

"The Host shall set the Input_Transport_Unit_Size and
Output_Transport_Unit_Size to be equal. For HCI Host transport
the Host shall set them to 0."

Fixes: b2af264ad3af ("Bluetooth: Add support for HCI_Enhanced_Setup_Synchronous_Connection command")
Signed-off-by: Zijun Hu <zijun.hu@xxxxxxxxxxxxxxxx>
---
net/bluetooth/hci_conn.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b007f623b2ec..eebd73988bf6 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -322,18 +322,20 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
cp.in_coded_data_size = __cpu_to_le16(16);
cp.out_coded_data_size = __cpu_to_le16(16);
cp.in_pcm_data_format = 2;
cp.out_pcm_data_format = 2;
cp.in_pcm_sample_payload_msb_pos = 0;
cp.out_pcm_sample_payload_msb_pos = 0;
cp.in_data_path = conn->codec.data_path;
cp.out_data_path = conn->codec.data_path;
- cp.in_transport_unit_size = 1;
- cp.out_transport_unit_size = 1;
+ if (conn->codec.data_path) {
+ cp.in_transport_unit_size = 1;
+ cp.out_transport_unit_size = 1;
+ }
break;

case BT_CODEC_TRANSPARENT:
if (!find_next_esco_param(conn, esco_param_msbc,
ARRAY_SIZE(esco_param_msbc)))
goto unlock;

param = &esco_param_msbc[conn->attempt - 1];
@@ -348,18 +350,20 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
cp.in_coded_data_size = __cpu_to_le16(16);
cp.out_coded_data_size = __cpu_to_le16(16);
cp.in_pcm_data_format = 2;
cp.out_pcm_data_format = 2;
cp.in_pcm_sample_payload_msb_pos = 0;
cp.out_pcm_sample_payload_msb_pos = 0;
cp.in_data_path = conn->codec.data_path;
cp.out_data_path = conn->codec.data_path;
- cp.in_transport_unit_size = 1;
- cp.out_transport_unit_size = 1;
+ if (conn->codec.data_path) {
+ cp.in_transport_unit_size = 1;
+ cp.out_transport_unit_size = 1;
+ }
break;

case BT_CODEC_CVSD:
if (conn->parent && lmp_esco_capable(conn->parent)) {
if (!find_next_esco_param(conn, esco_param_cvsd,
ARRAY_SIZE(esco_param_cvsd)))
goto unlock;
param = &esco_param_cvsd[conn->attempt - 1];
@@ -379,18 +383,20 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
cp.in_coded_data_size = __cpu_to_le16(16);
cp.out_coded_data_size = __cpu_to_le16(16);
cp.in_pcm_data_format = 2;
cp.out_pcm_data_format = 2;
cp.in_pcm_sample_payload_msb_pos = 0;
cp.out_pcm_sample_payload_msb_pos = 0;
cp.in_data_path = conn->codec.data_path;
cp.out_data_path = conn->codec.data_path;
- cp.in_transport_unit_size = 16;
- cp.out_transport_unit_size = 16;
+ if (conn->codec.data_path) {
+ cp.in_transport_unit_size = 16;
+ cp.out_transport_unit_size = 16;
+ }
break;
default:
goto unlock;
}

hci_dev_unlock(hdev);

cp.retrans_effort = param->retrans_effort;

--
2.34.1