Linux bluetooth development
 help / color / mirror / Atom feed
* RE: Add support for HDT and EKS
  2026-11-03 22:19 [PATCH BlueZ v1 1/9] lib: Add HDT definitions Luiz Augusto von Dentz
@ 2026-11-04  2:34 ` bluez.test.bot
  0 siblings, 0 replies; 13+ messages in thread
From: bluez.test.bot @ 2026-11-04  2:34 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

[-- Attachment #1: Type: text/plain, Size: 15175 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1200958/

---Test result---

Test Summary:
CheckPatch                    FAIL      7.31 seconds
GitLint                       PASS      3.27 seconds
BuildEll                      PASS      16.30 seconds
BluezMake                     PASS      233.73 seconds
MakeCheck                     PASS      15.58 seconds
MakeDistcheck                 PASS      118.58 seconds
CheckValgrind                 PASS      188.91 seconds
CheckSmatch                   WARNING   230.71 seconds
bluezmakeextell               PASS      75.18 seconds
TestFunctional                PASS      987.86 seconds
IncrementalBuild              PASS      447.01 seconds
ScanBuild                     PASS      845.36 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,v1,2/9] monitor: Add HCI decoding for HDT
WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#162: FILE: monitor/bt.h:260:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#167: FILE: monitor/bt.h:265:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#172: FILE: monitor/bt.h:270:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#180: FILE: monitor/bt.h:278:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#188: FILE: monitor/bt.h:286:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#198: FILE: monitor/bt.h:296:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#206: FILE: monitor/bt.h:304:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#213: FILE: monitor/bt.h:311:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#220: FILE: monitor/bt.h:318:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#225: FILE: monitor/bt.h:323:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#253: FILE: monitor/bt.h:351:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#269: FILE: monitor/bt.h:3354:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#275: FILE: monitor/bt.h:3360:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#281: FILE: monitor/bt.h:3366:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#292: FILE: monitor/bt.h:3377:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#298: FILE: monitor/bt.h:3383:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#309: FILE: monitor/bt.h:3394:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#318: FILE: monitor/bt.h:3403:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#323: FILE: monitor/bt.h:3408:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#341: FILE: monitor/bt.h:3426:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#354: FILE: monitor/bt.h:3439:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#361: FILE: monitor/bt.h:3446:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#384: FILE: monitor/bt.h:3469:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#398: FILE: monitor/bt.h:3483:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#416: FILE: monitor/bt.h:3501:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#423: FILE: monitor/bt.h:3508:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#446: FILE: monitor/bt.h:3531:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#453: FILE: monitor/bt.h:3538:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#461: FILE: monitor/bt.h:3546:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#471: FILE: monitor/bt.h:3556:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#476: FILE: monitor/bt.h:3561:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#483: FILE: monitor/bt.h:3568:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#489: FILE: monitor/bt.h:3574:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#508: FILE: monitor/bt.h:4563:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#518: FILE: monitor/bt.h:4573:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#529: FILE: monitor/bt.h:4584:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#562: FILE: monitor/bt.h:4617:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#583: FILE: monitor/bt.h:4638:
+} __attribute__ ((packed));

WARNING:LINE_SPACING: Missing a blank line after declarations
#1192: FILE: monitor/packet.c:10541:
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)

WARNING:SPACING: Unnecessary space before function pointer arguments
#1512: FILE: monitor/packet.c:10861:
+	void (*cmd_func) (uint16_t index, const void *data, uint8_t size);

WARNING:SPACING: Unnecessary space before function pointer arguments
#1515: FILE: monitor/packet.c:10864:
+	void (*rsp_func) (uint16_t index, const void *data, uint8_t size);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1636: FILE: monitor/packet.c:10985:
+				enhanced_accept_sync_conn_request_cmd, 63, true },

/home/runner/work/bluez/bluez/src/patch/14942033.patch total: 0 errors, 42 warnings, 1890 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14942033.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v1,3/9] monitor: Add LL decoding for HDT
WARNING:LINE_SPACING: Missing a blank line after declarations
#184: FILE: monitor/ll.c:801:
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)

/home/runner/work/bluez/bluez/src/patch/14942032.patch total: 0 errors, 1 warnings, 355 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14942032.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v1,4/9] emulator: Add HDT support to btdev
WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#802: FILE: emulator/btdev.c:8419:
+	} __attribute__ ((packed)) rsp;

/home/runner/work/bluez/bluez/src/patch/14942034.patch total: 0 errors, 1 warnings, 1140 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14942034.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v1,6/9] shared/gatt: Add MIC length permission checks
WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#548: FILE: unit/test-gatt.c:4735:
+	define_test_server("/robustness/mic-len/read-multiple-variable", test_server,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#569: FILE: unit/test-gatt.c:4756:
+	define_test_server("/robustness/mic-len/read-by-group-type", test_server,

/home/runner/work/bluez/bluez/src/patch/14942036.patch total: 0 errors, 2 warnings, 356 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14942036.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v1,7/9] main.conf: Add HDT configuration
WARNING:STATIC_CONST_CHAR_ARRAY: static const char * array should probably be static const char * const
#213: FILE: src/main.c:193:
+static const char *hdt_options[] = {

/home/runner/work/bluez/bluez/src/patch/14942037.patch total: 0 errors, 1 warnings, 152 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14942037.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v1,8/9] l2cap-tester, iso-tester, mgmt-tester: Add HDT tests
WARNING:MACRO_ARG_UNUSED: Argument 'name' is not used in function-like macro
#362: FILE: tools/iso-tester.c:909:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:MACRO_ARG_UNUSED: Argument 'setup' is not used in function-like macro
#362: FILE: tools/iso-tester.c:909:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:MACRO_ARG_UNUSED: Argument 'func' is not used in function-like macro
#362: FILE: tools/iso-tester.c:909:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#2819: FILE: tools/mgmt-tester.c:14370:
+	} __attribute__((packed)) *cmd = param;

/home/runner/work/bluez/bluez/src/patch/14942039.patch total: 0 errors, 4 warnings, 2685 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14942039.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v1,9/9] l2test: Add HDT options
ERROR:INITIALISED_STATIC: do not initialise statics to 0
#204: FILE: tools/l2test.c:127:
+static int mic_len = 0;

/home/runner/work/bluez/bluez/src/patch/14942038.patch total: 1 errors, 0 warnings, 285 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14942038.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/packet.c:2290:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:4251:52: warning: array of flexible structuresmonitor/bt.h:4239:40: warning: array of flexible structuresemulator/bthost.c:707:28: warning: Variable length array is used.emulator/bthost.c:708:32: warning: Variable length array is used.emulator/bthost.c:961:28: warning: Variable length array is used.emulator/bthost.c:995:28: warning: Variable length array is used.emulator/bthost.c:996:32: warning: Variable length array is used.src/main.c: note: in included file (through src/device.h):


https://github.com/bluez/bluez/pull/2756

---
Regards,
Linux Bluetooth


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

* [PATCH BlueZ v2 0/9] Add support for HDT and EKS
@ 2026-11-04 18:36 Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 1/9] lib: Add HDT definitions Luiz Augusto von Dentz
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds support for the LE High Data Throughput (HDT) PHY and the
Encryption Key Schedule (EKS) introduced in Bluetooth Core 7.0:
definitions, btmon HCI and LL decoding, btdev/bthost emulation, GATT
MIC length permissions, main.conf options, tests in l2cap-tester,
iso-tester and mgmt-tester, and l2test options.

Changes in v2:
 - Remove the values from drafts of the specification and use the ones
   from Core 7.0:
   - ATT MIC Length Too Short is 0x14; L2CAP results are 0x000C (LE
     Credit Based) and 0x0010 (Enhanced Credit Based); the HCI error
     0xFE is removed and btmon decodes the 7.0 errors 0x49-0x4B.
   - The draft LL PDUs are replaced by the versioned LL_PHY_REQ,
     LL_PHY_RSP, LL_PHY_UPDATE_IND, LL_CIS_REQ and LL_CIS_IND [v2],
     decoded by length.
   - 0x20AA is LE Set Data Length v2; LE feature page 0 bit 59 is
     removed; Set CIG Parameters Test v2 decodes
     Anchor_Update_Buffer_Time.
 - btdev: a 64-bit MIC is only used when both sides prefer it; the
   re-encryption tests now pair with Secure Connections and check the
   128-bit MIC is kept.
 - lib: struct bt_iso_qos_ext replaces bt_iso_qos_v2, BT_PHY_* without
   BIT().
 - btmon: Create BIG Complete v2 bounds the BIS handles and shows the
   MIC length, CIG Parameters Test v2 and Create BIG Test v2 are
   variable length, Data Length Change v2 checks its own size,
   PHY_Options S=8 is bit 1, Coded rates label S=2, LL window size
   fields are masked.
 - btdev: Create BIG v2 rejects an invalid Num_BIS without completing,
   opportunistic encryption reports key size 0 and EKS mode 2, the
   peer PHY Update Complete swaps TX/RX, fixes default PHY selection,
   BIS rates come from the PHY value, unknown handles return the v2
   opcode, and CIS Established uses the version the host unmasked.
 - shared/gatt: Read By Group Type checks every service before
   encoding it.
 - main.conf: DefaultRates is sent little endian.
 - Testers wait for the re-encryption result; iso-tester converts the
   extended QoS for the emulated remote.
 - l2test: the requested PHY is separate from the queried one and the
   MIC requirement keeps the requested security level.

Luiz Augusto von Dentz (9):
  lib: Add HDT definitions
  monitor: Add HCI decoding for HDT
  monitor: Add LL decoding for HDT
  emulator: Add HDT support to btdev
  emulator: Add HDT support to bthost
  shared/gatt: Add MIC length permission checks
  main.conf: Add HDT configuration
  l2cap-tester, iso-tester, mgmt-tester: Add HDT tests
  l2test: Add HDT options

 client/scripts/gatt-mic-128.bt       |    5 +
 client/scripts/gatt-mic-64-128.bt    |    7 +
 client/scripts/gatt-mic-64.bt        |    5 +
 doc/l2cap-protocol.rst               |   42 +-
 doc/mgmt-protocol.rst                |    3 +
 doc/org.bluez.GattCharacteristic.rst |    4 +
 doc/org.bluez.GattDescriptor.rst     |    4 +
 emulator/btdev.c                     |  884 ++++++++++++--
 emulator/btdev.h                     |    1 +
 emulator/bthost.c                    |   99 ++
 emulator/bthost.h                    |   14 +
 emulator/hciemu.c                    |    3 +
 emulator/hciemu.h                    |    1 +
 emulator/main.c                      |    5 +-
 lib/bluetooth/bluetooth.h            |   65 +
 monitor/att.c                        |    3 +
 monitor/bt.h                         |  378 ++++++
 monitor/l2cap.c                      |    6 +
 monitor/ll.c                         |  215 +++-
 monitor/packet.c                     | 1321 +++++++++++++++++----
 src/adapter.c                        |   28 +
 src/btd.h                            |    7 +
 src/gatt-database.c                  |   26 +
 src/main.c                           |   33 +
 src/main.conf                        |   27 +
 src/shared/att-types.h               |   17 +-
 src/shared/att.c                     |   39 +
 src/shared/att.h                     |    3 +
 src/shared/gatt-db.c                 |    9 +
 src/shared/gatt-db.h                 |    3 +
 src/shared/gatt-server.c             |   33 +-
 tools/iso-tester.c                   | 1638 +++++++++++++++++++++++---
 tools/l2cap-tester.c                 |  761 ++++++++++++
 tools/l2test.c                       |  153 ++-
 tools/mgmt-tester.c                  |  170 +++
 unit/test-gatt.c                     |  101 ++
 36 files changed, 5603 insertions(+), 510 deletions(-)
 create mode 100644 client/scripts/gatt-mic-128.bt
 create mode 100644 client/scripts/gatt-mic-64-128.bt
 create mode 100644 client/scripts/gatt-mic-64.bt

-- 
2.56.0


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

* [PATCH BlueZ v2 1/9] lib: Add HDT definitions
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 23:07   ` Add support for HDT and EKS bluez.test.bot
  2026-11-04 18:36 ` [PATCH BlueZ v2 2/9] monitor: Add HCI decoding for HDT Luiz Augusto von Dentz
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add the socket API needed for the LE HDT PHY:

- BT_PHY bits for the HDT2, HDT3, HDT4, HDT6 and HDT7.5 rates in each
  direction, with the existing bits converted to BIT() for consistency
- bt_security.mic_len to request and read the MIC length of a link
- struct bt_iso_qos_v2, which adds the rates field to the ISO QoS
  passed with BT_ISO_QOS
---
 lib/bluetooth/bluetooth.h | 65 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/lib/bluetooth/bluetooth.h b/lib/bluetooth/bluetooth.h
index f9f22c3f7523..e9ed2f2f2a19 100644
--- a/lib/bluetooth/bluetooth.h
+++ b/lib/bluetooth/bluetooth.h
@@ -53,6 +53,7 @@ extern "C" {
 struct bt_security {
 	uint8_t level;
 	uint8_t key_size;
+	uint8_t mic_len;
 };
 #define BT_SECURITY_SDP		0
 #define BT_SECURITY_LOW		1
@@ -130,6 +131,16 @@ struct bt_voice {
 #define BT_PHY_LE_2M_RX		0x00001000
 #define BT_PHY_LE_CODED_TX	0x00002000
 #define BT_PHY_LE_CODED_RX	0x00004000
+#define BT_PHY_HDT_2M_TX	0x00008000
+#define BT_PHY_HDT_2M_RX	0x00010000
+#define BT_PHY_HDT_3M_TX	0x00020000
+#define BT_PHY_HDT_3M_RX	0x00040000
+#define BT_PHY_HDT_4M_TX	0x00080000
+#define BT_PHY_HDT_4M_RX	0x00100000
+#define BT_PHY_HDT_6M_TX	0x00200000
+#define BT_PHY_HDT_6M_RX	0x00400000
+#define BT_PHY_HDT_7_5M_TX	0x00800000
+#define BT_PHY_HDT_7_5M_RX	0x01000000
 
 #define BT_MODE			15
 
@@ -219,6 +230,60 @@ struct bt_iso_qos {
 	};
 };
 
+/* Extended ISO QoS, set and read with BT_ISO_QOS: the option length tells it
+ * apart from struct bt_iso_qos, and version tells which fields follow.
+ *
+ * Version 1 adds the rates of each direction, set when the PHY is
+ * BT_ISO_PHY_HDT.
+ */
+#define BT_ISO_QOS_VERSION_1	0x01
+
+struct bt_iso_io_qos_ext {
+	uint32_t interval;
+	uint16_t latency;
+	uint16_t sdu;
+	uint8_t  phys;
+	uint8_t  rtn;
+	uint16_t rates;
+};
+
+struct bt_iso_ucast_qos_ext {
+	uint8_t  cig;
+	uint8_t  cis;
+	uint8_t  sca;
+	uint8_t  packing;
+	uint8_t  framing;
+	struct bt_iso_io_qos_ext in;
+	struct bt_iso_io_qos_ext out;
+};
+
+struct bt_iso_bcast_qos_ext {
+	uint8_t  big;
+	uint8_t  bis;
+	uint8_t  sync_factor;
+	uint8_t  packing;
+	uint8_t  framing;
+	struct bt_iso_io_qos_ext in;
+	struct bt_iso_io_qos_ext out;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+	uint8_t  options;
+	uint16_t skip;
+	uint16_t sync_timeout;
+	uint8_t  sync_cte_type;
+	uint8_t  mse;
+	uint16_t timeout;
+};
+
+struct bt_iso_qos_ext {
+	uint8_t  version;
+	uint8_t  rfu[3];
+	union {
+		struct bt_iso_ucast_qos_ext ucast;
+		struct bt_iso_bcast_qos_ext bcast;
+	};
+};
+
 #define BT_CODEC		19
 struct bt_codec {
 	uint8_t id;
-- 
2.56.0


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

* [PATCH BlueZ v2 2/9] monitor: Add HCI decoding for HDT
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 1/9] lib: Add HDT definitions Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 3/9] monitor: Add LL " Luiz Augusto von Dentz
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Decode the HCI commands, events, feature bits and supported commands
bits introduced by High Data Throughput (HDT) and Encryption Key Schedule
(EKS) in Bluetooth 7.0, along with the MIC Length Too Short error codes
of L2CAP and ATT, the HDT MGMT setting and the HDT default parameters
and EKS Opportunistic Encryption system configuration TLVs.

Assisted-by: OpenCode:claude-opus-5
---
 monitor/att.c    |    3 +
 monitor/bt.h     |  378 +++++++++++++
 monitor/l2cap.c  |    6 +
 monitor/packet.c | 1321 ++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 1474 insertions(+), 234 deletions(-)

diff --git a/monitor/att.c b/monitor/att.c
index a35198949e3d..1d16ae21dadf 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -364,6 +364,9 @@ static void att_error_response(const struct l2cap_frame *frame)
 	case 0x13:
 		str = "Value Not Allowed";
 		break;
+	case 0x14:
+		str = "MIC Length Too Short";
+		break;
 	case 0xfd:
 		str = "CCC Improperly Configured";
 		break;
diff --git a/monitor/bt.h b/monitor/bt.h
index 2ddf37ccc22f..955ac29eb809 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -253,6 +253,68 @@ struct bt_ll_feature_ext_rsp {
 	uint8_t  features[24];
 } __attribute__ ((packed));
 
+/* Fields added at the end of LL_PHY_REQ and LL_PHY_RSP [v2] */
+struct bt_ll_phy_v2 {
+	uint8_t  flags;
+} __attribute__ ((packed));
+
+/* Fields added at the end of LL_PHY_UPDATE_IND [v2] */
+struct bt_ll_phy_update_ind_v2 {
+	uint8_t  address[5];
+	uint8_t  flags;
+} __attribute__ ((packed));
+
+/* Fields added at the end of LL_CIS_REQ [v2] */
+struct bt_ll_cis_req_v2 {
+	uint16_t c_rates;
+	uint16_t p_rates;
+	uint8_t  config_id;
+	uint8_t  tl_group_id;
+	uint8_t  flags;
+	uint8_t  se_length[3];
+} __attribute__ ((packed));
+
+/* Fields added at the end of LL_CIS_IND [v2] */
+struct bt_ll_cis_ind_v2 {
+	uint8_t  pca_h;
+} __attribute__ ((packed));
+
+#define BT_LL_ENC_ECDH_RSP	0x41
+struct bt_ll_enc_ecdh_rsp {
+	uint8_t flags;
+	uint8_t rand[16];
+	uint8_t key_type;
+	uint8_t pubkey[64];
+} __attribute__ ((packed));
+
+#define BT_LL_ENC_ECDH_REQ	0x40
+struct bt_ll_enc_ecdh_req {
+	uint8_t flags;
+	uint8_t rand[16];
+	uint8_t key_type;
+	uint8_t pubkey[64];
+} __attribute__ ((packed));
+
+#define BT_LL_HDT_CONFIG_RSP	0x43
+struct bt_ll_hdt_config_rsp {
+	uint8_t  wincfg;
+	uint16_t acl_rx_rates;
+	uint16_t acl_rx_mtu;
+} __attribute__ ((packed));
+
+#define BT_LL_HDT_CONFIG_REQ	0x42
+struct bt_ll_hdt_config_req {
+	uint8_t  wincfg;
+	uint16_t acl_rx_rates;
+	uint16_t acl_rx_mtu;
+} __attribute__ ((packed));
+
+#define BT_LL_HDT_LQF_REPORTING_IND 0x44
+struct bt_ll_hdt_lqf_ind {
+	uint8_t  transport;
+} __attribute__ ((packed));
+
+
 #define LMP_ESC4(x) ((127 << 8) | (x))
 
 #define BT_LMP_NAME_REQ			1
@@ -3247,6 +3309,235 @@ struct bt_hci_rsp_le_read_conn_interval {
 	struct bt_hci_le_conn_interval_group grps[0];
 } __attribute__ ((packed));
 
+#define BT_HCI_CMD_LE_WRITE_DEF_DATA_LEN_V2	0x20b2
+#define BT_HCI_BIT_LE_WRITE_DEF_DATA_LEN_V2	BT_HCI_CMD_BIT(50, 7)
+struct bt_hci_cmd_le_write_def_data_len_v2 {
+	uint16_t tx_len;
+	uint16_t tx_time;
+	uint8_t  phys;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_DEF_DATA_LEN_V2	0x20b1
+#define BT_HCI_BIT_LE_READ_DEF_DATA_LEN_V2	BT_HCI_CMD_BIT(50, 6)
+struct bt_hci_cmd_le_read_def_data_len_v2 {
+	uint8_t  phys;
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_read_def_data_len_v2 {
+	uint8_t  status;
+	uint16_t tx_len;
+	uint16_t tx_time;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_ENABLE_ENCRYPT_V2		0x20af
+#define BT_HCI_BIT_LE_ENABLE_ENCRYPT_V2		BT_HCI_CMD_BIT(50, 4)
+struct bt_hci_cmd_le_enable_encrypt_v2 {
+	uint16_t handle;
+	uint64_t rand;
+	uint16_t ediv;
+	uint8_t  ltk[16];
+	uint8_t  mic_len;
+	uint8_t  encryption;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_MAX_DATA_LEN_V2	0x20b0
+#define BT_HCI_BIT_LE_READ_MAX_DATA_LEN_V2	BT_HCI_CMD_BIT(50, 5)
+struct bt_hci_cmd_le_read_data_len_v2 {
+	uint8_t  phy;
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_read_data_len_v2 {
+	uint8_t  status;
+	uint16_t max_tx_len;
+	uint16_t max_tx_time;
+	uint16_t max_rx_len;
+	uint16_t max_rx_time;
+	uint8_t  max_tx_win;
+	uint8_t  max_rx_win;
+	uint16_t max_rx_packet;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_DATA_LEN_V2	0x20aa
+#define BT_HCI_BIT_LE_SET_DATA_LEN_V2	BT_HCI_CMD_BIT(52, 3)
+struct bt_hci_cmd_le_set_data_len_v2 {
+	uint16_t handle;
+	uint16_t tx_len;
+	uint16_t tx_time;
+	uint8_t  phys;
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_set_data_len_v2 {
+	uint8_t  status;
+	uint16_t handle;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_CIG_PARAMS_V2		0x20b3
+#define BT_HCI_BIT_LE_SET_CIG_PARAMS_V2		BT_HCI_CMD_BIT(51, 0)
+struct bt_hci_cis_params_v2 {
+	uint8_t  cis_id;
+	uint16_t c_sdu;
+	uint16_t p_sdu;
+	uint8_t  c_phy;
+	uint8_t  p_phy;
+	uint8_t  c_rtn;
+	uint8_t  p_rtn;
+	uint8_t  c_coded_rates;
+	uint8_t  p_coded_rates;
+	uint16_t c_hdt_rates;
+	uint16_t p_hdt_rates;
+	uint8_t  mic_len;
+	uint8_t  format;
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_set_cig_params_v2 {
+	uint8_t  cig_id;
+	uint8_t  c_interval[3];
+	uint8_t  p_interval[3];
+	uint8_t  sca;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint16_t c_latency;
+	uint16_t p_latency;
+	uint8_t  num_cis;
+	struct bt_hci_cis_params_v2 cis[0];
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_set_cig_params_v2 {
+	uint8_t  status;
+	uint8_t  cig_id;
+	uint8_t  num_handles;
+	uint16_t handle[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_CIG_PARAMS_TEST_V2	0x20b4
+#define BT_HCI_BIT_LE_SET_CIG_PARAMS_TEST_V2	BT_HCI_CMD_BIT(51, 1)
+struct bt_hci_cis_params_test_v2 {
+	uint8_t  cis_id;
+	uint8_t  nse;
+	uint16_t c_sdu;
+	uint16_t p_sdu;
+	uint16_t c_pdu;
+	uint16_t p_pdu;
+	uint8_t  c_phy;
+	uint8_t  p_phy;
+	uint8_t  c_bn;
+	uint8_t  p_bn;
+	uint8_t  c_coded_rates;
+	uint8_t  p_coded_rates;
+	uint16_t c_hdt_rates;
+	uint16_t p_hdt_rates;
+	uint8_t  mic_len;
+	uint8_t  format;
+	uint8_t  c_win;
+	uint8_t  p_win;
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_set_cig_params_test_v2 {
+	uint8_t  cig_id;
+	uint8_t  c_interval[3];
+	uint8_t  p_interval[3];
+	uint8_t  c_ft;
+	uint8_t  p_ft;
+	uint16_t iso_interval;
+	uint8_t  sca;
+	uint16_t anchor_update;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  num_cis;
+	struct bt_hci_cis_params_test_v2 cis[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_CREATE_BIG_V2		0x20b6
+#define BT_HCI_BIT_LE_CREATE_BIG_V2		BT_HCI_CMD_BIT(51, 3)
+struct bt_hci_bis_v2 {
+	uint8_t  sdu_interval[3];
+	uint16_t sdu;
+	uint16_t latency;
+	uint8_t  rtn;
+	uint8_t  phy;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+	uint8_t  coded_rates;
+	uint16_t hdt_rates;
+	uint8_t  mic_len;
+	uint8_t  format;
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_create_big_v2 {
+	uint8_t  handle;
+	uint8_t  adv_handle;
+	uint8_t  num_bis;
+	struct bt_hci_bis_v2 bis;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_CREATE_BIG_TEST_V2	0x20b7
+#define BT_HCI_BIT_LE_CREATE_BIG_TEST_V2	BT_HCI_CMD_BIT(51, 4)
+struct bt_hci_bis_test_v2 {
+	uint8_t  sdu_interval[3];
+	uint16_t iso_interval;
+	uint8_t  nse;
+	uint16_t sdu;
+	uint16_t pdu;
+	uint8_t  phy;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  bn;
+	uint8_t  irc;
+	uint8_t  pto;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+	uint8_t  coded_rates;
+	uint16_t hdt_rates;
+	uint8_t  mic_len;
+	uint8_t  format;
+	uint8_t  blocks;
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_create_big_test_v2 {
+	uint8_t  big_handle;
+	uint8_t  adv_handle;
+	uint8_t  num_bis;
+	struct bt_hci_bis_test_v2 bis[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_HDT_DEFAULT_PARAMS	0x20bc
+#define BT_HCI_BIT_LE_SET_HDT_DEFAULT_PARAMS	BT_HCI_CMD_BIT(52, 1)
+struct bt_hci_cmd_le_hdt_set_default_params {
+	uint8_t  mic_len;
+	uint8_t  format;
+	uint16_t rates;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_HDT_PARAMS_TEST	0x20bd
+#define BT_HCI_BIT_LE_SET_HDT_PARAMS_TEST	BT_HCI_CMD_BIT(52, 2)
+struct bt_hci_cmd_le_hdt_set_params_test {
+	uint16_t handle;
+	uint8_t  mic_len;
+	uint8_t  format;
+	uint8_t  blocks;
+	uint16_t tx_rates;
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_hdt_set_params_test {
+	uint8_t  status;
+	uint16_t handle;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_EKS_DEBUG_MODE	0x20b8
+#define BT_HCI_BIT_LE_READ_EKS_DEBUG_MODE	BT_HCI_CMD_BIT(51, 5)
+struct bt_hci_rsp_le_read_eks_debug_mode {
+	uint8_t  status;
+	uint8_t  mode;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_WRITE_EKS_DEBUG_MODE	0x20b9
+#define BT_HCI_BIT_LE_WRITE_EKS_DEBUG_MODE	BT_HCI_CMD_BIT(51, 6)
+struct bt_hci_cmd_le_write_eks_debug_mode {
+	uint8_t  mode;
+} __attribute__ ((packed));
+
 #define BT_HCI_EVT_INQUIRY_COMPLETE		0x01
 struct bt_hci_evt_inquiry_complete {
 	uint8_t  status;
@@ -4224,6 +4515,93 @@ struct bt_hci_evt_le_conn_rate_change {
 	uint16_t supv_timeout;
 } __attribute__ ((packed));
 
+#define BT_HCI_EVT_ENCRYPT_CHANGE_V3		0x5a
+#define BT_HCI_BIT_ENCRYPT_CHANGE_V3		26
+struct bt_hci_evt_encrypt_change_v3 {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  mode;
+	uint8_t  key_size;
+	uint8_t  mic_len;
+	uint8_t  eks_mode;
+	uint8_t  eks_debug;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE_V2 0x5b
+#define BT_HCI_BIT_ENCRYPT_KEY_REFRESH_COMPLETE_V2 27
+struct bt_hci_evt_encrypt_key_refresh_complete_v2 {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  mic_len;
+	uint8_t  eks_mode;
+	uint8_t  eks_debug;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_DATA_LENGTH_CHANGE_V2	0x39
+#define BT_HCI_BIT_LE_DATA_LENGTH_CHANGE_V2	56
+struct bt_hci_evt_le_data_length_change_v2 {
+	uint16_t handle;
+	uint16_t max_tx_len;
+	uint16_t max_tx_time;
+	uint16_t max_rx_len;
+	uint16_t max_rx_time;
+	uint8_t  phys;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_CIS_ESTABLISHED_V3	0x3a
+#define BT_HCI_BIT_LE_CIS_ESTABLISHED_V3	57
+struct bt_hci_evt_le_cis_established_v3 {
+	uint8_t  status;
+	uint16_t conn_handle;
+	uint8_t  cig_sync_delay[3];
+	uint8_t  cis_sync_delay[3];
+	uint8_t  c_latency[3];
+	uint8_t  p_latency[3];
+	uint8_t  c_phy;
+	uint8_t  p_phy;
+	uint8_t  nse;
+	uint8_t  c_bn;
+	uint8_t  p_bn;
+	uint8_t  c_ft;
+	uint8_t  p_ft;
+	uint16_t c_mtu;
+	uint16_t p_mtu;
+	uint16_t interval;
+	uint8_t  sub_interval[3];
+	uint16_t c_sdu;
+	uint16_t p_sdu;
+	uint8_t  c_sdu_interval[3];
+	uint8_t  p_sdu_interval[3];
+	uint8_t  framing;
+	uint16_t c_rates;
+	uint16_t p_rates;
+	uint8_t  config_id;
+	uint8_t  group_id;
+	uint8_t  encryption;
+	uint8_t  mic_len;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_BIG_COMPLETE_V2		0x3b
+#define BT_HCI_BIT_LE_BIG_COMPLETE_V2		58
+struct bt_hci_evt_le_big_complete_v2 {
+	uint8_t  status;
+	uint8_t  handle;
+	uint8_t  sync_delay[3];
+	uint8_t  latency[3];
+	uint8_t  phy;
+	uint8_t  nse;
+	uint8_t  bn;
+	uint8_t  pto;
+	uint8_t  irc;
+	uint16_t max_pdu;
+	uint16_t interval;
+	uint16_t rates;
+	uint8_t  encryption;
+	uint8_t  mic_len;
+	uint8_t  num_bis;
+	uint16_t bis_handle[0];
+} __attribute__ ((packed));
+
 #define BT_HCI_ERR_SUCCESS			0x00
 #define BT_HCI_ERR_UNKNOWN_COMMAND		0x01
 #define BT_HCI_ERR_UNKNOWN_CONN_ID		0x02
diff --git a/monitor/l2cap.c b/monitor/l2cap.c
index d94d996010ff..ddc2388d55b8 100644
--- a/monitor/l2cap.c
+++ b/monitor/l2cap.c
@@ -633,6 +633,9 @@ static void print_le_conn_result(uint16_t result)
 	case 0x000b:
 		str = "Connection refused - unacceptable parameters";
 		break;
+	case 0x000c:
+		str = "Connection refused - MIC length too short";
+		break;
 	default:
 		str = "Reserved";
 		break;
@@ -1440,6 +1443,9 @@ static void print_ecred_conn_result(uint16_t result)
 	case 0x000b:
 		str = "All Connections refused - unacceptable parameters";
 		break;
+	case 0x0010:
+		str = "All Connections refused - MIC length too short";
+		break;
 	default:
 		str = "Reserved";
 		break;
diff --git a/monitor/packet.c b/monitor/packet.c
index c8a53a119294..a577f02b7d87 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -1004,6 +1004,9 @@ static const struct {
 	{ 0x43, "Limit Reached"						},
 	{ 0x44, "Operation Cancelled by Host"				},
 	{ 0x45, "Packet Too Long"					},
+	{ 0x49, "Invalid Packet Format"					},
+	{ 0x4a, "Invalid Public Key"					},
+	{ 0x4b, "Debug Key Not Allowed"					},
 	{ }
 };
 
@@ -3224,6 +3227,15 @@ static const struct bitfield_data features_le_1[] = {
 	{  9, "Shorter Connection Intervals (Host Support)"	},
 	{ 10, "LE Flushable ACL Data"				},
 	{ 11, "Channel Sounding Enhancement #1"			},
+	{ 12, "Encryption Key Schedule"				},
+	{ 13, "High Data Throughput"				},
+	{ 14, "Receive HDT6 Rate"				},
+	{ 15, "Transmit HDT6 Rate"				},
+	{ 16, "Receive HDT7.5 Rate"				},
+	{ 17, "Transmit HDT7.5 Rate"				},
+	{ 18, "HDT Packet Format 1"				},
+	{ 19, "Link Quality Feedback"				},
+	{ 26, "Opportunistic Encryption (Host Support)"		},
 	{ }
 };
 
@@ -3299,6 +3311,7 @@ static void print_features(uint8_t page, const uint8_t *features_array,
 			break;
 		case 1:
 			features_table = features_le_1;
+			break;
 		}
 		break;
 	case 0xf0:
@@ -3612,9 +3625,11 @@ static const struct bitfield_data events_page2_table[] = {
 	{ 23, "Authenticated Payload Timeout Expired"			},
 	{ 24, "SAM Status Change"					},
 	{ 25, "Encryption Change [v2]"					},
+	{ 26, "Encryption Change [v3]"					},
+	{ 27, "Encryption Key Refresh Complete [v2]"			},
+	{ 28, "Encryption Key Debug Report"				},
 	{ }
 };
-
 static const struct bitfield_data events_le_table[] = {
 	{  0, "LE Connection Complete"					},
 	{  1, "LE Advertising Report"					},
@@ -3672,6 +3687,9 @@ static const struct bitfield_data events_le_table[] = {
 	{ 53, "LE UTP Received"						},
 	{ 54, "LE Connection Rate Change"				},
 	{ 55, "LE CS Read Remote Supported Capabilities Complete [v2]"	},
+	{ 56, "LE Data Length Change [v2]"				},
+	{ 57, "LE CIS Established [v3]"				},
+	{ 58, "LE Create BIG Complete [v2]"				},
 	{ }
 };
 
@@ -8165,6 +8183,9 @@ static void print_le_phy(const char *prefix, uint8_t phy)
 	case 0x03:
 		str = "LE Coded";
 		break;
+	case 0x05:
+		str = "LE HDT";
+		break;
 	default:
 		str = "Reserved";
 		break;
@@ -8187,6 +8208,7 @@ static const struct bitfield_data le_phys[] = {
 	{  0, "LE 1M"	},
 	{  1, "LE 2M"	},
 	{  2, "LE Coded"},
+	{  4, "LE HDT"	},
 	{ }
 };
 
@@ -8232,26 +8254,36 @@ static void le_set_default_phy_cmd(uint16_t index, const void *data,
 	print_le_phys_preference(cmd->all_phys, cmd->tx_phys, cmd->rx_phys);
 }
 
+static const struct bitfield_data hdt_phy_opts[] = {
+	{ 0, "Coded S=2" },
+	{ 1, "Coded S=8" },
+	{ 2, "HDT 2M" },
+	{ 3, "HDT 3M" },
+	{ 4, "HDT 4M" },
+	{ 5, "HDT 6M" },
+	{ 6, "HDT 7.5M" },
+	{ }
+};
+
+static void print_le_phy_options(const char *label, uint16_t opts)
+{
+	uint16_t mask;
+
+	print_field("%s: 0x%4.4x", label, opts);
+
+	mask = print_bitfield(4, opts, hdt_phy_opts);
+	if (mask)
+		print_text(COLOR_UNKNOWN_OPTIONS_BIT, "  Reserved"
+							" (0x%4.4x)", mask);
+}
+
 static void le_set_phy_cmd(uint16_t index, const void *data, uint8_t size)
 {
 	const struct bt_hci_cmd_le_set_phy *cmd = data;
-	const char *str;
 
 	print_handle(cmd->handle);
 	print_le_phys_preference(cmd->all_phys, cmd->tx_phys, cmd->rx_phys);
-	switch (le16_to_cpu(cmd->phy_opts)) {
-	case 0x0001:
-		str = "S2 coding";
-		break;
-	case 0x0002:
-		str = "S8 coding";
-		break;
-	default:
-		str = "Reserved";
-		break;
-	}
-
-	print_field("PHY options preference: %s (0x%4.4x)", str, cmd->phy_opts);
+	print_le_phy_options("PHY Options", le16_to_cpu(cmd->phy_opts));
 }
 
 static void le_enhanced_receiver_test_cmd(uint16_t index, const void *data,
@@ -9208,7 +9240,7 @@ static void print_framing(uint8_t value)
 		print_field("Framing: Framed (0x%2.2x)", value);
 		return;
 	default:
-		print_field("Packing: Reserved (0x%2.2x)", value);
+		print_field("Framing: Reserved (0x%2.2x)", value);
 	}
 }
 
@@ -10302,229 +10334,752 @@ static void le_read_conn_interval_rsp(uint16_t index, const void *data,
 	}
 }
 
-struct opcode_data {
-	uint16_t opcode;
-	int bit;
+static void print_le_def_phys(uint8_t phys)
+{
 	const char *str;
-	void (*cmd_func) (uint16_t index, const void *data, uint8_t size);
-	uint8_t cmd_size;
-	bool cmd_fixed;
-	void (*rsp_func) (uint16_t index, const void *data, uint8_t size);
-	uint8_t rsp_size;
-	bool rsp_fixed;
-};
 
-static const struct opcode_data opcode_table[] = {
-	{ 0x0000,  -1, "NOP" },
+	switch (phys) {
+	case 0x00:
+		str = "All GFSK";
+		break;
+	case 0x01:
+		str = "HDT";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
 
-	/* OGF 1 - Link Control */
-	{ 0x0401,   0, "Inquiry",
-				inquiry_cmd, 5, true },
-	{ 0x0402,   1, "Inquiry Cancel",
-				null_cmd, 0, true,
-				status_rsp, 1, true },
-	{ 0x0403,   2, "Periodic Inquiry Mode",
-				periodic_inquiry_cmd, 9, true,
-				status_rsp, 1, true },
-	{ 0x0404,   3, "Exit Periodic Inquiry Mode",
-				null_cmd, 0, true,
-				status_rsp, 1, true },
-	{ 0x0405,   4, "Create Connection",
-				create_conn_cmd, 13, true },
-	{ 0x0406,   5, "Disconnect",
-				disconnect_cmd, 3, true },
-	{ 0x0407,   6, "Add SCO Connection",
-				add_sco_conn_cmd, 4, true },
-	{ 0x0408,   7, "Create Connection Cancel",
-				create_conn_cancel_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x0409,   8, "Accept Connection Request",
-				accept_conn_request_cmd, 7, true },
-	{ 0x040a,   9, "Reject Connection Request",
-				reject_conn_request_cmd, 7, true },
-	{ 0x040b,  10, "Link Key Request Reply",
-				link_key_request_reply_cmd, 22, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x040c,  11, "Link Key Request Negative Reply",
-				link_key_request_neg_reply_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x040d,  12, "PIN Code Request Reply",
-				pin_code_request_reply_cmd, 23, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x040e,  13, "PIN Code Request Negative Reply",
-				pin_code_request_neg_reply_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x040f,  14, "Change Connection Packet Type",
-				change_conn_pkt_type_cmd, 4, true },
-	{ 0x0411,  15, "Authentication Requested",
-				auth_requested_cmd, 2, true },
-	{ 0x0413,  16, "Set Connection Encryption",
-				set_conn_encrypt_cmd, 3, true },
-	{ 0x0415,  17, "Change Connection Link Key",
-				change_conn_link_key_cmd, 2, true },
-	{ 0x0417,  18, "Temporary Link Key",
-				link_key_selection_cmd, 1, true },
-	{ 0x0419,  19, "Remote Name Request",
-				remote_name_request_cmd, 10, true },
-	{ 0x041a,  20, "Remote Name Request Cancel",
-				remote_name_request_cancel_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x041b,  21, "Read Remote Supported Features",
-				read_remote_features_cmd, 2, true },
-	{ 0x041c,  22, "Read Remote Extended Features",
-				read_remote_ext_features_cmd, 3, true },
-	{ 0x041d,  23, "Read Remote Version Information",
-				read_remote_version_cmd, 2, true },
-	{ 0x041f,  24, "Read Clock Offset",
-				read_clock_offset_cmd, 2, true },
-	{ 0x0420,  25, "Read LMP Handle",
-				read_lmp_handle_cmd, 2, true,
-				read_lmp_handle_rsp, 8, true },
-	{ 0x0428, 131, "Setup Synchronous Connection",
-				setup_sync_conn_cmd, 17, true },
-	{ 0x0429, 132, "Accept Synchronous Connection Request",
-				accept_sync_conn_request_cmd, 21, true },
-	{ 0x042a, 133, "Reject Synchronous Connection Request",
-				reject_sync_conn_request_cmd, 7, true },
-	{ 0x042b, 151, "IO Capability Request Reply",
-				io_capability_request_reply_cmd, 9, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x042c, 152, "User Confirmation Request Reply",
-				user_confirm_request_reply_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x042d, 153, "User Confirmation Request Neg Reply",
-				user_confirm_request_neg_reply_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x042e, 154, "User Passkey Request Reply",
-				user_passkey_request_reply_cmd, 10, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x042f, 155, "User Passkey Request Negative Reply",
-				user_passkey_request_neg_reply_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x0430, 156, "Remote OOB Data Request Reply",
-				remote_oob_data_request_reply_cmd, 38, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x0433, 159, "Remote OOB Data Request Neg Reply",
-				remote_oob_data_request_neg_reply_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x0434, 163, "IO Capability Request Negative Reply",
-				io_capability_request_neg_reply_cmd, 7, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x0435, 168, "Create Physical Link",
-				create_phy_link_cmd, 3, false },
-	{ 0x0436, 169, "Accept Physical Link",
-				accept_phy_link_cmd, 3, false },
-	{ 0x0437, 170, "Disconnect Physical Link",
-				disconn_phy_link_cmd, 2, true },
-	{ 0x0438, 171, "Create Logical Link",
-				create_logic_link_cmd, 33, true },
-	{ 0x0439, 172, "Accept Logical Link",
-				accept_logic_link_cmd, 33, true },
-	{ 0x043a, 173, "Disconnect Logical Link",
-				disconn_logic_link_cmd, 2, true },
-	{ 0x043b, 174, "Logical Link Cancel",
-				logic_link_cancel_cmd, 2, true,
-				logic_link_cancel_rsp, 3, true },
-	{ 0x043c, 175, "Flow Specification Modify",
-				flow_spec_modify_cmd, 34, true },
-	{ 0x043d, 235, "Enhanced Setup Synchronous Connection",
-				enhanced_setup_sync_conn_cmd, 59, true },
-	{ 0x043e, 236, "Enhanced Accept Synchronous Connection Request",
-				enhanced_accept_sync_conn_request_cmd, 63, true },
-	{ 0x043f, 246, "Truncated Page",
-				truncated_page_cmd, 9, true },
-	{ 0x0440, 247, "Truncated Page Cancel",
-				truncated_page_cancel_cmd, 6, true,
-				status_bdaddr_rsp, 7, true },
-	{ 0x0441, 248, "Set Connectionless Peripheral Broadcast",
-				set_peripheral_broadcast_cmd, 11, true,
-				set_peripheral_broadcast_rsp, 4, true },
-	{ 0x0442, 249, "Set Connectionless Peripheral Broadcast Receive",
-				set_peripheral_broadcast_receive_cmd, 34, true,
-				set_peripheral_broadcast_receive_rsp, 8, true },
-	{ 0x0443, 250, "Start Synchronization Train",
-				null_cmd, 0, true },
-	{ 0x0444, 251, "Receive Synchronization Train",
-				receive_sync_train_cmd, 12, true },
-	{ 0x0445, 257, "Remote OOB Extended Data Request Reply",
-				remote_oob_ext_data_request_reply_cmd, 70, true,
-				status_bdaddr_rsp, 7, true },
+	print_field("PHYs: %s (0x%2.2x)", str, phys);
+}
 
-	/* OGF 2 - Link Policy */
-	{ 0x0801,  33, "Hold Mode",
-				hold_mode_cmd, 6, true },
-	{ 0x0803,  34, "Sniff Mode",
-				sniff_mode_cmd, 10, true },
-	{ 0x0804,  35, "Exit Sniff Mode",
-				exit_sniff_mode_cmd, 2, true },
-	{ 0x0805,  36, "Park State",
-				park_state_cmd, 6, true },
-	{ 0x0806,  37, "Exit Park State",
-				exit_park_state_cmd, 2, true },
-	{ 0x0807,  38, "QoS Setup",
-				qos_setup_cmd, 20, true },
-	{ 0x0809,  39, "Role Discovery",
-				role_discovery_cmd, 2, true,
-				role_discovery_rsp, 4, true },
-	{ 0x080b,  40, "Switch Role",
-				switch_role_cmd, 7, true },
-	{ 0x080c,  41, "Read Link Policy Settings",
-				read_link_policy_cmd, 2, true,
-				read_link_policy_rsp, 5, true },
-	{ 0x080d,  42, "Write Link Policy Settings",
-				write_link_policy_cmd, 4, true,
-				write_link_policy_rsp, 3, true },
-	{ 0x080e,  43, "Read Default Link Policy Settings",
-				null_cmd, 0, true,
-				read_default_link_policy_rsp, 3, true },
-	{ 0x080f,  44, "Write Default Link Policy Settings",
-				write_default_link_policy_cmd, 2, true,
-				status_rsp, 1, true },
-	{ 0x0810,  45, "Flow Specification",
-				flow_spec_cmd, 21, true },
-	{ 0x0811, 140, "Sniff Subrating",
-				sniff_subrating_cmd, 8, true,
-				sniff_subrating_rsp, 3, true },
+static void le_write_def_data_len_v2(uint16_t index, const void *data,
+							uint8_t size)
+{
+	const struct bt_hci_cmd_le_write_def_data_len_v2 *cmd = data;
 
-	/* OGF 3 - Host Control */
-	{ 0x0c01,  46, "Set Event Mask",
-				set_event_mask_cmd, 8, true,
-				status_rsp, 1, true },
-	{ 0x0c03,  47, "Reset",
-				null_cmd, 0, true,
-				status_rsp, 1, true },
-	{ 0x0c05,  48, "Set Event Filter",
-				set_event_filter_cmd, 1, false,
-				status_rsp, 1, true },
-	{ 0x0c08,  49, "Flush",
-				flush_cmd, 2, true,
-				flush_rsp, 3, true },
-	{ 0x0c09,  50, "Read PIN Type",
-				null_cmd, 0, true,
-				read_pin_type_rsp, 2, true },
-	{ 0x0c0a,  51, "Write PIN Type",
-				write_pin_type_cmd, 1, true,
-				status_rsp, 1, true },
-	{ 0x0c0b,  52, "Create New Unit Key",
-				null_cmd, 0, true,
-				status_rsp, 1, true },
-	{ 0x0c0d,  53, "Read Stored Link Key",
-				read_stored_link_key_cmd, 7, true,
-				read_stored_link_key_rsp, 5, true },
-	{ 0x0c11,  54, "Write Stored Link Key",
-				write_stored_link_key_cmd, 1, false,
-				write_stored_link_key_rsp, 2, true },
-	{ 0x0c12,  55, "Delete Stored Link Key",
-				delete_stored_link_key_cmd, 7, true,
-				delete_stored_link_key_rsp, 3, true },
-	{ 0x0c13,  56, "Write Local Name",
-				write_local_name_cmd, 248, true,
-				status_rsp, 1, true },
-	{ 0x0c14,  57, "Read Local Name",
-				null_cmd, 0, true,
-				read_local_name_rsp, 249, true },
-	{ 0x0c15,  58, "Read Connection Accept Timeout",
-				null_cmd, 0, true,
+	print_field("TX octets: %d", le16_to_cpu(cmd->tx_len));
+	print_field("TX time: %d", le16_to_cpu(cmd->tx_time));
+	print_le_def_phys(cmd->phys);
+}
+
+static void le_read_def_data_len_v2(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_read_def_data_len_v2 *cmd = data;
+
+	print_le_def_phys(cmd->phys);
+}
+
+static void le_read_def_data_len_v2_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_read_def_data_len_v2 *rsp = data;
+
+	print_status(rsp->status);
+	print_field("TX octets: %d", le16_to_cpu(rsp->tx_len));
+	print_field("TX time: %d", le16_to_cpu(rsp->tx_time));
+}
+
+static void print_prefer_mic_len(uint8_t mic_len)
+{
+	const char *str;
+
+	switch (mic_len) {
+	case 0x01:
+		str = "Prefer 64 bits";
+		break;
+	case 0x02:
+		str = "128 bits";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
+
+	print_field("MIC Length: %s (0x%2.2x)", str, mic_len);
+}
+
+static void print_enable_encrypt(uint8_t encrypt)
+{
+	const char *str;
+
+	switch (encrypt) {
+	case 0x00:
+		str = "LTK";
+		break;
+	case 0x01:
+		str = "Opportunistic with Key Schedule";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
+
+	print_field("Encryption: %s (0x%2.2x)", str, encrypt);
+}
+
+static void le_enable_encrypt_v2(uint16_t index, const void *data, uint8_t size)
+{
+	const struct bt_hci_cmd_le_enable_encrypt_v2 *cmd = data;
+
+	print_handle(cmd->handle);
+	print_random_number(cmd->rand);
+	print_encrypted_diversifier(cmd->ediv);
+	print_key("Long term key", cmd->ltk);
+	print_prefer_mic_len(cmd->mic_len);
+	print_enable_encrypt(cmd->encryption);
+}
+
+static void print_set_le_phy(const char *prefix, uint8_t phy)
+{
+	if (phy)
+		return print_le_phy(prefix, phy);
+
+	print_field("%s: No PHY (0x%2.2x)", prefix, phy);
+}
+
+static void le_read_max_data_len_v2(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_read_data_len_v2 *cmd = data;
+
+	print_set_le_phy("PHY", cmd->phy);
+}
+
+static void le_read_max_data_len_v2_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_read_data_len_v2 *rsp = data;
+
+	print_status(rsp->status);
+	print_field("Max TX octets: %d", le16_to_cpu(rsp->max_tx_len));
+	print_field("Max TX time: %d", le16_to_cpu(rsp->max_tx_time));
+	print_field("Max RX octets: %d", le16_to_cpu(rsp->max_rx_len));
+	print_field("Max RX time: %d", le16_to_cpu(rsp->max_rx_time));
+	print_field("Max TX Payload Window size: %d", rsp->max_tx_win);
+	print_field("Max RX Payload Window size: %d", rsp->max_rx_win);
+	print_field("Max RX Payload Packet size: %d",
+			le16_to_cpu(rsp->max_rx_packet));
+}
+
+static void print_phys(uint8_t phys)
+{
+	const char *str;
+
+	switch (phys) {
+	case 0x00:
+		str = "GFSK";
+		break;
+	case 0x01:
+		str = "HDT";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
+
+	print_field("PHYs: %s (0x%2.2x)", str, phys);
+}
+
+static void le_set_data_len_v2(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_set_data_len_v2 *cmd = data;
+
+	print_handle(cmd->handle);
+	print_field("TX octets: %d", le16_to_cpu(cmd->tx_len));
+	print_field("TX time: %d", le16_to_cpu(cmd->tx_time));
+	print_phys(cmd->phys);
+}
+
+static void le_set_data_len_v2_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_set_data_len_v2 *rsp = data;
+
+	print_status(rsp->status);
+	print_handle(rsp->handle);
+}
+
+static const struct bitfield_data coded_rates[] = {
+	{ 0, "CODED S=8" },
+	{ 1, "CODED S=2" },
+	{ }
+};
+
+static const struct bitfield_data hdt_rates[] = {
+	{ 0, "HDT 2M" },
+	{ 1, "HDT 3M" },
+	{ 2, "HDT 4M" },
+	{ 3, "HDT 6M" },
+	{ 4, "HDT 7.5M" },
+	{ }
+};
+
+static void print_rates(const char *prefix, uint8_t phy, uint16_t rates)
+{
+	const struct bitfield_data *fields = NULL;
+
+	switch (phy) {
+	case 0x01:
+	case 0x02:
+		break;
+	case 0x03:
+		fields = coded_rates;
+		break;
+	case 0x05:
+		fields = hdt_rates;
+		break;
+	default:
+		break;
+	}
+
+	print_field("%s: 0x%4.4x", prefix, rates);
+
+	if (fields) {
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)
+			print_text(COLOR_UNKNOWN_OPTIONS_BIT, "  Reserved"
+							" (0x%4.4x)", mask);
+	}
+}
+
+static void print_packet_format(uint8_t format)
+{
+	const char *str;
+
+	switch (format) {
+	case 0x00:
+		str = "No preffered format";
+		break;
+	case 0x01:
+		str = "Packet Format 0";
+		break;
+	case 0x02:
+		str = "Packet Format 1";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
+
+	print_field("Packet Format: %s (0x%2.2x)", str, format);
+}
+
+static void print_cis_params_v2(const void *data, int i)
+{
+	const struct bt_hci_cis_params_v2 *cis = data;
+
+	print_field("CIS ID: 0x%2.2x", cis->cis_id);
+	print_field("Central to Peripheral Maximum SDU Size: %u",
+						le16_to_cpu(cis->c_sdu));
+	print_field("Peripheral to Central Maximum SDU Size: %u",
+						le16_to_cpu(cis->p_sdu));
+	print_le_phys("Central to Peripheral PHY", cis->c_phy);
+	print_le_phys("Peripheral to Central PHY", cis->p_phy);
+	print_field("Central to Peripheral Retransmission attempts: 0x%2.2x",
+							cis->c_rtn);
+	print_field("Peripheral to Central Retransmission attempts: 0x%2.2x",
+							cis->p_rtn);
+	print_rates("Central to Peripheral Coded Rates", 0x03,
+			cis->c_coded_rates);
+	print_rates("Peripheral to Central Coded Rates", 0x03,
+			cis->p_coded_rates);
+	print_rates("Central to Peripheral HDT Rates", 0x05,
+			le16_to_cpu(cis->c_hdt_rates));
+	print_rates("Peripheral to Central HDT Rates", 0x05,
+			le16_to_cpu(cis->p_hdt_rates));
+	print_prefer_mic_len(cis->mic_len);
+	print_packet_format(cis->format);
+}
+
+static void le_set_cig_params_v2(uint16_t index, const void *data, uint8_t size)
+{
+	const struct bt_hci_cmd_le_set_cig_params_v2 *cmd = data;
+
+	print_field("CIG ID: 0x%2.2x", cmd->cig_id);
+	print_usec_interval("Central to Peripheral SDU Interval",
+							cmd->c_interval);
+	print_usec_interval("Peripheral to Central SDU Interval",
+							cmd->p_interval);
+	print_sca(cmd->sca);
+	print_packing(cmd->packing);
+	print_framing(cmd->framing);
+	print_field("Central to Peripheral Maximum Latency: %d ms (0x%4.4x)",
+		le16_to_cpu(cmd->c_latency), le16_to_cpu(cmd->c_latency));
+	print_field("Peripheral to Central Maximum Latency: %d ms (0x%4.4x)",
+		le16_to_cpu(cmd->p_latency), le16_to_cpu(cmd->p_latency));
+	print_field("Number of CIS: %u", cmd->num_cis);
+
+	size -= sizeof(*cmd);
+
+	print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis),
+						print_cis_params_v2);
+}
+
+static void le_set_cig_params_v2_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_set_cig_params *rsp = data;
+
+	print_status(rsp->status);
+
+	if (size == 1)
+		return;
+
+	print_field("CIG ID: 0x%2.2x", rsp->cig_id);
+	print_field("Number of Handles: %u", rsp->num_handles);
+
+	size -= sizeof(*rsp);
+
+	print_list(rsp->handle, size, rsp->num_handles, sizeof(*rsp->handle),
+						print_cig_handle);
+}
+
+static void print_cis_params_test_v2(const void *data, int i)
+{
+	const struct bt_hci_cis_params_test_v2 *cis = data;
+
+	print_field("CIS ID: 0x%2.2x", cis->cis_id);
+	print_field("NSE: 0x%2.2x", cis->nse);
+	print_field("Central to Peripheral Maximum SDU: 0x%4.4x",
+						le16_to_cpu(cis->c_sdu));
+	print_field("Peripheral to Central Maximum SDU: 0x%4.4x",
+						le16_to_cpu(cis->p_sdu));
+	print_field("Central to Peripheral Maximum PDU: 0x%4.4x",
+						le16_to_cpu(cis->c_pdu));
+	print_field("Peripheral to Central Maximum PDU: 0x%4.4x",
+						le16_to_cpu(cis->p_pdu));
+	print_le_phys("Central to Peripheral PHY", cis->c_phy);
+	print_le_phys("Peripheral to Central PHY", cis->p_phy);
+	print_field("Central to Peripheral Burst Number: 0x%2.2x", cis->c_bn);
+	print_field("Peripheral to Central Burst Number: 0x%2.2x", cis->p_bn);
+	print_rates("Central to Peripheral Coded Rates", 0x03,
+			cis->c_coded_rates);
+	print_rates("Peripheral to Central Coded Rates", 0x03,
+			cis->p_coded_rates);
+	print_rates("Central to Peripheral HDT Rates", 0x05,
+			le16_to_cpu(cis->c_hdt_rates));
+	print_rates("Peripheral to Central HDT Rates", 0x05,
+			le16_to_cpu(cis->p_hdt_rates));
+	print_prefer_mic_len(cis->mic_len);
+	print_packet_format(cis->format);
+	print_field("Central to Peripheral Payload Window size: %d",
+			cis->c_win);
+	print_field("Peripheral to Central Payload Window size: %d",
+			cis->p_win);
+}
+
+static void le_set_cig_params_test_v2(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_set_cig_params_test_v2 *cmd = data;
+
+	print_field("CIG ID: 0x%2.2x", cmd->cig_id);
+	print_usec_interval("Central to Peripheral SDU Interval",
+							cmd->c_interval);
+	print_usec_interval("Peripheral to Central SDU Interval",
+							cmd->p_interval);
+	print_field("Central to Peripheral Flush Timeout: 0x%2.2x", cmd->c_ft);
+	print_field("Peripheral to Central Flush Timeout: 0x%2.2x", cmd->p_ft);
+	print_field("ISO Interval: %.2f ms (0x%4.4x)",
+				le16_to_cpu(cmd->iso_interval) * 1.25,
+				le16_to_cpu(cmd->iso_interval));
+	print_sca(cmd->sca);
+	print_field("Anchor Update Buffer Time: %u us",
+					le16_to_cpu(cmd->anchor_update));
+	print_packing(cmd->packing);
+	print_framing(cmd->framing);
+	print_field("Number of CIS: %u", cmd->num_cis);
+
+	size -= sizeof(*cmd);
+
+	print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis),
+						print_cis_params_test_v2);
+}
+
+static void le_set_cig_params_test_v2_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_set_cig_params_v2 *rsp = data;
+
+	print_status(rsp->status);
+
+	if (size == 1)
+		return;
+
+	print_field("CIG ID: 0x%2.2x", rsp->cig_id);
+	print_field("Number of Handles: %u", rsp->num_handles);
+
+	size -= sizeof(*rsp);
+
+	print_list(rsp->handle, size, rsp->num_handles, sizeof(*rsp->handle),
+						print_cig_handle);
+}
+
+static void print_bis_v2(const struct bt_hci_bis_v2 *bis)
+{
+	print_usec_interval("SDU Interval", bis->sdu_interval);
+	print_field("Maximum SDU size: %u", le16_to_cpu(bis->sdu));
+	print_field("Maximum Latency: %u ms (0x%4.4x)",
+			le16_to_cpu(bis->latency), le16_to_cpu(bis->latency));
+	print_field("RTN: 0x%2.2x", bis->rtn);
+	print_le_phys("PHY", bis->phy);
+	print_packing(bis->packing);
+	print_framing(bis->framing);
+	print_field("Encryption: 0x%2.2x", bis->encryption);
+	print_hex_field("Broadcast Code", bis->bcode, 16);
+	print_rates("Coded Rates", 0x03, bis->coded_rates);
+	print_rates("HDT Rates", 0x05, le16_to_cpu(bis->hdt_rates));
+	print_prefer_mic_len(bis->mic_len);
+	print_packet_format(bis->format);
+}
+
+static void le_create_big_v2(uint16_t index, const void *data, uint8_t size)
+{
+	const struct bt_hci_cmd_le_create_big_v2 *cmd = data;
+
+	print_field("Handle: 0x%2.2x", cmd->handle);
+	print_field("Advertising Handle: 0x%2.2x", cmd->adv_handle);
+	print_field("Number of BIS: %u", cmd->num_bis);
+	print_bis_v2(&cmd->bis);
+}
+
+static void print_bis_test_v2(const void *data, int i)
+{
+	const struct bt_hci_bis_test_v2 *bis = data;
+
+	print_usec_interval("SDU Interval", bis->sdu_interval);
+	print_field("ISO Interval: %.2f ms (0x%4.4x)",
+				le16_to_cpu(bis->iso_interval) * 1.25,
+				le16_to_cpu(bis->iso_interval));
+	print_field("Number of Subevents: %u", bis->nse);
+	print_field("Maximum SDU: %u", bis->sdu);
+	print_field("Maximum PDU: %u", bis->pdu);
+	print_packing(bis->packing);
+	print_framing(bis->framing);
+	print_le_phy("PHY", bis->phy);
+	print_field("Burst Number: %u", bis->bn);
+	print_field("Immediate Repetition Count: %u", bis->irc);
+	print_field("Pre Transmission Offset: 0x%2.2x", bis->pto);
+	print_field("Encryption: 0x%2.2x", bis->encryption);
+	print_hex_field("Broadcast Code", bis->bcode, 16);
+	print_rates("Coded Rates", 0x03, bis->coded_rates);
+	print_rates("HDT Rates", 0x05, le16_to_cpu(bis->hdt_rates));
+	print_prefer_mic_len(bis->mic_len);
+	print_packet_format(bis->format);
+	print_field("Blocks per Payload: %u", bis->blocks);
+}
+
+static void le_create_big_test_v2(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_create_big_test_v2 *cmd = data;
+
+	print_field("BIG Handle: 0x%2.2x", cmd->big_handle);
+	print_field("Advertising Handle: 0x%2.2x", cmd->adv_handle);
+	print_field("Number of BIS: %u", cmd->num_bis);
+
+	size -= sizeof(*cmd);
+
+	print_list(cmd->bis, size, cmd->num_bis, sizeof(*cmd->bis),
+						print_bis_test_v2);
+}
+
+static void le_set_hdt_default_params(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_hdt_set_default_params *cmd = data;
+
+	print_prefer_mic_len(cmd->mic_len);
+	print_packet_format(cmd->format);
+	print_rates("ACL Rates", 0x05, le16_to_cpu(cmd->rates));
+}
+
+static void le_set_hdt_params_test(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_hdt_set_params_test *cmd = data;
+
+	print_handle(cmd->handle);
+	print_prefer_mic_len(cmd->mic_len);
+	print_packet_format(cmd->format);
+	print_field("Blocks per Payload: %u", cmd->blocks);
+	print_rates("TX Rates", 0x05, cmd->tx_rates);
+}
+
+static void le_set_hdt_params_test_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_hdt_set_params_test *rsp = data;
+
+	print_status(rsp->status);
+	print_handle(rsp->handle);
+}
+
+static void print_eks_debug_mode(uint8_t mode)
+{
+	const char *str;
+
+	switch (mode) {
+	case 0x00:
+		str = "Disable";
+		break;
+	case 0x01:
+		str = "Accept";
+		break;
+	case 0x02:
+		str = "Enable";
+		break;
+	default:
+		str = "Reserved";
+		break;
+	}
+
+	print_field("Debug Mode: %s (0x%2.2x)", str, mode);
+}
+
+static void le_read_eks_debug_mode_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_read_eks_debug_mode *rsp = data;
+
+	print_status(rsp->status);
+	print_eks_debug_mode(rsp->mode);
+}
+
+static void le_write_eks_debug_mode(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_cmd_le_write_eks_debug_mode *cmd = data;
+
+	print_eks_debug_mode(cmd->mode);
+}
+
+struct opcode_data {
+	uint16_t opcode;
+	int bit;
+	const char *str;
+	void (*cmd_func) (uint16_t index, const void *data, uint8_t size);
+	uint8_t cmd_size;
+	bool cmd_fixed;
+	void (*rsp_func) (uint16_t index, const void *data, uint8_t size);
+	uint8_t rsp_size;
+	bool rsp_fixed;
+};
+
+static const struct opcode_data opcode_table[] = {
+	{ 0x0000,  -1, "NOP" },
+
+	/* OGF 1 - Link Control */
+	{ 0x0401,   0, "Inquiry",
+				inquiry_cmd, 5, true },
+	{ 0x0402,   1, "Inquiry Cancel",
+				null_cmd, 0, true,
+				status_rsp, 1, true },
+	{ 0x0403,   2, "Periodic Inquiry Mode",
+				periodic_inquiry_cmd, 9, true,
+				status_rsp, 1, true },
+	{ 0x0404,   3, "Exit Periodic Inquiry Mode",
+				null_cmd, 0, true,
+				status_rsp, 1, true },
+	{ 0x0405,   4, "Create Connection",
+				create_conn_cmd, 13, true },
+	{ 0x0406,   5, "Disconnect",
+				disconnect_cmd, 3, true },
+	{ 0x0407,   6, "Add SCO Connection",
+				add_sco_conn_cmd, 4, true },
+	{ 0x0408,   7, "Create Connection Cancel",
+				create_conn_cancel_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x0409,   8, "Accept Connection Request",
+				accept_conn_request_cmd, 7, true },
+	{ 0x040a,   9, "Reject Connection Request",
+				reject_conn_request_cmd, 7, true },
+	{ 0x040b,  10, "Link Key Request Reply",
+				link_key_request_reply_cmd, 22, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x040c,  11, "Link Key Request Negative Reply",
+				link_key_request_neg_reply_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x040d,  12, "PIN Code Request Reply",
+				pin_code_request_reply_cmd, 23, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x040e,  13, "PIN Code Request Negative Reply",
+				pin_code_request_neg_reply_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x040f,  14, "Change Connection Packet Type",
+				change_conn_pkt_type_cmd, 4, true },
+	{ 0x0411,  15, "Authentication Requested",
+				auth_requested_cmd, 2, true },
+	{ 0x0413,  16, "Set Connection Encryption",
+				set_conn_encrypt_cmd, 3, true },
+	{ 0x0415,  17, "Change Connection Link Key",
+				change_conn_link_key_cmd, 2, true },
+	{ 0x0417,  18, "Temporary Link Key",
+				link_key_selection_cmd, 1, true },
+	{ 0x0419,  19, "Remote Name Request",
+				remote_name_request_cmd, 10, true },
+	{ 0x041a,  20, "Remote Name Request Cancel",
+				remote_name_request_cancel_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x041b,  21, "Read Remote Supported Features",
+				read_remote_features_cmd, 2, true },
+	{ 0x041c,  22, "Read Remote Extended Features",
+				read_remote_ext_features_cmd, 3, true },
+	{ 0x041d,  23, "Read Remote Version Information",
+				read_remote_version_cmd, 2, true },
+	{ 0x041f,  24, "Read Clock Offset",
+				read_clock_offset_cmd, 2, true },
+	{ 0x0420,  25, "Read LMP Handle",
+				read_lmp_handle_cmd, 2, true,
+				read_lmp_handle_rsp, 8, true },
+	{ 0x0428, 131, "Setup Synchronous Connection",
+				setup_sync_conn_cmd, 17, true },
+	{ 0x0429, 132, "Accept Synchronous Connection Request",
+				accept_sync_conn_request_cmd, 21, true },
+	{ 0x042a, 133, "Reject Synchronous Connection Request",
+				reject_sync_conn_request_cmd, 7, true },
+	{ 0x042b, 151, "IO Capability Request Reply",
+				io_capability_request_reply_cmd, 9, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x042c, 152, "User Confirmation Request Reply",
+				user_confirm_request_reply_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x042d, 153, "User Confirmation Request Neg Reply",
+				user_confirm_request_neg_reply_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x042e, 154, "User Passkey Request Reply",
+				user_passkey_request_reply_cmd, 10, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x042f, 155, "User Passkey Request Negative Reply",
+				user_passkey_request_neg_reply_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x0430, 156, "Remote OOB Data Request Reply",
+				remote_oob_data_request_reply_cmd, 38, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x0433, 159, "Remote OOB Data Request Neg Reply",
+				remote_oob_data_request_neg_reply_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x0434, 163, "IO Capability Request Negative Reply",
+				io_capability_request_neg_reply_cmd, 7, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x0435, 168, "Create Physical Link",
+				create_phy_link_cmd, 3, false },
+	{ 0x0436, 169, "Accept Physical Link",
+				accept_phy_link_cmd, 3, false },
+	{ 0x0437, 170, "Disconnect Physical Link",
+				disconn_phy_link_cmd, 2, true },
+	{ 0x0438, 171, "Create Logical Link",
+				create_logic_link_cmd, 33, true },
+	{ 0x0439, 172, "Accept Logical Link",
+				accept_logic_link_cmd, 33, true },
+	{ 0x043a, 173, "Disconnect Logical Link",
+				disconn_logic_link_cmd, 2, true },
+	{ 0x043b, 174, "Logical Link Cancel",
+				logic_link_cancel_cmd, 2, true,
+				logic_link_cancel_rsp, 3, true },
+	{ 0x043c, 175, "Flow Specification Modify",
+				flow_spec_modify_cmd, 34, true },
+	{ 0x043d, 235, "Enhanced Setup Synchronous Connection",
+				enhanced_setup_sync_conn_cmd, 59, true },
+	{ 0x043e, 236, "Enhanced Accept Synchronous Connection Request",
+				enhanced_accept_sync_conn_request_cmd, 63, true },
+	{ 0x043f, 246, "Truncated Page",
+				truncated_page_cmd, 9, true },
+	{ 0x0440, 247, "Truncated Page Cancel",
+				truncated_page_cancel_cmd, 6, true,
+				status_bdaddr_rsp, 7, true },
+	{ 0x0441, 248, "Set Connectionless Peripheral Broadcast",
+				set_peripheral_broadcast_cmd, 11, true,
+				set_peripheral_broadcast_rsp, 4, true },
+	{ 0x0442, 249, "Set Connectionless Peripheral Broadcast Receive",
+				set_peripheral_broadcast_receive_cmd, 34, true,
+				set_peripheral_broadcast_receive_rsp, 8, true },
+	{ 0x0443, 250, "Start Synchronization Train",
+				null_cmd, 0, true },
+	{ 0x0444, 251, "Receive Synchronization Train",
+				receive_sync_train_cmd, 12, true },
+	{ 0x0445, 257, "Remote OOB Extended Data Request Reply",
+				remote_oob_ext_data_request_reply_cmd, 70, true,
+				status_bdaddr_rsp, 7, true },
+
+	/* OGF 2 - Link Policy */
+	{ 0x0801,  33, "Hold Mode",
+				hold_mode_cmd, 6, true },
+	{ 0x0803,  34, "Sniff Mode",
+				sniff_mode_cmd, 10, true },
+	{ 0x0804,  35, "Exit Sniff Mode",
+				exit_sniff_mode_cmd, 2, true },
+	{ 0x0805,  36, "Park State",
+				park_state_cmd, 6, true },
+	{ 0x0806,  37, "Exit Park State",
+				exit_park_state_cmd, 2, true },
+	{ 0x0807,  38, "QoS Setup",
+				qos_setup_cmd, 20, true },
+	{ 0x0809,  39, "Role Discovery",
+				role_discovery_cmd, 2, true,
+				role_discovery_rsp, 4, true },
+	{ 0x080b,  40, "Switch Role",
+				switch_role_cmd, 7, true },
+	{ 0x080c,  41, "Read Link Policy Settings",
+				read_link_policy_cmd, 2, true,
+				read_link_policy_rsp, 5, true },
+	{ 0x080d,  42, "Write Link Policy Settings",
+				write_link_policy_cmd, 4, true,
+				write_link_policy_rsp, 3, true },
+	{ 0x080e,  43, "Read Default Link Policy Settings",
+				null_cmd, 0, true,
+				read_default_link_policy_rsp, 3, true },
+	{ 0x080f,  44, "Write Default Link Policy Settings",
+				write_default_link_policy_cmd, 2, true,
+				status_rsp, 1, true },
+	{ 0x0810,  45, "Flow Specification",
+				flow_spec_cmd, 21, true },
+	{ 0x0811, 140, "Sniff Subrating",
+				sniff_subrating_cmd, 8, true,
+				sniff_subrating_rsp, 3, true },
+
+	/* OGF 3 - Host Control */
+	{ 0x0c01,  46, "Set Event Mask",
+				set_event_mask_cmd, 8, true,
+				status_rsp, 1, true },
+	{ 0x0c03,  47, "Reset",
+				null_cmd, 0, true,
+				status_rsp, 1, true },
+	{ 0x0c05,  48, "Set Event Filter",
+				set_event_filter_cmd, 1, false,
+				status_rsp, 1, true },
+	{ 0x0c08,  49, "Flush",
+				flush_cmd, 2, true,
+				flush_rsp, 3, true },
+	{ 0x0c09,  50, "Read PIN Type",
+				null_cmd, 0, true,
+				read_pin_type_rsp, 2, true },
+	{ 0x0c0a,  51, "Write PIN Type",
+				write_pin_type_cmd, 1, true,
+				status_rsp, 1, true },
+	{ 0x0c0b,  52, "Create New Unit Key",
+				null_cmd, 0, true,
+				status_rsp, 1, true },
+	{ 0x0c0d,  53, "Read Stored Link Key",
+				read_stored_link_key_cmd, 7, true,
+				read_stored_link_key_rsp, 5, true },
+	{ 0x0c11,  54, "Write Stored Link Key",
+				write_stored_link_key_cmd, 1, false,
+				write_stored_link_key_rsp, 2, true },
+	{ 0x0c12,  55, "Delete Stored Link Key",
+				delete_stored_link_key_cmd, 7, true,
+				delete_stored_link_key_rsp, 3, true },
+	{ 0x0c13,  56, "Write Local Name",
+				write_local_name_cmd, 248, true,
+				status_rsp, 1, true },
+	{ 0x0c14,  57, "Read Local Name",
+				null_cmd, 0, true,
+				read_local_name_rsp, 249, true },
+	{ 0x0c15,  58, "Read Connection Accept Timeout",
+				null_cmd, 0, true,
 				read_conn_accept_timeout_rsp, 3, true },
 	{ 0x0c16,  59, "Write Connection Accept Timeout",
 				write_conn_accept_timeout_cmd, 2, true,
@@ -11432,6 +11987,87 @@ static const struct opcode_data opcode_table[] = {
 	{ 0x20a6, 395, "LE CS Write Cached Remote Supported Capabilities [v2]" },
 	{ 0x20a7, 396, "LE CS Set Security Requirements" },
 	{ 0x20a8, 397, "LE CS Set Default Security Requirements" },
+	{ BT_HCI_CMD_LE_WRITE_DEF_DATA_LEN_V2,
+			BT_HCI_BIT_LE_WRITE_DEF_DATA_LEN_V2,
+			"LE Write Suggested Default Data Length V2",
+			le_write_def_data_len_v2,
+			sizeof(struct bt_hci_cmd_le_write_def_data_len_v2),
+			true, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_READ_DEF_DATA_LEN_V2,
+			BT_HCI_BIT_LE_READ_DEF_DATA_LEN_V2,
+			"LE Read Suggested Default Data Length v2",
+			le_read_def_data_len_v2,
+			sizeof(struct bt_hci_cmd_le_read_def_data_len_v2),
+			true, le_read_def_data_len_v2_rsp,
+			sizeof(struct bt_hci_rsp_le_read_def_data_len_v2),
+			true },
+	{ BT_HCI_CMD_LE_ENABLE_ENCRYPT_V2, BT_HCI_BIT_LE_ENABLE_ENCRYPT_V2,
+				"LE Enable Encryption v2", le_enable_encrypt_v2,
+				sizeof(struct bt_hci_cmd_le_enable_encrypt_v2),
+				true, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_READ_MAX_DATA_LEN_V2,
+			BT_HCI_BIT_LE_READ_MAX_DATA_LEN_V2,
+			"LE Read Max Data Length v2", le_read_max_data_len_v2,
+			sizeof(struct bt_hci_cmd_le_read_data_len_v2),
+			true, le_read_max_data_len_v2_rsp,
+			sizeof(struct bt_hci_rsp_le_read_data_len_v2),
+			true },
+	{ BT_HCI_CMD_LE_SET_DATA_LEN_V2, BT_HCI_BIT_LE_SET_DATA_LEN_V2,
+			"LE Set Data Length v2", le_set_data_len_v2,
+			sizeof(struct bt_hci_cmd_le_set_data_len_v2),
+			true, le_set_data_len_v2_rsp,
+			sizeof(struct bt_hci_rsp_le_set_data_len_v2),
+			true },
+	{ BT_HCI_CMD_LE_SET_CIG_PARAMS_V2, BT_HCI_BIT_LE_SET_CIG_PARAMS_V2,
+			"LE Set Connected Isochronous Group Parameters v2",
+			le_set_cig_params_v2,
+			sizeof(struct bt_hci_cmd_le_set_cig_params_v2),
+			false, le_set_cig_params_v2_rsp,
+			sizeof(struct bt_hci_rsp_le_set_cig_params_v2),
+			false },
+	{ BT_HCI_CMD_LE_SET_CIG_PARAMS_TEST_V2,
+			BT_HCI_BIT_LE_SET_CIG_PARAMS_TEST_V2,
+			"LE Set Connected Isochronous Group Parameters Test v2",
+			le_set_cig_params_test_v2,
+			sizeof(struct bt_hci_cmd_le_set_cig_params_test_v2),
+			false, le_set_cig_params_test_v2_rsp,
+			sizeof(struct bt_hci_rsp_le_set_cig_params_v2),
+			false },
+	{ BT_HCI_CMD_LE_CREATE_BIG_V2, BT_HCI_BIT_LE_CREATE_BIG_V2,
+				"LE Create Broadcast Isochronous Group v2",
+				le_create_big_v2,
+				sizeof(struct bt_hci_cmd_le_create_big_v2), true,
+				status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_CREATE_BIG_TEST_V2, BT_HCI_BIT_LE_CREATE_BIG_TEST_V2,
+				"LE Create Broadcast Isochronous Group Test v2",
+				le_create_big_test_v2,
+				sizeof(struct bt_hci_cmd_le_create_big_test_v2),
+				false, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_SET_HDT_DEFAULT_PARAMS,
+			BT_HCI_BIT_LE_SET_HDT_DEFAULT_PARAMS,
+			"LE Set HDT Default Parameters",
+			le_set_hdt_default_params,
+			sizeof(struct bt_hci_cmd_le_hdt_set_default_params),
+			true, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_SET_HDT_PARAMS_TEST, BT_HCI_BIT_LE_SET_HDT_PARAMS_TEST,
+			"LE Set HDT Parameters Test",
+			le_set_hdt_params_test,
+			sizeof(struct bt_hci_cmd_le_hdt_set_params_test), true,
+			le_set_hdt_params_test_rsp,
+			sizeof(struct bt_hci_rsp_le_hdt_set_params_test),
+			true },
+	{ BT_HCI_CMD_LE_READ_EKS_DEBUG_MODE, BT_HCI_BIT_LE_READ_EKS_DEBUG_MODE,
+			"LE Read Encryption Key Schedule Debug Mode",
+			null_cmd, 0, true,
+			le_read_eks_debug_mode_rsp,
+			sizeof(struct bt_hci_rsp_le_read_eks_debug_mode),
+			true },
+	{ BT_HCI_CMD_LE_WRITE_EKS_DEBUG_MODE,
+			BT_HCI_BIT_LE_WRITE_EKS_DEBUG_MODE,
+			"LE Write Encryption Key Schedule Debug Mode",
+			le_write_eks_debug_mode,
+			sizeof(struct bt_hci_cmd_le_write_eks_debug_mode),
+			true },
 	{ }
 };
 
@@ -14179,6 +14815,197 @@ static void le_conn_rate_change_evt(struct timeval *tv, uint16_t index,
 					le16_to_cpu(evt->supv_timeout));
 }
 
+static void print_mic_len(uint8_t value)
+{
+	const char *str;
+
+	switch (value) {
+	case 0x00:
+		str = "32 bits";
+		break;
+	case 0x01:
+		str = "64 bits";
+		break;
+	case 0x02:
+		str = "128 bits";
+		break;
+	default:
+		str = "RFU";
+	}
+
+	print_field("MIC length: %s (0x%2.2x)", str, value);
+}
+
+static void print_eks_mode(uint8_t mode)
+{
+	const char *str;
+
+	switch (mode) {
+	case 0x00:
+		str = "off";
+		break;
+	case 0x01:
+		str = "AES-CCM";
+		break;
+	case 0x02:
+		str = "opportunistic ASE-CCM";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
+
+	print_field("Key Schedule: %s (%d)", str, mode);
+}
+
+static void encrypt_change_v3_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
+{
+	const struct bt_hci_evt_encrypt_change_v3 *evt = data;
+
+	print_status(evt->status);
+	print_handle(evt->handle);
+	print_encr_mode_change(evt->mode, evt->handle);
+	print_field("Key size: %u", evt->key_size);
+	print_mic_len(evt->mic_len);
+	print_eks_mode(evt->eks_mode);
+	print_field("EKS Debug: %s (0x%2.2x)",
+		    evt->eks_debug ? "Enabled" : "Disabled", evt->eks_debug);
+}
+
+static void encrypt_key_refresh_complete_v2_evt(struct timeval *tv,
+						uint16_t index,
+						const void *data, uint8_t size)
+{
+	const struct bt_hci_evt_encrypt_key_refresh_complete_v2 *evt = data;
+
+	print_status(evt->status);
+	print_handle(evt->handle);
+	print_mic_len(evt->mic_len);
+	print_eks_mode(evt->eks_mode);
+	print_field("EKS Debug: %s (0x%2.2x)",
+		    evt->eks_debug ? "Enabled" : "Disabled", evt->eks_debug);
+}
+
+static void le_data_len_change_v2_evt(struct timeval *tv, uint16_t index,
+						const void *data, uint8_t size)
+{
+	const struct bt_hci_evt_le_data_length_change_v2 *evt = data;
+
+	print_handle(evt->handle);
+	print_field("Max TX octets: %d", le16_to_cpu(evt->max_tx_len));
+	print_field("Max TX time: %d", le16_to_cpu(evt->max_tx_time));
+	print_field("Max RX octets: %d", le16_to_cpu(evt->max_rx_len));
+	print_field("Max RX time: %d", le16_to_cpu(evt->max_rx_time));
+	print_phys(evt->phys);
+}
+
+static void print_cis_encryption(uint8_t encryption)
+{
+	const char *str;
+
+	switch (encryption) {
+	case 0x00:
+		str = "Disabled";
+		break;
+	case 0x01:
+		str = "Enabled";
+		break;
+	case 0x02:
+		str = "Key Schedule";
+		break;
+	case 0x03:
+		str = "Opportunistic and Key Schedule";
+		break;
+	default:
+		str = "RFU";
+		break;
+	}
+
+	print_field("Encryption: %s (%d)", str, encryption);
+}
+
+static void le_cis_estabilished_v3_evt(struct timeval *tv, uint16_t index,
+						const void *data, uint8_t size)
+{
+	const struct bt_hci_evt_le_cis_established_v3 *evt = data;
+
+	print_status(evt->status);
+	print_field("Connection Handle: %d", le16_to_cpu(evt->conn_handle));
+	print_usec_interval("CIG Synchronization Delay", evt->cig_sync_delay);
+	print_usec_interval("CIS Synchronization Delay", evt->cis_sync_delay);
+	print_usec_interval("Central to Peripheral Latency", evt->c_latency);
+	print_usec_interval("Peripheral to Central Latency", evt->p_latency);
+	print_le_phy("Central to Peripheral PHY", evt->c_phy);
+	print_le_phy("Peripheral to Central PHY", evt->p_phy);
+	print_field("Number of Subevents: %u", evt->nse);
+	print_field("Central to Peripheral Burst Number: %u", evt->c_bn);
+	print_field("Peripheral to Central Burst Number: %u", evt->p_bn);
+	print_field("Central to Peripheral Flush Timeout: %u", evt->c_ft);
+	print_field("Peripheral to Central Flush Timeout: %u", evt->p_ft);
+	print_field("Central to Peripheral MTU: %u", le16_to_cpu(evt->c_mtu));
+	print_field("Peripheral to Central MTU: %u", le16_to_cpu(evt->p_mtu));
+	print_slot_125("ISO Interval", evt->interval);
+	print_usec_interval("ISO Sub-Interval", evt->sub_interval);
+	print_field("Central to Peripheral SDU: %u", le16_to_cpu(evt->c_sdu));
+	print_field("Peripheral to Central SDU: %u", le16_to_cpu(evt->p_sdu));
+	print_usec_interval("Central to Peripheral SDU Interval",
+				evt->c_sdu_interval);
+	print_usec_interval("Peripheral to Central SDU Interval",
+				evt->p_sdu_interval);
+	print_framing(evt->framing);
+	print_rates("Central to Peripheral Rates", evt->c_phy,
+			le16_to_cpu(evt->c_rates));
+	print_rates("Peripheral to Central Rates", evt->p_phy,
+			le16_to_cpu(evt->p_rates));
+	print_field("Config ID: %u", evt->config_id);
+	print_field("Group ID: %u", evt->group_id);
+	print_cis_encryption(evt->encryption);
+	print_mic_len(evt->mic_len);
+
+	if (!evt->status)
+		assign_handle(index, le16_to_cpu(evt->conn_handle), 0x05,
+					NULL, BDADDR_LE_PUBLIC);
+}
+
+static void le_big_complete_v2_evt(struct timeval *tv, uint16_t index,
+						const void *data, uint8_t size)
+{
+	const struct bt_hci_evt_le_big_complete_v2 *evt = data;
+
+	print_status(evt->status);
+	print_field("Handle: 0x%2.2x", evt->handle);
+	print_usec_interval("BIG Synchronization Delay", evt->sync_delay);
+	print_usec_interval("Transport Latency", evt->latency);
+	print_le_phy("PHY", evt->phy);
+	print_field("NSE: %u", evt->nse);
+	print_field("BN: %u", evt->bn);
+	print_field("PTO: %u", evt->pto);
+	print_field("IRC: %u", evt->irc);
+	print_field("Maximum PDU: %u", evt->max_pdu);
+	print_slot_125("ISO Interval", evt->interval);
+	print_rates("Rates", evt->phy, le16_to_cpu(evt->rates));
+	print_field("Encryption: %s (0x%2.2x)",
+			evt->encryption ? "Encrypted" : "Unencrypted",
+			evt->encryption);
+	print_mic_len(evt->mic_len);
+
+	/* Only the handles the event has room for */
+	size -= sizeof(*evt);
+
+	print_list(evt->bis_handle, size, evt->num_bis,
+				sizeof(*evt->bis_handle), print_bis_handle);
+
+	if (!evt->status) {
+		int i;
+
+		for (i = 0; i < evt->num_bis &&
+				i < (int) (size / sizeof(*evt->bis_handle)); i++)
+			assign_handle(index, le16_to_cpu(evt->bis_handle[i]),
+					0x05, NULL, BDADDR_LE_PUBLIC);
+	}
+}
+
 struct subevent_data {
 	uint8_t subevent;
 	const char *str;
@@ -14353,6 +15180,18 @@ static const struct subevent_data le_meta_event_table[] = {
 		"LE Connection Rate Change",
 		le_conn_rate_change_evt,
 		sizeof(struct bt_hci_evt_le_conn_rate_change) },
+	{ BT_HCI_EVT_LE_DATA_LENGTH_CHANGE_V2,
+		"LE Data Length Change v2",
+		le_data_len_change_v2_evt,
+		sizeof(struct bt_hci_evt_le_data_length_change_v2) },
+	{ BT_HCI_EVT_LE_CIS_ESTABLISHED_V3,
+		"LE Connected Isochronous Stream Established v3",
+		le_cis_estabilished_v3_evt,
+		sizeof(struct bt_hci_evt_le_cis_established_v3) },
+	{ BT_HCI_EVT_LE_BIG_COMPLETE_V2,
+		"LE Broadcast Isochronous Group Complete v2",
+		le_big_complete_v2_evt,
+		sizeof(struct bt_hci_evt_le_big_complete_v2) },
 	{ }
 };
 
@@ -14583,8 +15422,17 @@ static const struct event_data event_table[] = {
 	{ 0x57, "Authenticated Payload Timeout Expired",
 				auth_payload_timeout_expired_evt, 2, true },
 	{ 0x58, "SAM Status Change" },
+
 	{ 0x59, "Encryption Change v2",
 				encrypt_change_evt_v2, 5, true },
+	{ BT_HCI_EVT_ENCRYPT_CHANGE_V3, "Encrypt Change V3",
+				encrypt_change_v3_evt,
+				sizeof(struct bt_hci_evt_encrypt_change_v3),
+				true },
+	{ BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE_V2,
+		"Encrypt Key Refresh Complete v2",
+		encrypt_key_refresh_complete_v2_evt,
+		sizeof(struct bt_hci_evt_encrypt_key_refresh_complete_v2) },
 	{ 0xfe, "Testing" },
 	{ 0xff, "Vendor", evt_vendor, 0, false },
 	{ }
@@ -15610,6 +16458,7 @@ static const struct bitfield_data mgmt_settings_table[] = {
 	{ 23, "PAST Sender"		},
 	{ 24, "PAST Receiver"		},
 	{ 25, "Shorter Connection Interval"	},
+	{ 26, "HDT"			},
 	{}
 };
 
@@ -17104,6 +17953,10 @@ static const struct {
 	{0x001e, "LE No Filter Scanning Duration for adv monitoring"  },
 	{0x001f, "LE Enable Interleave Scan for adv monitoring"       },
 	{0x0020, "BR/EDR Connection Idle Timeout"                     },
+	{0x0021, "LE HDT Default MIC Length"                          },
+	{0x0022, "LE HDT Default Packet Format"                      },
+	{0x0023, "LE HDT Default Rates"                              },
+	{0x0024, "LE Opportunistic Encryption"                        },
 	{ }
 };
 
-- 
2.56.0


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

* [PATCH BlueZ v2 3/9] monitor: Add LL decoding for HDT
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 1/9] lib: Add HDT definitions Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 2/9] monitor: Add HCI decoding for HDT Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 4/9] emulator: Add HDT support to btdev Luiz Augusto von Dentz
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Decode the LL_ENC_ECDH_REQ/RSP, LL_HDT_CONFIG_REQ/RSP and
LL_HDT_LQF_REPORTING_IND Link Layer PDUs introduced by HDT and EKS.
---
 monitor/ll.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 209 insertions(+), 6 deletions(-)

diff --git a/monitor/ll.c b/monitor/ll.c
index 6c0f67b5dcae..ba625adac46c 100644
--- a/monitor/ll.c
+++ b/monitor/ll.c
@@ -537,7 +537,9 @@ static void length_req_rsp(const void *data, uint8_t size)
 static const struct bitfield_data le_phys[] = {
 	{  0, "LE 1M"	},
 	{  1, "LE 2M"	},
-	{  2, "LE Coded"},
+	{  2, "LE Coded S=8"},
+	{  3, "LE Coded S=2"},
+	{  4, "LE HDT"	},
 	{ }
 };
 
@@ -558,6 +560,15 @@ static void phy_req_rsp(const void *data, uint8_t size)
 	if (mask)
 		print_text(COLOR_UNKNOWN_OPTIONS_BIT, "  Reserved"
 							" (0x%2.2x)", mask);
+
+	/* [v2] */
+	if (size >= sizeof(*pdu) + sizeof(struct bt_ll_phy_v2)) {
+		const struct bt_ll_phy_v2 *v2 = data + sizeof(*pdu);
+
+		print_field("Refresh: %u", v2->flags & 0x01);
+		print_field("MIC Length: %s (%u)", v2->flags & 0x02 ?
+				"64 bits" : "128 bits", (v2->flags >> 1) & 0x01);
+	}
 }
 
 static void phy_update_ind(const void *data, uint8_t size)
@@ -580,6 +591,19 @@ static void phy_update_ind(const void *data, uint8_t size)
 							" (0x%2.2x)", mask);
 
 	print_field("Instant: 0x%4.4x", pdu->instant);
+
+	/* [v2] */
+	if (size >= sizeof(*pdu) + sizeof(struct bt_ll_phy_update_ind_v2)) {
+		const struct bt_ll_phy_update_ind_v2 *v2 = data + sizeof(*pdu);
+
+		print_field("Address: %2.2x%2.2x%2.2x%2.2x%2.2x",
+				v2->address[4], v2->address[3],
+				v2->address[2], v2->address[1],
+				v2->address[0]);
+		print_field("Refresh: %u", v2->flags & 0x01);
+		print_field("MIC Length: %s (%u)", v2->flags & 0x02 ?
+				"64 bits" : "128 bits", (v2->flags >> 1) & 0x01);
+	}
 }
 
 static void min_used_channels(const void *data, uint8_t size)
@@ -648,6 +672,41 @@ static void clock_acc_req_rsp(const void *data, uint8_t size)
 	print_field("SCA: 0x%2.2x", pdu->sca);
 }
 
+static const struct bitfield_data coded_rates[] = {
+	{ 0, "CODED S=8" },
+	{ 1, "CODED S=2" },
+	{ }
+};
+
+static const struct bitfield_data hdt_rates[] = {
+	{ 0, "HDT 2M" },
+	{ 1, "HDT 3M" },
+	{ 2, "HDT 4M" },
+	{ 3, "HDT 6M" },
+	{ 4, "HDT 7.5M" },
+	{ }
+};
+
+/* The rates are those of the PHY set in phys, as defined in Table 2.24 */
+static void print_rates(const char *prefix, uint8_t phys, uint16_t rates)
+{
+	const struct bitfield_data *fields = NULL;
+
+	if (phys & BIT(4))
+		fields = hdt_rates;
+	else if (phys & BIT(2))
+		fields = coded_rates;
+
+	print_field("%s: 0x%4.4x", prefix, rates);
+
+	if (fields) {
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)
+			print_text(COLOR_UNKNOWN_OPTIONS_BIT, "  Reserved"
+							" (0x%4.4x)", mask);
+	}
+}
+
 static void cis_req(const void *data, uint8_t size)
 {
 	const struct bt_ll_cis_req *cmd = data;
@@ -699,6 +758,25 @@ static void cis_req(const void *data, uint8_t size)
 	print_field("CIS Offset Maximum: 0x%6.6x", le32_to_cpu(interval));
 
 	print_field("Connection Event Count: %u", cmd->conn_event_count);
+
+	/* [v2] */
+	if (size >= sizeof(*cmd) + sizeof(struct bt_ll_cis_req_v2)) {
+		const struct bt_ll_cis_req_v2 *v2 = data + sizeof(*cmd);
+
+		print_rates("Central to Peripheral Rates", cmd->c_phys,
+						le16_to_cpu(v2->c_rates));
+		print_rates("Peripheral To Central Rates", cmd->p_phys,
+						le16_to_cpu(v2->p_rates));
+		print_field("Config ID: %u", v2->config_id);
+		print_field("TL Group ID: %u", v2->tl_group_id & 0x1f);
+		print_field("Central to Peripheral Payload Window Size: %u",
+						v2->flags & 0x03);
+		print_field("Peripheral to Central Payload Window Size: %u",
+						(v2->flags >> 2) & 0x03);
+		print_field("MIC Length: %s (%u)", v2->flags & 0x10 ?
+				"64 bits" : "128 bits", (v2->flags >> 4) & 0x01);
+		print_field("SE Length: %u us", get_le24(v2->se_length));
+	}
 }
 
 static void cis_rsp(const void *data, uint8_t size)
@@ -730,6 +808,13 @@ static void cis_ind(const void *data, uint8_t size)
 	print_field("CIS Synchronization Delay: %u us",
 					le32_to_cpu(interval));
 	print_field("Connection Event Count: %u", ind->conn_event_count);
+
+	/* [v2] */
+	if (size >= sizeof(*ind) + sizeof(struct bt_ll_cis_ind_v2)) {
+		const struct bt_ll_cis_ind_v2 *v2 = data + sizeof(*ind);
+
+		print_field("PCA-H: 0x%2.2x", v2->pca_h);
+	}
 }
 
 static void cis_term_ind(const void *data, uint8_t size)
@@ -759,6 +844,107 @@ static void feature_ext_rsp(const void *data, uint8_t size)
 	packet_print_features_ext_ll(rsp->page, rsp->features);
 }
 
+static const struct bitfield_data lqf_transports[] = {
+	{ 0, "ACL" },
+	{ 1, "CIS" },
+	{ }
+};
+
+static void hdt_lqf_ind(const void *data, uint8_t size)
+{
+	const struct bt_ll_hdt_lqf_ind *pdu = data;
+	uint8_t mask;
+
+	print_field("Transport: 0x%2.2x", pdu->transport);
+
+	mask = print_bitfield(2, pdu->transport, lqf_transports);
+	if (mask)
+		print_text(COLOR_UNKNOWN_OPTIONS_BIT, "  Reserved"
+							" (0x%2.2x)", mask);
+}
+
+static void hdt_config_req(const void *data, uint8_t size)
+{
+	const struct bt_ll_hdt_config_req *pdu = data;
+
+	print_field("ACL RX Payload Windows Size: %u",
+			pdu->wincfg & 0x03);
+	print_field("Max CIS TX Windows Size: %u",
+			(pdu->wincfg >> 2) & 0x03);
+	print_field("Max CIS RX Windows Size: %u",
+			(pdu->wincfg >> 4) & 0x03);
+	print_rates("ACL RX Rates", BIT(4), le16_to_cpu(pdu->acl_rx_rates));
+	print_field("Max ACL RX Packet Size: %u",
+					le16_to_cpu(pdu->acl_rx_mtu));
+}
+
+static void hdt_config_rsp(const void *data, uint8_t size)
+{
+	const struct bt_ll_hdt_config_rsp *pdu = data;
+
+	print_field("ACL RX Payload Windows Size: %u",
+			pdu->wincfg & 0x03);
+	print_field("Max CIS TX Windows Size: %u",
+			(pdu->wincfg >> 2) & 0x03);
+	print_field("Max CIS RX Windows Size: %u",
+			(pdu->wincfg >> 4) & 0x03);
+	print_rates("ACL RX Rates", BIT(4), le16_to_cpu(pdu->acl_rx_rates));
+	print_field("Max ACL RX Packet Size: %u",
+					le16_to_cpu(pdu->acl_rx_mtu));
+}
+
+static const struct bitfield_data ecdh_flags[] = {
+	{ 0, "Allow 64-bit MIC length" },
+	{ 1, "Opportunistic encryption" },
+	{ }
+};
+
+static void print_key_type(const char *str, uint8_t type)
+{
+	switch (type) {
+	case 0x00:
+		print_field("%s: Public key P-256 (0x00)", str);
+		break;
+	default:
+		print_field("%s: Reserved (0x%2.2x)", str, type);
+		break;
+	}
+}
+
+static void enc_ecdh_req(const void *data, uint8_t size)
+{
+	const struct bt_ll_enc_ecdh_req *cmd = data;
+	uint8_t mask;
+
+	print_field("Flags: 0x%2.2x", cmd->flags);
+
+	mask = print_bitfield(2, cmd->flags, ecdh_flags);
+	if (mask)
+		print_text(COLOR_UNKNOWN_OPTIONS_BIT, "  Reserved"
+							" (0x%2.2x)", mask);
+
+	print_hex_field("Rand", cmd->rand, 16);
+	print_key_type("Key Type", cmd->key_type);
+	print_hex_field("Public Key", cmd->pubkey, 64);
+}
+
+static void enc_ecdh_rsp(const void *data, uint8_t size)
+{
+	const struct bt_ll_enc_ecdh_rsp *rsp = data;
+	uint8_t mask;
+
+	print_field("Flags: 0x%2.2x", rsp->flags);
+
+	mask = print_bitfield(2, rsp->flags, ecdh_flags);
+	if (mask)
+		print_text(COLOR_UNKNOWN_OPTIONS_BIT, "  Reserved"
+							" (0x%2.2x)", mask);
+
+	print_hex_field("Rand", rsp->rand, 16);
+	print_key_type("Key Type", rsp->key_type);
+	print_hex_field("Public Key", rsp->pubkey, 64);
+}
+
 struct llcp_data {
 	uint8_t opcode;
 	const char *str;
@@ -767,6 +953,12 @@ struct llcp_data {
 	bool fixed;
 };
 
+#define LLCP_OP_VL(_op, _str, _func, _type) \
+	{ _op, _str, _func, sizeof(_type), false }
+
+#define LLCP_OP(_op, _str, _func, _type) \
+	{ _op, _str, _func, sizeof(_type), true }
+
 static const struct llcp_data llcp_table[] = {
 	{ 0x00, "LL_CONNECTION_UPDATE_REQ", conn_update_req,   11, true },
 	{ 0x01, "LL_CHANNEL_MAP_REQ",       channel_map_req,    7, true },
@@ -790,9 +982,9 @@ static const struct llcp_data llcp_table[] = {
 	{ 0x13, "LL_PING_RSP",              null_pdu,           0, true },
 	{ 0x14, "LL_LENGTH_REQ",            length_req_rsp,     8, true },
 	{ 0x15, "LL_LENGTH_RSP",            length_req_rsp,     8, true },
-	{ 0x16, "LL_PHY_REQ",               phy_req_rsp,        2, true },
-	{ 0x17, "LL_PHY_RSP",               phy_req_rsp,        2, true },
-	{ 0x18, "LL_PHY_UPDATE_IND",        phy_update_ind,     4, true },
+	{ 0x16, "LL_PHY_REQ",               phy_req_rsp,        2, false },
+	{ 0x17, "LL_PHY_RSP",               phy_req_rsp,        2, false },
+	{ 0x18, "LL_PHY_UPDATE_IND",        phy_update_ind,     4, false },
 	{ 0x19, "LL_MIN_USED_CHANNELS_IND", min_used_channels,  2, true },
 	{ 0x1a, "LL_CTE_REQ",               cte_req,            1, true },
 	{ 0x1b, "LL_CTE_RSP",               null_pdu,           0, true },
@@ -800,11 +992,11 @@ static const struct llcp_data llcp_table[] = {
 	{ 0x1d, "LL_CLOCK_ACCURACY_REQ",    clock_acc_req_rsp,  1, true },
 	{ 0x1e, "LL_CLOCK_ACCURACY_RSP",    clock_acc_req_rsp,  1, true },
 	{ BT_LL_CIS_REQ, "LL_CIS_REQ",      cis_req,
-					sizeof(struct bt_ll_cis_req), true },
+					sizeof(struct bt_ll_cis_req), false },
 	{ BT_LL_CIS_RSP, "LL_CIS_RSP",      cis_rsp,
 					sizeof(struct bt_ll_cis_rsp), true },
 	{ BT_LL_CIS_IND, "LL_CIS_IND",      cis_ind,
-					sizeof(struct bt_ll_cis_ind), true },
+					sizeof(struct bt_ll_cis_ind), false },
 	{ BT_LL_CIS_TERMINATE_IND, "LL_CIS_TERMINATE_IND", cis_term_ind,
 					sizeof(struct bt_ll_cis_term_ind),
 					true },
@@ -814,6 +1006,17 @@ static const struct llcp_data llcp_table[] = {
 	{ BT_LL_CIS_RSP, "LL_FEATURE_EXT_RSP", feature_ext_rsp,
 					sizeof(struct bt_ll_feature_ext_rsp),
 					true },
+	/* HDT LLCP commands */
+	LLCP_OP(BT_LL_HDT_LQF_REPORTING_IND, "LL_HDT_LQF_REPORTING_IND",
+					hdt_lqf_ind, struct bt_ll_hdt_lqf_ind),
+	LLCP_OP(BT_LL_HDT_CONFIG_REQ, "LL_HDT_CONFIG_REQ", hdt_config_req,
+					struct bt_ll_hdt_config_req),
+	LLCP_OP(BT_LL_HDT_CONFIG_RSP, "LL_HDT_CONFIG_RSP", hdt_config_rsp,
+					struct bt_ll_hdt_config_rsp),
+	LLCP_OP(BT_LL_ENC_ECDH_REQ, "LL_ENC_ECDH_REQ", enc_ecdh_req,
+					struct bt_ll_enc_ecdh_req),
+	LLCP_OP(BT_LL_ENC_ECDH_RSP, "LL_ENC_ECDH_RSP", enc_ecdh_rsp,
+					struct bt_ll_enc_ecdh_rsp),
 	{ }
 };
 
-- 
2.56.0


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

* [PATCH BlueZ v2 4/9] emulator: Add HDT support to btdev
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2026-11-04 18:36 ` [PATCH BlueZ v2 3/9] monitor: Add LL " Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 5/9] emulator: Add HDT support to bthost Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add a Bluetooth 7.0 controller type, BTDEV_TYPE_BREDRLE70, which
advertises the HDT and EKS feature bits and supported commands and
implements the HDT commands and events: LE Enable Encryption v2 with
MIC length negotiation, Read/Write Suggested Default Data Length v2,
Read Maximum Data Length v2, Set Data Length v2, Set CIG Parameters v2,
Create BIG v2, Set HDT Default Parameters, CIS Established v3, Create BIG
Complete v2 and the EKS Opportunistic Encryption host feature. Make it
the default for btvirt.

Assisted-by: OpenCode:claude-opus-5
---
 emulator/btdev.c  | 884 ++++++++++++++++++++++++++++++++++++++++++----
 emulator/btdev.h  |   1 +
 emulator/hciemu.c |   3 +
 emulator/hciemu.h |   1 +
 emulator/main.c   |   5 +-
 5 files changed, 825 insertions(+), 69 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 7a8d8a4645f6..7c1e20cc6ea4 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -84,10 +84,14 @@ struct hook {
 struct btdev_conn {
 	uint16_t handle;
 	uint8_t  type;
+	uint8_t  tx_phy;
+	uint8_t  rx_phy;
+	uint8_t  mic_len;
 	uint8_t  past_mode;
 	struct btdev *dev;
 	struct btdev_conn *link;
 	struct queue *links;
+	size_t data_len;
 	void *data;
 };
 
@@ -143,7 +147,11 @@ struct le_big {
 
 struct le_cig {
 	struct bt_hci_cmd_le_set_cig_params params;
-	struct bt_hci_cis_params cis[CIS_SIZE];
+	union {
+		struct bt_hci_cis_params cis_v1[CIS_SIZE];
+		struct bt_hci_cis_params_v2 cis_v2[CIS_SIZE];
+	};
+	uint8_t version;
 	bool activated;
 } __attribute__ ((packed));
 
@@ -258,8 +266,13 @@ struct btdev {
 	uint8_t  le_pa_data_len;
 	uint8_t  le_pa_data[MAX_PA_DATA_LEN];
 	uint8_t  le_ltk[16];
+	uint8_t  hdt_def_mic_len;
+	uint8_t  hdt_def_format;
+	uint16_t hdt_def_rates;
 	struct le_cig le_cig[CIG_SIZE];
 	uint8_t  le_iso_path[2];
+	uint8_t  le_def_tx_phys;
+	uint8_t  le_def_rx_phys;
 
 	uint8_t  le_rl_enable;
 
@@ -1263,7 +1276,7 @@ static struct btdev_conn *conn_add_cis(struct btdev_conn *acl, uint16_t handle)
 }
 
 static struct btdev_conn *conn_add_bis(struct btdev *dev, uint16_t handle,
-						const struct bt_hci_bis *bis)
+						const void *bis, size_t len)
 {
 	struct btdev_conn *conn;
 
@@ -1271,7 +1284,8 @@ static struct btdev_conn *conn_add_bis(struct btdev *dev, uint16_t handle,
 	if (!conn)
 		return conn;
 
-	conn->data = util_memdup(bis, sizeof(*bis));
+	conn->data_len = len;
+	conn->data = util_memdup(bis, len);
 
 	return conn;
 }
@@ -1309,7 +1323,7 @@ static struct btdev_conn *conn_link_bis(struct btdev *dev, struct btdev *remote,
 	if (!bis)
 		return NULL;
 
-	conn = conn_add_bis(dev, BIS_HANDLE, bis->data);
+	conn = conn_add_bis(dev, BIS_HANDLE, bis->data, bis->data_len);
 	if (!conn)
 		return NULL;
 
@@ -2057,14 +2071,50 @@ static int cmd_set_conn_encrypt(struct btdev *dev, const void *data,
 	return 0;
 }
 
+static void encrypt_change_v3(struct btdev_conn *conn, uint8_t mode,
+				uint8_t eks_mode, uint8_t status)
+{
+	struct bt_hci_evt_encrypt_change_v3 ev;
+
+	if (!conn)
+		return;
+
+	memset(&ev, 0, sizeof(ev));
+
+	ev.status = status;
+	ev.handle = cpu_to_le16(conn->handle);
+	ev.mode = mode;
+
+	switch (eks_mode) {
+	case 0x00: /* EKS disabled */
+	case 0x01: /* EKS enabled */
+		ev.key_size = 16;
+		break;
+	case 0x02: /* EKS opportunistic */
+		ev.key_size = 0;
+		break;
+	}
+
+	ev.eks_mode = eks_mode;
+	ev.mic_len = conn->mic_len;
+
+	send_event(conn->dev, BT_HCI_EVT_ENCRYPT_CHANGE_V3, &ev, sizeof(ev));
+}
+
 static void encrypt_change(struct btdev_conn *conn, uint8_t mode,
-					uint8_t status)
+				uint8_t eks_mode, uint8_t status)
 {
 	struct bt_hci_evt_encrypt_change ev;
 
 	if (!conn)
 		return;
 
+	/* Check if BT_HCI_EVT_ENCRYPT_CHANGE_V3 has been enabled in the event
+	 * mask page 2.
+	 */
+	if (conn->dev->event_mask_page2[3] & BIT(2))
+		return encrypt_change_v3(conn, mode, eks_mode, status);
+
 	memset(&ev, 0, sizeof(ev));
 
 	ev.status = status;
@@ -2094,8 +2144,8 @@ static int cmd_set_conn_encrypt_complete(struct btdev *dev, const void *data,
 	else
 		mode = 0x01;
 
-	encrypt_change(conn, mode, BT_HCI_ERR_SUCCESS);
-	encrypt_change(conn->link, mode, BT_HCI_ERR_SUCCESS);
+	encrypt_change(conn, mode, 0x00, BT_HCI_ERR_SUCCESS);
+	encrypt_change(conn->link, mode, 0x00, BT_HCI_ERR_SUCCESS);
 
 	return 0;
 }
@@ -4874,8 +4924,11 @@ static int cmd_ltk_reply(struct btdev *dev, const void *data, uint8_t len)
 		mode = 0x01;
 	}
 
-	encrypt_change(conn, mode, status);
-	encrypt_change(conn->link, mode, status);
+	/* Pass eks_mode as 0x01 for EKS enabled since only in case of V3 being
+	 * enabled it will get used.
+	 */
+	encrypt_change(conn, mode, 0x01, status);
+	encrypt_change(conn->link, mode, 0x01, status);
 
 	return 0;
 }
@@ -4900,7 +4953,7 @@ static int cmd_ltk_neg_reply(struct btdev *dev, const void *data, uint8_t len)
 	rp.status = BT_HCI_ERR_SUCCESS;
 	cmd_complete(dev, BT_HCI_CMD_LE_LTK_REQ_NEG_REPLY, &rp, sizeof(rp));
 
-	encrypt_change(conn->link, 0x00, BT_HCI_ERR_PIN_OR_KEY_MISSING);
+	encrypt_change(conn->link, 0x00, 0x00, BT_HCI_ERR_PIN_OR_KEY_MISSING);
 
 	return 0;
 }
@@ -5000,6 +5053,34 @@ static int cmd_conn_param_neg_reply_complete(struct btdev *dev,
 	return 0;
 }
 
+static int cmd_le_read_def_data_len(struct btdev *dev, const void *data,
+						uint8_t len)
+{
+	struct bt_hci_rsp_le_read_default_data_length rsp;
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	rsp.status = BT_HCI_ERR_SUCCESS;
+	rsp.tx_len = cpu_to_le16(0x001b);
+	rsp.tx_time = cpu_to_le16(0x0148);
+
+	cmd_complete(dev, BT_HCI_CMD_LE_READ_DEFAULT_DATA_LENGTH, &rsp,
+						sizeof(rsp));
+
+	return 0;
+}
+
+static int cmd_le_write_def_data_len(struct btdev *dev, const void *data,
+						uint8_t len)
+{
+	uint8_t status = BT_HCI_ERR_SUCCESS;
+
+	cmd_complete(dev, BT_HCI_CMD_LE_WRITE_DEFAULT_DATA_LENGTH, &status,
+						sizeof(status));
+
+	return 0;
+}
+
 static int cmd_read_local_pk256(struct btdev *dev, const void *data,
 						uint8_t len)
 {
@@ -5011,6 +5092,24 @@ static int cmd_gen_dhkey(struct btdev *dev, const void *data, uint8_t len)
 	return -ENOTSUP;
 }
 
+static int cmd_le_read_max_data_len(struct btdev *dev, const void *data,
+						uint8_t len)
+{
+	struct bt_hci_rsp_le_read_max_data_length rsp;
+
+	memset(&rsp, 0, sizeof(rsp));
+	rsp.status = BT_HCI_ERR_SUCCESS;
+	rsp.max_tx_len = cpu_to_le16(0x00fb);
+	rsp.max_tx_time = cpu_to_le16(0x4290);
+	rsp.max_rx_len = cpu_to_le16(0x00fb);
+	rsp.max_rx_time = cpu_to_le16(0x4290);
+
+	cmd_complete(dev, BT_HCI_CMD_LE_READ_MAX_DATA_LENGTH, &rsp,
+						sizeof(rsp));
+
+	return 0;
+}
+
 #define CMD_LE \
 	CMD(BT_HCI_CMD_READ_LE_HOST_SUPPORTED, cmd_read_le_host_supported, \
 					NULL), \
@@ -5055,6 +5154,10 @@ static int cmd_gen_dhkey(struct btdev *dev, const void *data, uint8_t len)
 					cmd_conn_param_reply_complete), \
 	CMD(BT_HCI_CMD_LE_CONN_PARAM_REQ_NEG_REPLY, cmd_conn_param_neg_reply, \
 					cmd_conn_param_neg_reply_complete), \
+	CMD(BT_HCI_CMD_LE_READ_DEFAULT_DATA_LENGTH, cmd_le_read_def_data_len, \
+					NULL), \
+	CMD(BT_HCI_CMD_LE_WRITE_DEFAULT_DATA_LENGTH, \
+					cmd_le_write_def_data_len, NULL), \
 	CMD(BT_HCI_CMD_LE_READ_LOCAL_PK256, cmd_read_local_pk256, NULL), \
 	CMD(BT_HCI_CMD_LE_GENERATE_DHKEY, cmd_gen_dhkey, NULL), \
 	CMD(BT_HCI_CMD_LE_ADD_TO_RESOLV_LIST, cmd_add_rl,  NULL), \
@@ -5065,7 +5168,9 @@ static int cmd_gen_dhkey(struct btdev *dev, const void *data, uint8_t len)
 	CMD(BT_HCI_CMD_LE_READ_LOCAL_RESOLV_ADDR, cmd_read_local_rl_addr, \
 					NULL), \
 	CMD(BT_HCI_CMD_LE_SET_RESOLV_ENABLE, cmd_set_rl_enable, NULL), \
-	CMD(BT_HCI_CMD_LE_SET_RESOLV_TIMEOUT, cmd_set_rl_timeout, NULL)
+	CMD(BT_HCI_CMD_LE_SET_RESOLV_TIMEOUT, cmd_set_rl_timeout, NULL), \
+	CMD(BT_HCI_CMD_LE_READ_MAX_DATA_LENGTH, cmd_le_read_max_data_len, \
+					NULL) \
 
 static const struct btdev_cmd cmd_bredr_le[] = {
 	CMD_COMMON_ALL,
@@ -5096,16 +5201,20 @@ static int cmd_set_default_phy(struct btdev *dev, const void *data,
 							uint8_t len)
 {
 	const struct bt_hci_cmd_le_set_default_phy *cmd = data;
-	uint8_t status;
+	uint8_t status = BT_HCI_ERR_SUCCESS;
 
 	if (cmd->all_phys > 0x03 || (!(cmd->all_phys & 0x01) &&
-			(!cmd->tx_phys || cmd->tx_phys > 0x07)) ||
+			(!cmd->tx_phys || cmd->tx_phys > 0x17)) ||
 			(!(cmd->all_phys & 0x02) &&
-			(!cmd->rx_phys || cmd->rx_phys > 0x07)))
+			(!cmd->rx_phys || cmd->rx_phys > 0x17))) {
 		status = BT_HCI_ERR_INVALID_PARAMETERS;
-	else
-		status = BT_HCI_ERR_SUCCESS;
+		goto done;
+	}
+
+	dev->le_def_tx_phys = cmd->tx_phys;
+	dev->le_def_rx_phys = cmd->rx_phys;
 
+done:
 	cmd_complete(dev, BT_HCI_CMD_LE_SET_DEFAULT_PHY, &status,
 					sizeof(status));
 
@@ -5127,9 +5236,9 @@ static int cmd_le_set_phy(struct btdev *dev, const void *data,
 	}
 
 	if (cmd->all_phys > 0x03 || (!(cmd->all_phys & 0x01) &&
-			(!cmd->tx_phys || cmd->tx_phys > 0x07)) ||
+			(!cmd->tx_phys || cmd->tx_phys > 0x17)) ||
 			(!(cmd->all_phys & 0x02) &&
-			(!cmd->rx_phys || cmd->rx_phys > 0x07)))
+			(!cmd->rx_phys || cmd->rx_phys > 0x17)))
 		status = BT_HCI_ERR_INVALID_PARAMETERS;
 	else
 		status = BT_HCI_ERR_SUCCESS;
@@ -5153,9 +5262,9 @@ static int cmd_le_set_phy_complete(struct btdev *dev, const void *data,
 		return 0;
 
 	if (cmd->all_phys > 0x03 || (!(cmd->all_phys & 0x01) &&
-			(!cmd->tx_phys || cmd->tx_phys > 0x07)) ||
+			(!cmd->tx_phys || cmd->tx_phys > 0x17)) ||
 			(!(cmd->all_phys & 0x02) &&
-			(!cmd->rx_phys || cmd->rx_phys > 0x07)))
+			(!cmd->rx_phys || cmd->rx_phys > 0x17)))
 		return 0;
 
 	memset(&ev, 0, sizeof(ev));
@@ -5169,19 +5278,39 @@ static int cmd_le_set_phy_complete(struct btdev *dev, const void *data,
 		ev.rx_phy = 0x01; /* LE 1M PHY */
 
 	if (cmd->tx_phys & BIT(1))
-		ev.tx_phy |= 0x02; /* LE 2M PHY */
+		ev.tx_phy = 0x02; /* LE 2M PHY */
 
 	if (cmd->rx_phys & BIT(1))
-		ev.rx_phy |= 0x02; /* LE 2M PHY */
+		ev.rx_phy = 0x02; /* LE 2M PHY */
 
 	if (cmd->tx_phys & BIT(2))
-		ev.tx_phy |= 0x03; /* LE CODED PHY */
+		ev.tx_phy = 0x03; /* LE CODED PHY */
 
 	if (cmd->rx_phys & BIT(2))
-		ev.rx_phy |= 0x03; /* LE CODED PHY */
+		ev.rx_phy = 0x03; /* LE CODED PHY */
+
+	if (cmd->tx_phys & BIT(4))
+		ev.tx_phy = 0x05; /* HDT PHY */
+
+	if (cmd->rx_phys & BIT(4))
+		ev.rx_phy = 0x05; /* HDT PHY */
 
 	le_meta_event(dev, BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE, &ev, sizeof(ev));
 
+	/* The peer receives on the PHY this side transmits on and the other
+	 * way around.
+	 */
+	if (conn->link) {
+		uint8_t tx_phy = ev.tx_phy;
+
+		ev.handle = cpu_to_le16(conn->link->handle);
+		ev.tx_phy = ev.rx_phy;
+		ev.rx_phy = tx_phy;
+		le_meta_event(conn->link->dev,
+				BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE, &ev,
+				sizeof(ev));
+	}
+
 	return 0;
 }
 
@@ -5814,7 +5943,9 @@ static uint8_t bits_to_phy(uint8_t bits)
 {
 	uint8_t phy = 0x00;
 
-	/* Convert PHY bits to PHY values on a ascending order. */
+	/* Convert PHY bits to PHY values on a ascending order so if HDT bit is
+	 * set it takes precedence over LE 2M and LE 1M.
+	 */
 	if (bits & BIT(0))
 		phy = 0x01; /* LE 1M */
 
@@ -5824,6 +5955,9 @@ static uint8_t bits_to_phy(uint8_t bits)
 	if (bits & BIT(2))
 		phy = 0x03; /* LE Coded */
 
+	if (bits & BIT(4))
+		phy = 0x05; /* HDT */
+
 	return phy;
 }
 
@@ -6155,6 +6289,62 @@ static void ext_adv_term(void *data, void *user_data)
 	}
 }
 
+static void le_phy_update_event(struct btdev_conn *conn, uint8_t tx_phy,
+							uint8_t rx_phy)
+{
+	struct bt_hci_evt_le_phy_update_complete ev;
+
+	if (!conn || !tx_phy || !rx_phy)
+		return;
+
+	memset(&ev, 0, sizeof(ev));
+
+	ev.handle = cpu_to_le16(conn->handle);
+	ev.tx_phy = tx_phy;
+	ev.rx_phy = rx_phy;
+
+	le_meta_event(conn->dev, BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE,
+					&ev, sizeof(ev));
+
+	/* The peer receives on the PHY this side transmits on and the other
+	 * way around.
+	 */
+	ev.handle = cpu_to_le16(conn->link->handle);
+	ev.tx_phy = rx_phy;
+	ev.rx_phy = tx_phy;
+	le_meta_event(conn->link->dev, BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE,
+					&ev, sizeof(ev));
+}
+
+/* Highest PHY both sides prefer: HDT, then LE 2M, then LE 1M */
+static uint8_t le_phy_select(uint8_t local, uint8_t remote)
+{
+	uint8_t phys = local & remote;
+
+	if (phys & BIT(4))
+		return 0x05; /* HDT */
+
+	if (phys & BIT(1))
+		return 0x02; /* LE 2M */
+
+	return 0x01; /* LE 1M */
+}
+
+static void le_phy_update(struct btdev_conn *conn)
+{
+	uint8_t tx_phy, rx_phy;
+
+	/* Each direction is transmitted by one side and received by the
+	 * other.
+	 */
+	tx_phy = le_phy_select(conn->dev->le_def_tx_phys,
+					conn->link->dev->le_def_rx_phys);
+	rx_phy = le_phy_select(conn->dev->le_def_rx_phys,
+					conn->link->dev->le_def_tx_phys);
+
+	le_phy_update_event(conn, tx_phy, rx_phy);
+}
+
 static void le_ext_conn_complete(struct btdev *btdev,
 			const struct bt_hci_cmd_le_ext_create_conn *cmd,
 			struct le_ext_adv *ext_adv,
@@ -6220,9 +6410,11 @@ static void le_ext_conn_complete(struct btdev *btdev,
 	le_meta_event(btdev, BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE, &ev,
 						sizeof(ev));
 
-	/* Disable EXT ADV */
-	if (conn)
+	/* Disable EXT ADV and update PHY */
+	if (conn) {
 		queue_foreach(btdev->le_ext_adv, ext_adv_term, conn);
+		le_phy_update(conn);
+	}
 }
 
 static int cmd_ext_create_conn_complete(struct btdev *dev, const void *data,
@@ -6861,7 +7053,7 @@ static int cmd_set_cig_params(struct btdev *dev, const void *data,
 
 	rsp.params.cig_id = cmd->cig_id;
 
-	if (cmd->num_cis > ARRAY_SIZE(dev->le_cig[0].cis)) {
+	if (cmd->num_cis > ARRAY_SIZE(dev->le_cig[0].cis_v1)) {
 		rsp.params.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
 		goto done;
 	}
@@ -6938,6 +7130,7 @@ static int cmd_set_cig_params(struct btdev *dev, const void *data,
 	}
 
 	memcpy(&dev->le_cig[cig_idx], data, len);
+	dev->le_cig[cig_idx].version = 1;
 
 done:
 	cmd_complete(dev, BT_HCI_CMD_LE_SET_CIG_PARAMS, &rsp,
@@ -7010,10 +7203,94 @@ static uint32_t le_cis_latecy(uint8_t ft, uint8_t iso_interval,
 	return latency >= interval ? latency : interval;
 }
 
+/* LE CIS Established v1 is a prefix of v3, so send the newest version the
+ * host unmasked: v3 is LE event mask bit 57.
+ */
+static void le_cis_estabilished_send(struct btdev *btdev,
+				struct bt_hci_evt_le_cis_established_v3 *evt)
+{
+	if (btdev->le_event_mask[7] & BIT(1))
+		le_meta_event(btdev, BT_HCI_EVT_LE_CIS_ESTABLISHED_V3, evt,
+							sizeof(*evt));
+	else
+		le_meta_event(btdev, BT_HCI_EVT_LE_CIS_ESTABLISHED, evt,
+				sizeof(struct bt_hci_evt_le_cis_established));
+}
+
+static void le_cis_estabilished_fill(struct bt_hci_evt_le_cis_established_v3 *evt,
+					struct le_cig *le_cig, int cis_idx)
+{
+	uint8_t c_phys, p_phys;
+
+	if (le_cig->version == 2) {
+		struct bt_hci_cis_params_v2 *cis = &le_cig->cis_v2[cis_idx];
+
+		c_phys = cis->c_phy;
+		p_phys = cis->p_phy;
+		evt->c_mtu = cis->c_sdu;
+		evt->p_mtu = cis->p_sdu;
+		evt->mic_len = cis->mic_len;
+		evt->c_phy = bits_to_phy(c_phys);
+		evt->p_phy = bits_to_phy(p_phys);
+
+		switch (evt->c_phy) {
+		case 0x03:
+			evt->c_rates = cpu_to_le16(cis->c_coded_rates);
+			break;
+		case 0x05:
+			evt->c_rates = cis->c_hdt_rates;
+			break;
+		}
+
+		switch (evt->p_phy) {
+		case 0x03:
+			evt->p_rates = cpu_to_le16(cis->p_coded_rates);
+			break;
+		case 0x05:
+			evt->p_rates = cis->p_hdt_rates;
+			break;
+		}
+	} else {
+		struct bt_hci_cis_params *cis = &le_cig->cis_v1[cis_idx];
+
+		evt->c_phy = bits_to_phy(cis->c_phys);
+		evt->p_phy = bits_to_phy(cis->p_phys);
+		evt->c_mtu = cis->c_sdu;
+		evt->p_mtu = cis->p_sdu;
+	}
+
+	evt->nse = 0x01;
+	evt->c_bn = 0x01;
+	evt->p_bn = 0x01;
+	evt->c_ft = 0x02;
+	evt->p_ft = 0x02;
+	evt->interval = le_cis_interval(le_cig->params.c_interval);
+	evt->c_sdu = evt->c_mtu;
+	evt->p_sdu = evt->p_mtu;
+	memcpy(evt->c_sdu_interval, le_cig->params.c_interval,
+					sizeof(evt->c_sdu_interval));
+	memcpy(evt->p_sdu_interval, le_cig->params.p_interval,
+					sizeof(evt->p_sdu_interval));
+	evt->framing = le_cig->params.framing;
+
+	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 6, Part G
+	 * page 3050:
+	 *
+	 * 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
+	 */
+	put_le24(le_cis_latecy(evt->c_ft, evt->interval,
+				le_cig->params.c_interval), evt->c_latency);
+	put_le24(le_cis_latecy(evt->p_ft, evt->interval,
+				le_cig->params.p_interval), evt->p_latency);
+}
+
 static void le_cis_estabilished(struct btdev *dev, struct btdev_conn *conn,
 						uint8_t status)
 {
-	struct bt_hci_evt_le_cis_established evt;
+	struct bt_hci_evt_le_cis_established_v3 evt;
 	int cig_idx, cis_idx = -1;
 
 	memset(&evt, 0, sizeof(evt));
@@ -7025,44 +7302,18 @@ static void le_cis_estabilished(struct btdev *dev, struct btdev_conn *conn,
 	if (cig_idx < 0 && !evt.status)
 		evt.status = BT_HCI_ERR_UNSPECIFIED_ERROR;
 
-	if (!evt.status) {
-		struct btdev *remote = conn->link->dev;
-		struct le_cig *le_cig = &remote->le_cig[cig_idx];
-
-		memset(evt.cig_sync_delay, 0, sizeof(evt.cig_sync_delay));
-		memset(evt.cis_sync_delay, 0, sizeof(evt.cis_sync_delay));
-
-		evt.c_phy = bits_to_phy(le_cig->cis[cis_idx].c_phys);
-		evt.p_phy = bits_to_phy(le_cig->cis[cis_idx].p_phys);
-		evt.nse = 0x01;
-		evt.c_bn = 0x01;
-		evt.p_bn = 0x01;
-		evt.c_ft = 0x02;
-		evt.p_ft = 0x02;
-		evt.c_mtu = le_cig->cis[cis_idx].c_sdu;
-		evt.p_mtu = le_cig->cis[cis_idx].p_sdu;
-		evt.interval = le_cis_interval(le_cig->params.c_interval);
-
-		/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 6, Part G
-		 * page 3050:
-		 *
-		 * 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
-		 */
-		put_le24(le_cis_latecy(evt.c_ft, evt.interval,
-				le_cig->params.c_interval), evt.c_latency);
-		put_le24(le_cis_latecy(evt.p_ft, evt.interval,
-				le_cig->params.p_interval), evt.p_latency);
-	}
+	if (!evt.status)
+		le_cis_estabilished_fill(&evt, &conn->link->dev->le_cig[cig_idx],
+								cis_idx);
 
-	le_meta_event(dev, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt, sizeof(evt));
+	le_cis_estabilished_send(dev, &evt);
 
+	/* Each device assigns its own handles, so the event of the
+	 * receiving side carries its handle.
+	 */
 	if (conn) {
 		evt.conn_handle = cpu_to_le16(conn->link->handle);
-		le_meta_event(conn->link->dev, BT_HCI_EVT_LE_CIS_ESTABLISHED,
-						&evt, sizeof(evt));
+		le_cis_estabilished_send(conn->link->dev, &evt);
 	}
 }
 
@@ -7108,13 +7359,22 @@ static int cmd_create_cis_complete(struct btdev *dev, const void *data,
 			}
 		}
 
+		memset(&evt, 0, sizeof(evt));
 		/* Each device assigns its own handles, so the event of
 		 * the receiving side carries its handles.
 		 */
 		evt.acl_handle = cpu_to_le16(acl->link->handle);
 		evt.cis_handle = cpu_to_le16(iso->link->handle);
 		evt.cig_id = le_cig->params.cig_id;
-		evt.cis_id = le_cig->cis[cis_idx].cis_id;
+
+		switch (le_cig->version) {
+		case 0x01:
+			evt.cis_id = le_cig->cis_v1[cis_idx].cis_id;
+			break;
+		case 0x02:
+			evt.cis_id = le_cig->cis_v2[cis_idx].cis_id;
+			break;
+		}
 
 		le_cig->activated = true;
 
@@ -7284,7 +7544,7 @@ static int cmd_create_big_complete(struct btdev *dev, const void *data,
 	for (i = 0; i < cmd->num_bis; i++) {
 		struct btdev_conn *conn;
 
-		conn = conn_add_bis(dev, BIS_HANDLE + i, bis);
+		conn = conn_add_bis(dev, BIS_HANDLE + i, bis, sizeof(*bis));
 		if (!conn) {
 			queue_remove(dev->le_big, big);
 			le_big_free(big);
@@ -7898,8 +8158,8 @@ static int cmd_le_read_all_remote_features(struct btdev *dev, const void *data,
 	memset(&ev, 0, sizeof(ev));
 	ev.status = BT_HCI_ERR_SUCCESS;
 	ev.handle = cpu_to_le16(conn->handle);
-	ev.max_pages = 1;
-	ev.valid_pages = 1;
+	ev.max_pages = 10;
+	ev.valid_pages = 10;
 	memcpy(ev.features, conn->link->dev->le_features, 248);
 
 	le_meta_event(dev, BT_HCI_EVT_LE_READ_ALL_REMOTE_FEATURES_COMPLETE, &ev,
@@ -8082,6 +8342,461 @@ static void set_le_62_commands(struct btdev *btdev)
 	btdev->cmds = cmd_le_6_2;
 }
 
+static int cmd_set_data_len_v2(struct btdev *dev, const void *data,
+					uint8_t len)
+{
+	const struct bt_hci_cmd_le_set_data_len_v2 *cmd = data;
+	struct bt_hci_rsp_le_set_data_len_v2 rsp;
+	struct btdev_conn *conn;
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	conn = queue_find(dev->conns, match_handle,
+				UINT_TO_PTR(le16_to_cpu(cmd->handle)));
+	if (!conn)
+		rsp.status = BT_HCI_ERR_UNKNOWN_CONN_ID;
+	else
+		rsp.handle = cpu_to_le16(conn->handle);
+
+	cmd_complete(dev, BT_HCI_CMD_LE_SET_DATA_LEN_V2, &rsp, sizeof(rsp));
+
+	return 0;
+}
+
+static int cmd_read_max_data_len_v2(struct btdev *dev, const void *data,
+					uint8_t len)
+{
+	const struct bt_hci_cmd_le_read_data_len_v2 *cmd = data;
+	struct bt_hci_rsp_le_read_data_len_v2 rsp;
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	switch (cmd->phy) {
+	case 0x00: /* No PHY */
+	case 0x01: /* LE 1M */
+	case 0x02: /* LE 2M */
+	case 0x03: /* LE Coded */
+		rsp.max_tx_len = cpu_to_le16(0x00fb);
+		rsp.max_tx_time = cpu_to_le16(0x0148);
+		rsp.max_rx_len = cpu_to_le16(0x00fb);
+		rsp.max_rx_time = cpu_to_le16(0x0148);
+		rsp.max_tx_win = 0x01;
+		rsp.max_rx_win = 0x01;
+		rsp.max_rx_packet = cpu_to_le16(0x00fb);
+		break;
+	case 0x05: /* LE HDT */
+		rsp.max_tx_len = cpu_to_le16(0x1fef);
+		rsp.max_tx_time = cpu_to_le16(0x148);
+		rsp.max_rx_len = cpu_to_le16(0x1fef);
+		rsp.max_rx_time = cpu_to_le16(0x148);
+		rsp.max_tx_win = 0x04;
+		rsp.max_rx_win = 0x04;
+		rsp.max_rx_packet = cpu_to_le16(0x1fef);
+		break;
+	default:
+		rsp.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		break;
+	}
+
+	cmd_complete(dev, BT_HCI_CMD_LE_READ_MAX_DATA_LEN_V2, &rsp,
+				sizeof(rsp));
+
+	return 0;
+}
+
+static int cmd_set_cig_params_v2(struct btdev *dev, const void *data,
+					uint8_t len)
+{
+	const struct bt_hci_cmd_le_set_cig_params_v2 *cmd = data;
+	struct lescp {
+		struct bt_hci_rsp_le_set_cig_params_v2 params;
+		uint16_t handle[CIS_SIZE];
+	} __attribute__ ((packed)) rsp;
+	int i = 0;
+	int cig_idx;
+	uint32_t interval;
+	uint16_t latency;
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	rsp.params.cig_id = cmd->cig_id;
+
+	if (cmd->num_cis > ARRAY_SIZE(dev->le_cig[0].cis_v2)) {
+		rsp.params.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		goto done;
+	}
+
+	if (cmd->cig_id > 0xef) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	interval = get_le24(cmd->c_interval);
+	if (interval < 0x0000ff || interval > 0x0fffff) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	interval = get_le24(cmd->p_interval);
+	if (interval < 0x0000ff || interval > 0x0fffff) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	if (cmd->sca > 0x07) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	if (cmd->packing > 0x01) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	if (cmd->framing > 0x01) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	latency = cpu_to_le16(cmd->c_latency);
+	if (latency < 0x0005 || latency > 0x0fa0) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	latency = cpu_to_le16(cmd->p_latency);
+	if (latency < 0x0005 || latency > 0x0fa0) {
+		rsp.params.status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	cig_idx = find_cig(dev, cmd->cig_id);
+	if (cig_idx < 0)
+		cig_idx = find_cig(dev, 0xff);
+	if (cig_idx < 0) {
+		rsp.params.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		goto done;
+	}
+
+	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
+	 * page 2553
+	 *
+	 * If the Host issues this command when the CIG is not in the
+	 * configurable state, the Controller shall return the error
+	 * code Command Disallowed (0x0C).
+	 */
+	if (dev->le_cig[cig_idx].activated) {
+		rsp.params.status = BT_HCI_ERR_COMMAND_DISALLOWED;
+		goto done;
+	}
+
+	rsp.params.status = BT_HCI_ERR_SUCCESS;
+
+	for (i = 0; i < cmd->num_cis; i++) {
+		rsp.params.num_handles++;
+		rsp.handle[i] = cpu_to_le16(make_cis_handle(cig_idx, i));
+	}
+
+	memcpy(&dev->le_cig[cig_idx], data, len);
+	dev->le_cig[cig_idx].version = 2;
+
+done:
+	cmd_complete(dev, BT_HCI_CMD_LE_SET_CIG_PARAMS_V2, &rsp,
+				sizeof(rsp.params) + (i * sizeof(uint16_t)));
+
+	return 0;
+}
+
+static int cmd_create_big_v2(struct btdev *dev, const void *data,
+					uint8_t len)
+{
+	const struct bt_hci_cmd_le_create_big_v2 *cmd = data;
+	uint8_t status = BT_HCI_ERR_SUCCESS;
+
+	/* If the Advertising_Handle does not identify a periodic advertising
+	 * train,, the Controller shall return the error code Unknown
+	 * Advertising Identifier (0x42).
+	 */
+	/* Num_BIS ranges from 0x01 to 0x1F */
+	if (!cmd->num_bis || cmd->num_bis > 0x1f) {
+		status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	if (!dev->le_pa_enable) {
+		status = BT_HCI_ERR_UNKNOWN_ADVERTISING_ID;
+		goto done;
+	}
+
+	/* If the Host sends this command with a BIG_Handle that is already
+	 * allocated, the Controller shall return the error code Command
+	 * Disallowed (0x0C).
+	 */
+	if (queue_find(dev->le_big, match_big_handle,
+				UINT_TO_PTR(cmd->handle))) {
+		status = BT_HCI_ERR_COMMAND_DISALLOWED;
+		goto done;
+	}
+
+done:
+	cmd_status(dev, status, BT_HCI_CMD_LE_CREATE_BIG_V2);
+
+	/* Only complete the command if it was accepted */
+	return status ? -EALREADY : 0;
+}
+
+static int cmd_create_big_v2_complete(struct btdev *dev, const void *data,
+							uint8_t len)
+{
+	const struct bt_hci_cmd_le_create_big_v2 *cmd = data;
+	const struct bt_hci_bis_v2 *bis = &cmd->bis;
+	struct le_big *big;
+	int i;
+	struct bt_hci_evt_le_big_complete_v2 evt;
+	uint16_t *bis_handle;
+	uint8_t *pdu;
+	size_t pdu_len;
+
+	memset(&evt, 0, sizeof(evt));
+
+	pdu_len = sizeof(evt) + cmd->num_bis * sizeof(*bis_handle);
+
+	pdu = malloc(pdu_len);
+	if (!pdu)
+		return -ENOMEM;
+
+	/* If the Controller cannot create all BISes of the BIG or if Num_BIS
+	 * exceeds the maximum value supported by the Controller, then it shall
+	 * return the error code Rejected due to Limited Resources (0x0D).
+	 */
+	big = le_big_new(dev, cmd->handle);
+	if (!big) {
+		evt.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		goto done;
+	}
+
+	bis_handle = (uint16_t *)(pdu + sizeof(evt));
+
+	for (i = 0; i < cmd->num_bis; i++) {
+		struct btdev_conn *conn;
+
+		conn = conn_add_bis(dev, BIS_HANDLE + i, bis, sizeof(*bis));
+		if (!conn) {
+			queue_remove(dev->le_big, big);
+			le_big_free(big);
+			evt.status = BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+			goto done;
+		}
+
+		queue_push_tail(big->bis, conn);
+		*bis_handle = cpu_to_le16(conn->handle);
+		bis_handle++;
+	}
+
+	evt.handle = cmd->handle;
+	evt.phy = bits_to_phy(bis->phy);
+	evt.max_pdu = bis->sdu;
+	memcpy(evt.sync_delay, bis->sdu_interval, 3);
+	memcpy(evt.latency, bis->sdu_interval, 3);
+	evt.interval = bis->latency / 1.25;
+
+	switch (evt.phy) {
+	case 0x03:
+		evt.rates = cpu_to_le16(bis->coded_rates);
+		break;
+	case 0x05:
+		evt.rates = bis->hdt_rates;
+		break;
+	}
+
+	evt.encryption = bis->encryption;
+	evt.mic_len = bis->mic_len;
+	evt.num_bis = cmd->num_bis;
+
+done:
+	memcpy(pdu, &evt, sizeof(evt));
+
+	le_meta_event(dev, BT_HCI_EVT_LE_BIG_COMPLETE_V2, pdu, pdu_len);
+
+	free(pdu);
+
+	return 0;
+}
+
+static int cmd_set_hdt_default_params(struct btdev *dev, const void *data,
+					uint8_t len)
+{
+	const struct bt_hci_cmd_le_hdt_set_default_params *cmd = data;
+	uint16_t valid_rates = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4);
+	uint8_t status;
+
+	if (cmd->mic_len > 0x02) {
+		status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	if (cmd->format > 0x02) {
+		status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	if (cmd->rates & ~valid_rates) {
+		status = BT_HCI_ERR_INVALID_PARAMETERS;
+		goto done;
+	}
+
+	dev->hdt_def_mic_len = cmd->mic_len;
+	dev->hdt_def_format = cmd->format;
+	dev->hdt_def_rates = le16_to_cpu(cmd->rates);
+	status = BT_HCI_ERR_SUCCESS;
+
+done:
+	cmd_complete(dev, BT_HCI_CMD_LE_SET_HDT_DEFAULT_PARAMS, &status,
+					sizeof(status));
+	return 0;
+}
+
+static int cmd_le_write_def_data_len_v2(struct btdev *dev, const void *data,
+						uint8_t len)
+{
+	uint8_t status = BT_HCI_ERR_SUCCESS;
+
+	cmd_complete(dev, BT_HCI_CMD_LE_WRITE_DEF_DATA_LEN_V2, &status,
+						sizeof(status));
+
+	return 0;
+}
+
+static int cmd_le_read_def_data_len_v2(struct btdev *dev, const void *data,
+						uint8_t len)
+{
+	const struct bt_hci_cmd_le_read_def_data_len_v2 *cmd = data;
+	struct bt_hci_rsp_le_read_default_data_length rsp;
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	switch (cmd->phys) {
+	case 0x00: /* All GFSK PHYs  */
+		rsp.status = BT_HCI_ERR_SUCCESS;
+		rsp.tx_len = cpu_to_le16(0x001b);
+		rsp.tx_time = cpu_to_le16(0x0148);
+		break;
+	case 0x01: /* HDT PHY */
+		rsp.status = BT_HCI_ERR_SUCCESS;
+		rsp.tx_len = cpu_to_le16(0x001b);
+		rsp.tx_time = cpu_to_le16(0x0148);
+		break;
+	default:
+		rsp.status = BT_HCI_ERR_INVALID_PARAMETERS;
+	}
+
+	cmd_complete(dev, BT_HCI_CMD_LE_READ_DEF_DATA_LEN_V2, &rsp,
+						sizeof(rsp));
+
+	return 0;
+}
+
+#define CMD_HDT \
+	CMD(BT_HCI_CMD_LE_WRITE_DEF_DATA_LEN_V2, \
+					cmd_le_write_def_data_len_v2, NULL), \
+	CMD(BT_HCI_CMD_LE_READ_DEF_DATA_LEN_V2, cmd_le_read_def_data_len_v2, \
+					NULL), \
+	CMD(BT_HCI_CMD_LE_SET_DATA_LEN_V2, cmd_set_data_len_v2, NULL), \
+	CMD(BT_HCI_CMD_LE_READ_MAX_DATA_LEN_V2, cmd_read_max_data_len_v2, \
+			NULL), \
+	CMD(BT_HCI_CMD_LE_SET_CIG_PARAMS_V2, cmd_set_cig_params_v2, NULL), \
+	CMD(BT_HCI_CMD_LE_CREATE_BIG_V2, cmd_create_big_v2, \
+			cmd_create_big_v2_complete), \
+	CMD(BT_HCI_CMD_LE_SET_HDT_DEFAULT_PARAMS, cmd_set_hdt_default_params, \
+					NULL)
+
+/* A 64-bit MIC is only used if both devices prefer it, the peer's
+ * preference being its LE Set HDT Default Parameters.
+ */
+static uint8_t le_mic_len(struct btdev_conn *conn, uint8_t mic_len)
+{
+	if (mic_len == 0x01 && conn->link &&
+				conn->link->dev->hdt_def_mic_len != 0x01)
+		return 0x02;
+
+	return mic_len;
+}
+
+static int cmd_le_enable_encrypt_v2(struct btdev *dev, const void *data,
+						uint8_t len)
+{
+	const struct bt_hci_cmd_le_enable_encrypt_v2 *cmd = data;
+	struct bt_hci_evt_le_long_term_key_request ev;
+	struct btdev_conn *conn;
+
+	conn = queue_find(dev->conns, match_handle,
+				UINT_TO_PTR(le16_to_cpu(cmd->handle)));
+	if (!conn) {
+		cmd_status(dev, BT_HCI_ERR_UNKNOWN_CONN_ID,
+				BT_HCI_CMD_LE_ENABLE_ENCRYPT_V2);
+		return 0;
+	}
+
+	cmd_status(dev, BT_HCI_ERR_SUCCESS, BT_HCI_CMD_LE_ENABLE_ENCRYPT_V2);
+
+	/* Opportunistic encryption: skip LTK request, proceed directly */
+	if (cmd->encryption == 0x01) {
+		conn->mic_len = le_mic_len(conn, cmd->mic_len);
+		if (conn->link)
+			conn->link->mic_len = conn->mic_len;
+		encrypt_change(conn, 0x01, 0x02, BT_HCI_ERR_SUCCESS);
+		encrypt_change(conn->link, 0x01, 0x02, BT_HCI_ERR_SUCCESS);
+		return 0;
+	}
+
+	memcpy(dev->le_ltk, cmd->ltk, 16);
+
+	conn->mic_len = le_mic_len(conn, cmd->mic_len);
+	if (conn->link)
+		conn->link->mic_len = conn->mic_len;
+
+	ev.handle = cpu_to_le16(conn->link->handle);
+	ev.ediv = cmd->ediv;
+	ev.rand = cmd->rand;
+
+	le_meta_event(conn->link->dev, BT_HCI_EVT_LE_LONG_TERM_KEY_REQUEST, &ev,
+					sizeof(ev));
+
+	return 0;
+}
+
+#define CMD_EKS \
+	CMD(BT_HCI_CMD_LE_ENABLE_ENCRYPT_V2, cmd_le_enable_encrypt_v2, NULL)
+
+static const struct btdev_cmd cmd_hdt[] = {
+	CMD_COMMON_ALL,
+	CMD_COMMON_BREDR_LE,
+	CMD_COMMON_BREDR_20,
+	CMD_COMMON_BREDR_LE_40,
+	CMD_BREDR,
+	CMD_LE,
+	CMD_LE_50,
+	CMD_LE_52,
+	CMD_LE_60,
+	CMD_LE_62,
+	CMD_HDT,
+	CMD_EKS,
+	{}
+};
+
+static void set_hdt_commands(struct btdev *btdev)
+{
+	btdev->commands[50] |= BIT(6);	/* LE Read Default Data Length V2 */
+	btdev->commands[50] |= BIT(7);	/* LE Write Default Data Length V2 */
+	btdev->commands[50] |= BIT(4);	/* LE Enable Encryption v2 */
+	btdev->commands[50] |= BIT(5);	/* LE Read Maximum Data Length v2 */
+	btdev->commands[52] |= BIT(3);	/* LE Set Data Length v2 */
+	btdev->commands[51] |= BIT(0);	/* LE Set CIG Parameters v2 */
+	btdev->commands[51] |= BIT(3);	/* LE Create BIG v2 */
+	btdev->commands[52] |= BIT(1);	/* LE Set HDT Default Parameters */
+	btdev->cmds = cmd_hdt;
+}
+
 static void set_le_commands(struct btdev *btdev)
 {
 	set_common_commands_all(btdev);
@@ -8123,6 +8838,8 @@ static void set_le_commands(struct btdev *btdev)
 	btdev->commands[33] |= 0x20;	/* LE Remote Conn Param Req Neg Reply */
 
 	/* Extra LE commands for >= 4.2 adapters */
+	btdev->commands[33] |= BIT(7);	/* LE Read Default Data Length */
+	btdev->commands[34] |= BIT(0);	/* LE Write Default Data Length */
 	btdev->commands[34] |= 0x02;	/* LE Read Local P-256 Public Key */
 	btdev->commands[34] |= 0x04;	/* LE Generate DHKey */
 	btdev->commands[34] |= 0x08;	/* LE Add Device To Resolving List */
@@ -8133,6 +8850,7 @@ static void set_le_commands(struct btdev *btdev)
 	btdev->commands[35] |= 0x01;	/* LE Read Local Resolvable Address */
 	btdev->commands[35] |= 0x02;	/* LE Set Address Resolution Enable */
 	btdev->commands[35] |= 0x04;	/* LE Set RPA Timeout */
+	btdev->commands[35] |= BIT(3);	/* LE Read Maximum Data Length */
 
 	btdev->cmds = cmd_le;
 
@@ -8162,6 +8880,12 @@ static void set_le_commands(struct btdev *btdev)
 		set_le_62_commands(btdev);
 		btdev->cmds = cmd_le_6_2;
 	}
+
+	/* Extra HDT commands for >= 7.0 adapters */
+	if (btdev->type >= BTDEV_TYPE_BREDRLE70) {
+		set_hdt_commands(btdev);
+		btdev->cmds = cmd_hdt;
+	}
 }
 
 static void set_bredrle_commands(struct btdev *btdev)
@@ -8214,6 +8938,7 @@ static void set_bredrle_features(struct btdev *btdev)
 		btdev->features[4] |= 0x80;	/* 3 slot EDR ACL packets */
 		btdev->features[5] |= 0x01;	/* 5 slot EDR ACL packets */
 
+		btdev->le_features[0] |= BIT(5); /* LE Data Length Extension */
 		btdev->le_features[0] |= 0x40;	/* LE PRIVACY */
 		btdev->le_features[1] |= 0x01;	/* LE 2M PHY */
 		btdev->le_features[1] |= 0x08;	/* LE Coded PHY */
@@ -8244,6 +8969,22 @@ static void set_bredrle_features(struct btdev *btdev)
 		btdev->le_features[9] |= BIT(1);
 	}
 
+	if (btdev->type >= BTDEV_TYPE_BREDRLE70) {
+		uint8_t *page_1 = &btdev->le_features[8];
+
+		btdev->version = 0x10;
+
+		page_1[1] |= BIT(4); /* Encryption Key Schedule */
+		page_1[1] |= BIT(5); /* High Data Throughput */
+		page_1[1] |= BIT(6); /* Receive HDT6 Rate */
+		page_1[1] |= BIT(7); /* Transmit HDT6 Rate */
+		page_1[2] |= BIT(0); /* Receive HDT7.5 Rate */
+		page_1[2] |= BIT(1); /* Transmit HDT7.5 Rate */
+		page_1[2] |= BIT(2); /* HDT Packet Format 1 */
+		page_1[2] |= BIT(3); /* Link Quality Feedback */
+		page_1[3] |= BIT(2); /* Opportunistic Encryption (Host) */
+	}
+
 	btdev->feat_page_2[0] |= 0x01;	/* CPB - Central Operation */
 	btdev->feat_page_2[0] |= 0x02;	/* CPB - Peripheral Operation */
 	btdev->feat_page_2[0] |= 0x04;	/* Synchronization Train */
@@ -8350,6 +9091,7 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
 	case BTDEV_TYPE_BREDRLE52:
 	case BTDEV_TYPE_BREDRLE60:
 	case BTDEV_TYPE_BREDRLE62:
+	case BTDEV_TYPE_BREDRLE70:
 		btdev->crypto = bt_crypto_new();
 		if (!btdev->crypto) {
 			free(btdev);
@@ -8369,6 +9111,12 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
 	btdev->revision = 0x0000;
 
 	switch (btdev->type) {
+	case BTDEV_TYPE_BREDRLE70:
+		btdev->version = 0x0e;
+		set_bredrle_features(btdev);
+		set_bredrle_commands(btdev);
+		set_le_states(btdev);
+		break;
 	case BTDEV_TYPE_BREDRLE:
 	case BTDEV_TYPE_BREDRLE50:
 	case BTDEV_TYPE_BREDRLE52:
@@ -9094,6 +9842,7 @@ int btdev_set_msft_opcode(struct btdev *btdev, uint16_t opcode)
 	case BTDEV_TYPE_BREDRLE52:
 	case BTDEV_TYPE_BREDRLE60:
 	case BTDEV_TYPE_BREDRLE62:
+	case BTDEV_TYPE_BREDRLE70:
 		btdev->msft_opcode = opcode;
 		btdev->msft_cmds = cmd_msft;
 		return 0;
@@ -9153,6 +9902,7 @@ int btdev_set_emu_opcode(struct btdev *btdev, uint16_t opcode)
 	case BTDEV_TYPE_BREDRLE52:
 	case BTDEV_TYPE_BREDRLE60:
 	case BTDEV_TYPE_BREDRLE62:
+	case BTDEV_TYPE_BREDRLE70:
 		btdev->emu_opcode = opcode;
 		btdev->emu_cmds = cmd_emu;
 		return 0;
diff --git a/emulator/btdev.h b/emulator/btdev.h
index aa04ca611ab5..0e7ed8639568 100644
--- a/emulator/btdev.h
+++ b/emulator/btdev.h
@@ -54,6 +54,7 @@ enum btdev_type {
 	BTDEV_TYPE_BREDRLE52,
 	BTDEV_TYPE_BREDRLE60,
 	BTDEV_TYPE_BREDRLE62,
+	BTDEV_TYPE_BREDRLE70,
 };
 
 enum btdev_hook_type {
diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index 2f544f319bf2..897402fa58dc 100644
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
@@ -409,6 +409,9 @@ struct hciemu *hciemu_new_num_debug(enum hciemu_type type, uint8_t num,
 	case HCIEMU_TYPE_BREDRLE62:
 		hciemu->btdev_type = BTDEV_TYPE_BREDRLE62;
 		break;
+	case HCIEMU_TYPE_BREDRLE70:
+		hciemu->btdev_type = BTDEV_TYPE_BREDRLE70;
+		break;
 	default:
 		return NULL;
 	}
diff --git a/emulator/hciemu.h b/emulator/hciemu.h
index cdf1ebe16752..34ab3af44ab7 100644
--- a/emulator/hciemu.h
+++ b/emulator/hciemu.h
@@ -23,6 +23,7 @@ enum hciemu_type {
 	HCIEMU_TYPE_BREDRLE52,
 	HCIEMU_TYPE_BREDRLE60,
 	HCIEMU_TYPE_BREDRLE62,
+	HCIEMU_TYPE_BREDRLE70,
 };
 
 enum hciemu_hook_type {
diff --git a/emulator/main.c b/emulator/main.c
index 794d381764b5..7be303716ca4 100644
--- a/emulator/main.c
+++ b/emulator/main.c
@@ -73,7 +73,7 @@ static void usage(void)
 		"\t-C, --core=<version>  Core Specification version of the\n"
 		"\t                      BR/EDR/LE controllers created with\n"
 		"\t                      -l, -s, -t and -V:\n"
-		"\t                      5.0, 5.2, 6.0 or 6.2 (default)\n"
+		"\t                      5.0, 5.2, 6.0, 6.2 or 7.0 (default)\n"
 		"\t-h, --help            Show help options\n");
 }
 
@@ -106,6 +106,7 @@ static const struct {
 	{ "5.2", BTDEV_TYPE_BREDRLE52 },
 	{ "6.0", BTDEV_TYPE_BREDRLE60 },
 	{ "6.2", BTDEV_TYPE_BREDRLE62 },
+	{ "7.0", BTDEV_TYPE_BREDRLE70 },
 };
 
 static bool parse_core_version(const char *version, enum btdev_type *type)
@@ -157,7 +158,7 @@ int main(int argc, char *argv[])
 	int letest_count = 0;
 	int vhci_count = 0;
 	/* Default to the latest version supported by the emulator */
-	enum btdev_type bredrle_type = BTDEV_TYPE_BREDRLE62;
+	enum btdev_type bredrle_type = BTDEV_TYPE_BREDRLE70;
 	enum btdev_type type;
 	bool type_set = false;
 	int i;
-- 
2.56.0


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

* [PATCH BlueZ v2 5/9] emulator: Add HDT support to bthost
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2026-11-04 18:36 ` [PATCH BlueZ v2 4/9] emulator: Add HDT support to btdev Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 6/9] shared/gatt: Add MIC length permission checks Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add helpers to set the PHY of a connection, including the HDT rates,
and to start encryption with a given MIC length through LE Enable
Encryption v2, so testers can exercise HDT and MIC length checks from
the remote side.
---
 emulator/bthost.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++
 emulator/bthost.h | 14 +++++++
 2 files changed, 113 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 2f05573786f8..afcf453be789 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -277,6 +277,10 @@ struct bthost {
 	bool conn_init;
 	bool le;
 	bool sc;
+	uint8_t mic_len;
+
+	bthost_encrypt_cb encrypt_cb;
+	void *encrypt_cb_data;
 
 	struct queue *le_ext_adv;
 
@@ -1605,6 +1609,9 @@ static void evt_encrypt_change(struct bthost *bthost, const void *data,
 
 	if (conn->smp_data)
 		smp_conn_encrypted(conn->smp_data, conn->encr_mode);
+
+	if (ev->encr_mode && bthost->encrypt_cb)
+		bthost->encrypt_cb(handle, bthost->encrypt_cb_data);
 }
 
 static void evt_io_cap_response(struct bthost *bthost, const void *data,
@@ -1946,6 +1953,17 @@ static void evt_le_big_info_adv_report(struct bthost *bthost,
 	send_command(bthost, BT_HCI_CMD_LE_BIG_CREATE_SYNC, &cmd, sizeof(cmd));
 }
 
+static void evt_le_cis_established_v3(struct bthost *bthost, const void *data,
+							uint8_t size)
+{
+	const struct bt_hci_evt_le_cis_established_v3 *ev = data;
+
+	if (ev->status)
+		return;
+
+	init_iso(bthost, ev->conn_handle, BDADDR_ANY->b, BDADDR_LE_PUBLIC);
+}
+
 static void evt_le_meta_event(struct bthost *bthost, const void *data,
 								uint8_t len)
 {
@@ -1994,6 +2012,9 @@ static void evt_le_meta_event(struct bthost *bthost, const void *data,
 	case BT_HCI_EVT_LE_CONN_RATE_CHANGE:
 		evt_le_conn_rate_change(bthost, evt_data, len - 1);
 		break;
+	case BT_HCI_EVT_LE_CIS_ESTABLISHED_V3:
+		evt_le_cis_established_v3(bthost, evt_data, len - 1);
+		break;
 	default:
 		bthost_debug(bthost, "Unsupported LE Meta event 0x%2.2x",
 								*event);
@@ -4030,6 +4051,12 @@ void bthost_le_start_encrypt(struct bthost *bthost, uint16_t handle,
 {
 	struct bt_hci_cmd_le_start_encrypt cmd;
 
+	if (bthost->mic_len) {
+		bthost_le_start_encrypt_v2(bthost, handle, ltk,
+							bthost->mic_len);
+		return;
+	}
+
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.handle = htobs(handle);
 	memcpy(cmd.ltk, ltk, 16);
@@ -4055,6 +4082,36 @@ void bthost_le_conn_rate(struct bthost *bthost, uint16_t handle,
 	send_command(bthost, BT_HCI_CMD_LE_CONN_RATE, &cmd, sizeof(cmd));
 }
 
+void bthost_le_start_encrypt_v2(struct bthost *bthost, uint16_t handle,
+					const uint8_t ltk[16], uint8_t mic_len)
+{
+	struct bt_hci_cmd_le_enable_encrypt_v2 cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.handle = htobs(handle);
+	memcpy(cmd.ltk, ltk, 16);
+	cmd.mic_len = mic_len;
+
+	send_command(bthost, BT_HCI_CMD_LE_ENABLE_ENCRYPT_V2, &cmd,
+							sizeof(cmd));
+}
+
+void bthost_le_reencrypt(struct bthost *bthost, uint16_t handle,
+							uint8_t mic_len)
+{
+	struct btconn *conn;
+	uint8_t ltk[16];
+
+	conn = bthost_find_conn(bthost, handle);
+	if (!conn || !conn->smp_data)
+		return;
+
+	if (smp_get_ltk(conn->smp_data, 0, 0, ltk) < 0)
+		return;
+
+	bthost_le_start_encrypt_v2(bthost, handle, ltk, mic_len);
+}
+
 uint64_t bthost_conn_get_fixed_chan(struct bthost *bthost, uint16_t handle)
 {
 	struct btconn *conn;
@@ -4113,6 +4170,48 @@ void bthost_set_sc_support(struct bthost *bthost, bool enable)
 							&cmd, sizeof(cmd));
 }
 
+void bthost_set_mic_len(struct bthost *bthost, uint8_t mic_len)
+{
+	bthost->mic_len = mic_len;
+}
+
+uint8_t bthost_get_mic_len(struct bthost *bthost)
+{
+	return bthost->mic_len;
+}
+
+void bthost_set_default_phy(struct bthost *bthost, uint8_t tx_phys,
+							uint8_t rx_phys)
+{
+	struct bt_hci_cmd_le_set_default_phy cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tx_phys = tx_phys;
+	cmd.rx_phys = rx_phys;
+
+	send_command(bthost, BT_HCI_CMD_LE_SET_DEFAULT_PHY, &cmd, sizeof(cmd));
+}
+
+void bthost_le_set_phy(struct bthost *bthost, uint16_t handle,
+					uint8_t tx_phys, uint8_t rx_phys)
+{
+	struct bt_hci_cmd_le_set_phy cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.handle = htobs(handle);
+	cmd.tx_phys = tx_phys;
+	cmd.rx_phys = rx_phys;
+
+	send_command(bthost, BT_HCI_CMD_LE_SET_PHY, &cmd, sizeof(cmd));
+}
+
+void bthost_set_encrypt_cb(struct bthost *bthost, bthost_encrypt_cb cb,
+							void *user_data)
+{
+	bthost->encrypt_cb = cb;
+	bthost->encrypt_cb_data = user_data;
+}
+
 void bthost_set_pin_code(struct bthost *bthost, const uint8_t *pin,
 							uint8_t pin_len)
 {
diff --git a/emulator/bthost.h b/emulator/bthost.h
index ed924eb99630..b3e18114638a 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -169,6 +169,10 @@ void bthost_request_auth(struct bthost *bthost, uint16_t handle);
 
 void bthost_le_start_encrypt(struct bthost *bthost, uint16_t handle,
 							const uint8_t ltk[16]);
+void bthost_le_start_encrypt_v2(struct bthost *bthost, uint16_t handle,
+					const uint8_t ltk[16], uint8_t mic_len);
+void bthost_le_reencrypt(struct bthost *bthost, uint16_t handle,
+							uint8_t mic_len);
 typedef void (*bthost_l2cap_connect_cb) (uint16_t handle, uint16_t cid,
 							void *user_data);
 typedef void (*bthost_l2cap_disconnect_cb) (uint16_t handle, uint16_t cid,
@@ -185,6 +189,16 @@ void bthost_add_l2cap_server_custom(struct bthost *bthost, uint16_t psm,
 				void *user_data);
 
 void bthost_set_sc_support(struct bthost *bthost, bool enable);
+void bthost_set_mic_len(struct bthost *bthost, uint8_t mic_len);
+uint8_t bthost_get_mic_len(struct bthost *bthost);
+void bthost_set_default_phy(struct bthost *bthost, uint8_t tx_phys,
+							uint8_t rx_phys);
+void bthost_le_set_phy(struct bthost *bthost, uint16_t handle,
+					uint8_t tx_phys, uint8_t rx_phys);
+
+typedef void (*bthost_encrypt_cb)(uint16_t handle, void *user_data);
+void bthost_set_encrypt_cb(struct bthost *bthost, bthost_encrypt_cb cb,
+							void *user_data);
 
 void bthost_set_pin_code(struct bthost *bthost, const uint8_t *pin,
 							uint8_t pin_len);
-- 
2.56.0


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

* [PATCH BlueZ v2 6/9] shared/gatt: Add MIC length permission checks
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2026-11-04 18:36 ` [PATCH BlueZ v2 5/9] emulator: Add HDT support to bthost Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 7/9] main.conf: Add HDT configuration Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add read and write MIC length permissions for 64-bit and 128-bit MICs,
take the MIC length of the link from the BT_SECURITY socket option, and
reject access with MIC Length Too Short when the link uses a shorter
one. Expose the permissions as GATT characteristic and descriptor flags
over D-Bus, and add bluetoothctl scripts exercising them.
---
 client/scripts/gatt-mic-128.bt       |   5 ++
 client/scripts/gatt-mic-64-128.bt    |   7 ++
 client/scripts/gatt-mic-64.bt        |   5 ++
 doc/org.bluez.GattCharacteristic.rst |   4 ++
 doc/org.bluez.GattDescriptor.rst     |   4 ++
 src/gatt-database.c                  |  26 +++++++
 src/shared/att-types.h               |  17 ++++-
 src/shared/att.c                     |  39 +++++++++++
 src/shared/att.h                     |   3 +
 src/shared/gatt-db.c                 |   9 +++
 src/shared/gatt-db.h                 |   3 +
 src/shared/gatt-server.c             |  33 ++++++++-
 unit/test-gatt.c                     | 101 +++++++++++++++++++++++++++
 13 files changed, 252 insertions(+), 4 deletions(-)
 create mode 100644 client/scripts/gatt-mic-128.bt
 create mode 100644 client/scripts/gatt-mic-64-128.bt
 create mode 100644 client/scripts/gatt-mic-64.bt

diff --git a/client/scripts/gatt-mic-128.bt b/client/scripts/gatt-mic-128.bt
new file mode 100644
index 000000000000..9d566ae5bf9c
--- /dev/null
+++ b/client/scripts/gatt-mic-128.bt
@@ -0,0 +1,5 @@
+gatt.register-service 12345678-1234-5678-1234-56789abcdef0
+yes
+gatt.register-characteristic 12345678-1234-5678-1234-56789abcdef2 mic-128-read,mic-128-write
+01 02 03 04
+gatt.register-application
diff --git a/client/scripts/gatt-mic-64-128.bt b/client/scripts/gatt-mic-64-128.bt
new file mode 100644
index 000000000000..f4e595165e71
--- /dev/null
+++ b/client/scripts/gatt-mic-64-128.bt
@@ -0,0 +1,7 @@
+gatt.register-service 12345678-1234-5678-1234-56789abcdef0
+yes
+gatt.register-characteristic 12345678-1234-5678-1234-56789abcdef1 mic-64-read,mic-64-write
+01 02 03 04
+gatt.register-characteristic 12345678-1234-5678-1234-56789abcdef2 mic-128-read,mic-128-write
+05 06 07 08
+gatt.register-application
diff --git a/client/scripts/gatt-mic-64.bt b/client/scripts/gatt-mic-64.bt
new file mode 100644
index 000000000000..b79717ae2534
--- /dev/null
+++ b/client/scripts/gatt-mic-64.bt
@@ -0,0 +1,5 @@
+gatt.register-service 12345678-1234-5678-1234-56789abcdef0
+yes
+gatt.register-characteristic 12345678-1234-5678-1234-56789abcdef1 mic-64-read,mic-64-write
+01 02 03 04
+gatt.register-application
diff --git a/doc/org.bluez.GattCharacteristic.rst b/doc/org.bluez.GattCharacteristic.rst
index 805f39593903..6dd5d44c04cf 100644
--- a/doc/org.bluez.GattCharacteristic.rst
+++ b/doc/org.bluez.GattCharacteristic.rst
@@ -382,6 +382,10 @@ Possible values:
 :"secure-write" (Server only):
 :"secure-notify" (Server only):
 :"secure-indicate" (Server only):
+:"mic-64-read" (Server only):
+:"mic-64-write" (Server only):
+:"mic-128-read" (Server only):
+:"mic-128-write" (Server only):
 :"authorize":
 
 uint16 Handle [read-only] (Client Only)
diff --git a/doc/org.bluez.GattDescriptor.rst b/doc/org.bluez.GattDescriptor.rst
index 790a5482d080..425d9becf635 100644
--- a/doc/org.bluez.GattDescriptor.rst
+++ b/doc/org.bluez.GattDescriptor.rst
@@ -160,6 +160,10 @@ Possible values:
 :"encrypt-authenticated-write":
 :"secure-read" (Server Only):
 :"secure-write" (Server Only):
+:"mic-64-read" (Server Only):
+:"mic-64-write" (Server Only):
+:"mic-128-read" (Server Only):
+:"mic-128-write" (Server Only):
 :"authorize":
 
 uint16 Handle [read-only] (Client Only)
diff --git a/src/gatt-database.c b/src/gatt-database.c
index d8e45581a138..cbee49d59f55 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -1799,6 +1799,21 @@ static bool parse_chrc_flags(DBusMessageIter *array, uint8_t *props,
 		} else if (!strcmp("secure-write", flag)) {
 			*props |= BT_GATT_CHRC_PROP_WRITE;
 			*perm |= BT_ATT_PERM_WRITE | BT_ATT_PERM_WRITE_SECURE;
+		} else if (!strcmp("mic-64-read", flag)) {
+			*props |= BT_GATT_CHRC_PROP_READ;
+			*perm |= BT_ATT_PERM_READ | BT_ATT_PERM_READ_MIC_LEN_64;
+		} else if (!strcmp("mic-64-write", flag)) {
+			*props |= BT_GATT_CHRC_PROP_WRITE;
+			*perm |= BT_ATT_PERM_WRITE |
+						BT_ATT_PERM_WRITE_MIC_LEN_64;
+		} else if (!strcmp("mic-128-read", flag)) {
+			*props |= BT_GATT_CHRC_PROP_READ;
+			*perm |= BT_ATT_PERM_READ |
+						BT_ATT_PERM_READ_MIC_LEN_128;
+		} else if (!strcmp("mic-128-write", flag)) {
+			*props |= BT_GATT_CHRC_PROP_WRITE;
+			*perm |= BT_ATT_PERM_WRITE |
+						BT_ATT_PERM_WRITE_MIC_LEN_128;
 		} else if (!strcmp("authorize", flag)) {
 			*req_prep_authorization = true;
 		} else if (!strcmp("encrypt-notify", flag)) {
@@ -1860,6 +1875,17 @@ static bool parse_desc_flags(DBusMessageIter *array, uint32_t *perm,
 			*perm |= BT_ATT_PERM_READ | BT_ATT_PERM_READ_SECURE;
 		else if (!strcmp("secure-write", flag))
 			*perm |= BT_ATT_PERM_WRITE | BT_ATT_PERM_WRITE_SECURE;
+		else if (!strcmp("mic-64-read", flag))
+			*perm |= BT_ATT_PERM_READ | BT_ATT_PERM_READ_MIC_LEN_64;
+		else if (!strcmp("mic-64-write", flag))
+			*perm |= BT_ATT_PERM_WRITE |
+						BT_ATT_PERM_WRITE_MIC_LEN_64;
+		else if (!strcmp("mic-128-read", flag))
+			*perm |= BT_ATT_PERM_READ |
+						BT_ATT_PERM_READ_MIC_LEN_128;
+		else if (!strcmp("mic-128-write", flag))
+			*perm |= BT_ATT_PERM_WRITE |
+						BT_ATT_PERM_WRITE_MIC_LEN_128;
 		else if (!strcmp("authorize", flag))
 			*req_prep_authorization = true;
 		else {
diff --git a/src/shared/att-types.h b/src/shared/att-types.h
index 69f45b6aa6d7..687ebf66cafa 100644
--- a/src/shared/att-types.h
+++ b/src/shared/att-types.h
@@ -98,6 +98,7 @@ struct bt_att_pdu_error_rsp {
 #define BT_ATT_ERROR_INSUFFICIENT_RESOURCES		0x11
 #define BT_ATT_ERROR_DB_OUT_OF_SYNC			0x12
 #define BT_ATT_ERROR_VALUE_NOT_ALLOWED			0x13
+#define BT_ATT_ERROR_MIC_LEN_TOO_SHORT			0x14
 
 /*
  * Common Profile and Service Error Code descriptions (see Supplement to the
@@ -131,14 +132,26 @@ struct bt_att_pdu_error_rsp {
 #define BT_ATT_PERM_WRITE_SECURE	0x0200
 #define BT_ATT_PERM_SECURE		(BT_ATT_PERM_READ_SECURE | \
 					BT_ATT_PERM_WRITE_SECURE)
+#define BT_ATT_PERM_READ_MIC_LEN_64	0x0400
+#define BT_ATT_PERM_READ_MIC_LEN_128	0x0800
+#define BT_ATT_PERM_WRITE_MIC_LEN_64	0x1000
+#define BT_ATT_PERM_WRITE_MIC_LEN_128	0x2000
+#define BT_ATT_PERM_MIC_LEN_64		(BT_ATT_PERM_READ_MIC_LEN_64 | \
+					BT_ATT_PERM_WRITE_MIC_LEN_64)
+#define BT_ATT_PERM_MIC_LEN_128	(BT_ATT_PERM_READ_MIC_LEN_128 | \
+					BT_ATT_PERM_WRITE_MIC_LEN_128)
 #define BT_ATT_PERM_READ_MASK		(BT_ATT_PERM_READ | \
 					BT_ATT_PERM_READ_AUTHEN | \
 					BT_ATT_PERM_READ_ENCRYPT | \
-					BT_ATT_PERM_READ_SECURE)
+					BT_ATT_PERM_READ_SECURE | \
+					BT_ATT_PERM_READ_MIC_LEN_64 | \
+					BT_ATT_PERM_READ_MIC_LEN_128)
 #define BT_ATT_PERM_WRITE_MASK		(BT_ATT_PERM_WRITE | \
 					BT_ATT_PERM_WRITE_AUTHEN | \
 					BT_ATT_PERM_WRITE_ENCRYPT | \
-					BT_ATT_PERM_WRITE_SECURE)
+					BT_ATT_PERM_WRITE_SECURE | \
+					BT_ATT_PERM_WRITE_MIC_LEN_64 | \
+					BT_ATT_PERM_WRITE_MIC_LEN_128)
 
 /* GATT Characteristic Properties Bitfield values */
 #define BT_GATT_CHRC_PROP_BROADCAST			0x01
diff --git a/src/shared/att.c b/src/shared/att.c
index 279a750ae863..296e19014d70 100644
--- a/src/shared/att.c
+++ b/src/shared/att.c
@@ -63,6 +63,7 @@ struct bt_att {
 	bool close_on_unref;
 	struct queue *chans;
 	uint8_t enc_size;
+	uint8_t mic_len;
 	uint16_t mtu;			/* Biggest possible MTU */
 
 	struct queue *notify_list;	/* List of registered callbacks */
@@ -2130,6 +2131,44 @@ void bt_att_set_enc_key_size(struct bt_att *att, uint8_t enc_size)
 	att->enc_size = enc_size;
 }
 
+static uint8_t bt_att_chan_get_mic_len(struct bt_att_chan *chan)
+{
+	struct bt_security sec;
+	socklen_t len;
+
+	if (chan->type == BT_ATT_LOCAL)
+		return chan->att->mic_len;
+
+	memset(&sec, 0, sizeof(sec));
+	len = sizeof(sec);
+	if (getsockopt(chan->fd, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) < 0)
+		return 0;
+
+	return sec.mic_len;
+}
+
+uint8_t bt_att_get_mic_len(struct bt_att *att)
+{
+	struct bt_att_chan *chan;
+
+	if (!att)
+		return 0;
+
+	chan = queue_peek_tail(att->chans);
+	if (!chan)
+		return 0;
+
+	return bt_att_chan_get_mic_len(chan);
+}
+
+void bt_att_set_mic_len(struct bt_att *att, uint8_t mic_len)
+{
+	if (!att)
+		return;
+
+	att->mic_len = mic_len;
+}
+
 static bool sign_set_key(struct sign_info **sign, uint8_t key[16],
 				bt_att_counter_func_t func, void *user_data)
 {
diff --git a/src/shared/att.h b/src/shared/att.h
index 5b5cd4fbab2c..4bee694e4352 100644
--- a/src/shared/att.h
+++ b/src/shared/att.h
@@ -116,6 +116,9 @@ int bt_att_get_security(struct bt_att *att, uint8_t *enc_size);
 bool bt_att_set_security(struct bt_att *att, int level);
 void bt_att_set_enc_key_size(struct bt_att *att, uint8_t enc_size);
 
+uint8_t bt_att_get_mic_len(struct bt_att *att);
+void bt_att_set_mic_len(struct bt_att *att, uint8_t mic_len);
+
 bool bt_att_set_local_key(struct bt_att *att, uint8_t sign_key[16],
 			bt_att_counter_func_t func, void *user_data);
 bool bt_att_set_remote_key(struct bt_att *att, uint8_t sign_key[16],
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 23c705bd9d16..2384c5fc8135 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -2180,6 +2180,15 @@ gatt_db_attribute_get_permissions(const struct gatt_db_attribute *attrib)
 	return attrib->permissions;
 }
 
+void gatt_db_attribute_set_permissions(struct gatt_db_attribute *attrib,
+							uint32_t permissions)
+{
+	if (!attrib)
+		return;
+
+	attrib->permissions = permissions;
+}
+
 static bool read_timeout(void *user_data)
 {
 	struct pending_read *p = user_data;
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 5e7e7203fcc3..8640768850fd 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -265,6 +265,9 @@ bool gatt_db_attribute_get_incl_data(const struct gatt_db_attribute *attrib,
 uint32_t
 gatt_db_attribute_get_permissions(const struct gatt_db_attribute *attrib);
 
+void gatt_db_attribute_set_permissions(struct gatt_db_attribute *attrib,
+							uint32_t permissions);
+
 bool gatt_db_attribute_set_fixed_length(struct gatt_db_attribute *attrib,
 						uint16_t len);
 
diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 15944bd1478f..84cfa094bfb0 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -189,7 +189,11 @@ static void attribute_read_cb(struct gatt_db_attribute *attrib, int err,
 	iov->iov_len = length;
 }
 
-static bool encode_read_by_grp_type_rsp(struct gatt_db *db, struct queue *q,
+static uint8_t check_permissions(struct bt_gatt_server *server,
+				struct gatt_db_attribute *attr, uint32_t mask);
+
+static bool encode_read_by_grp_type_rsp(struct bt_gatt_server *server,
+						struct queue *q,
 						struct bt_att *att,
 						uint16_t mtu, uint8_t *pdu,
 						uint16_t *len)
@@ -204,6 +208,12 @@ static bool encode_read_by_grp_type_rsp(struct gatt_db *db, struct queue *q,
 	while (queue_peek_head(q)) {
 		struct gatt_db_attribute *attrib = queue_pop_head(q);
 
+		/* Stop before a service the link does not have the security
+		 * to read, the caller reports it if it is the first one.
+		 */
+		if (check_permissions(server, attrib, BT_ATT_PERM_READ_MASK))
+			break;
+
 		value.iov_base = NULL;
 		value.iov_len = 0;
 
@@ -320,13 +330,21 @@ static void read_by_grp_type_cb(struct bt_att_chan *chan, uint16_t mtu,
 		goto error;
 	}
 
+	/* Check permissions on the first attribute */
+	ecode = check_permissions(server, queue_peek_head(q),
+							BT_ATT_PERM_READ_MASK);
+	if (ecode) {
+		ehandle = gatt_db_attribute_get_handle(queue_peek_head(q));
+		goto error;
+	}
+
 	rsp_pdu = malloc(mtu);
 	if (!rsp_pdu) {
 		ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
 		goto error;
 	}
 
-	if (!encode_read_by_grp_type_rsp(server->db, q, server->att, mtu,
+	if (!encode_read_by_grp_type_rsp(server, q, server->att, mtu,
 							rsp_pdu, &rsp_len)) {
 		ecode = BT_ATT_ERROR_UNLIKELY;
 		goto error;
@@ -460,6 +478,17 @@ static uint8_t check_permissions(struct bt_gatt_server *server,
 			return BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE;
 	}
 
+	/* Check MIC length requirements */
+	if (perm & (BT_ATT_PERM_READ_MIC_LEN_128 |
+					BT_ATT_PERM_WRITE_MIC_LEN_128)) {
+		if (bt_att_get_mic_len(server->att) < 0x02)
+			return BT_ATT_ERROR_MIC_LEN_TOO_SHORT;
+	} else if (perm & (BT_ATT_PERM_READ_MIC_LEN_64 |
+					BT_ATT_PERM_WRITE_MIC_LEN_64)) {
+		if (bt_att_get_mic_len(server->att) < 0x01)
+			return BT_ATT_ERROR_MIC_LEN_TOO_SHORT;
+	}
+
 	return 0;
 }
 
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 6d6d0c73ed40..2d5b4201de3f 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
@@ -2476,10 +2476,46 @@ static void test_hash_db(gconstpointer data)
 	context_quit(context);
 }
 
+/*
+ * Test database for MIC length validation:
+ * Primary service at handle 0x0001 with 4 handles.
+ * Characteristic at handle 0x0003 (value handle) with read/write permissions
+ * requiring 128-bit MIC length.
+ * Service declaration also has MIC length permission for Read By Group Type.
+ */
+static struct gatt_db *make_mic_len_db(void)
+{
+	const struct att_handle_spec specs[] = {
+		PRIMARY_SERVICE(0x0001, GAP_UUID, 4),
+		CHARACTERISTIC(GATT_CHARAC_DEVICE_NAME,
+				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE |
+				BT_ATT_PERM_READ_MIC_LEN_128 |
+				BT_ATT_PERM_WRITE_MIC_LEN_128,
+				BT_GATT_CHRC_PROP_READ |
+				BT_GATT_CHRC_PROP_WRITE,
+				0x01, 0x02, 0x03),
+		{ }
+	};
+	struct gatt_db *db;
+	struct gatt_db_attribute *attr;
+
+	db = make_db(specs);
+
+	/* Set MIC length permission on the service declaration for
+	 * Read By Group Type test.
+	 */
+	attr = gatt_db_get_attribute(db, 0x0001);
+	gatt_db_attribute_set_permissions(attr, BT_ATT_PERM_READ |
+						BT_ATT_PERM_READ_MIC_LEN_128);
+
+	return db;
+}
+
 int main(int argc, char *argv[])
 {
 	struct gatt_db *service_db_1, *service_db_2, *service_db_3;
 	struct gatt_db *ts_small_db, *ts_large_db_1, *ts_tail_db;
+	struct gatt_db *mic_len_db;
 
 	tester_init(&argc, &argv);
 
@@ -2489,6 +2525,7 @@ int main(int argc, char *argv[])
 	ts_small_db = make_test_spec_small_db();
 	ts_large_db_1 = make_test_spec_large_db_1();
 	ts_tail_db = make_test_tail_db();
+	mic_len_db = make_mic_len_db();
 
 	/*
 	 * Server Configuration
@@ -4658,5 +4695,69 @@ int main(int argc, char *argv[])
 			test_hash_db, ts_tail_db, NULL,
 			{});
 
+	/*
+	 * MIC Length Too Short
+	 *
+	 * Verify that the server rejects requests with error 0x14
+	 * (MIC Length Too Short) when the connection MIC length is
+	 * insufficient for the attribute's requirement.
+	 */
+
+	/* Read By Type Request */
+	define_test_server("/robustness/mic-len/read-by-type", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x08, 0x01, 0x00, 0x04, 0x00, 0x00, 0x2a),
+			raw_pdu(0x01, 0x08, 0x03, 0x00, 0x14));
+
+	/* Read Request */
+	define_test_server("/robustness/mic-len/read", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x0a, 0x03, 0x00),
+			raw_pdu(0x01, 0x0a, 0x03, 0x00, 0x14));
+
+	/* Read Blob Request */
+	define_test_server("/robustness/mic-len/read-blob", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x0c, 0x03, 0x00, 0x00, 0x00),
+			raw_pdu(0x01, 0x0c, 0x03, 0x00, 0x14));
+
+	/* Read Multiple Request */
+	define_test_server("/robustness/mic-len/read-multiple", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x0e, 0x03, 0x00, 0x03, 0x00),
+			raw_pdu(0x01, 0x0e, 0x03, 0x00, 0x14));
+
+	/* Read Multiple Variable Request */
+	define_test_server("/robustness/mic-len/read-multiple-variable", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x20, 0x03, 0x00, 0x03, 0x00),
+			raw_pdu(0x01, 0x20, 0x03, 0x00, 0x14));
+
+	/* Write Request */
+	define_test_server("/robustness/mic-len/write", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x12, 0x03, 0x00, 0x01),
+			raw_pdu(0x01, 0x12, 0x03, 0x00, 0x14));
+
+	/* Prepare Write Request */
+	define_test_server("/robustness/mic-len/prepare-write", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x16, 0x03, 0x00, 0x00, 0x00, 0x01),
+			raw_pdu(0x01, 0x16, 0x03, 0x00, 0x14));
+
+	/* Read By Group Type Request */
+	define_test_server("/robustness/mic-len/read-by-group-type", test_server,
+			mic_len_db, NULL,
+			raw_pdu(0x03, 0x00, 0x02),
+			raw_pdu(0x10, 0x01, 0x00, 0x04, 0x00, 0x00, 0x28),
+			raw_pdu(0x01, 0x10, 0x01, 0x00, 0x14));
+
 	return tester_run();
 }
-- 
2.56.0


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

* [PATCH BlueZ v2 7/9] main.conf: Add HDT configuration
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
                   ` (5 preceding siblings ...)
  2026-11-04 18:36 ` [PATCH BlueZ v2 6/9] shared/gatt: Add MIC length permission checks Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 8/9] l2cap-tester, iso-tester, mgmt-tester: Add HDT tests Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 9/9] l2test: Add HDT options Luiz Augusto von Dentz
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add an [HDT] group with DefaultMICLength, DefaultPacketFormat,
DefaultRates and EKSOpportunistic, and pass them to the kernel with the
LE HDT default parameters and Opportunistic Encryption system
configuration TLVs, documented in mgmt-protocol.rst.
---
 doc/mgmt-protocol.rst |  3 +++
 src/adapter.c         | 28 ++++++++++++++++++++++++++++
 src/btd.h             |  7 +++++++
 src/main.c            | 33 +++++++++++++++++++++++++++++++++
 src/main.conf         | 27 +++++++++++++++++++++++++++
 5 files changed, 98 insertions(+)

diff --git a/doc/mgmt-protocol.rst b/doc/mgmt-protocol.rst
index bf6a3b20084c..c4e1421e3a5c 100644
--- a/doc/mgmt-protocol.rst
+++ b/doc/mgmt-protocol.rst
@@ -3469,6 +3469,9 @@ Currently defined Parameter_Type values are:
 	0x001e, LE No Filter Scanning Duration for adv monitoring
 	0x001f, LE Enable Interleave Scan for adv monitoring
 	0x0020, BR/EDR Connection Idle Timeout
+	0x0021, LE HDT Default MIC Length
+	0x0022, LE HDT Default Packet Format
+	0x0023, LE HDT Default Rates
 
 This command can be used at any time and will return a list of supported default
 parameters as well as their current value.
diff --git a/src/adapter.c b/src/adapter.c
index 6588a6e2bdc9..ea438375cc72 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -5167,6 +5167,34 @@ static bool load_le_defaults(struct btd_adapter *adapter,
 			return false;
 	}
 
+	if (btd_opts.hdt.mic_len >= 0) {
+		uint8_t val = btd_opts.hdt.mic_len;
+
+		if (!mgmt_tlv_add_fixed(list, 0x0021, &val))
+			return false;
+	}
+
+	if (btd_opts.hdt.format >= 0) {
+		uint8_t val = btd_opts.hdt.format;
+
+		if (!mgmt_tlv_add_fixed(list, 0x0022, &val))
+			return false;
+	}
+
+	if (btd_opts.hdt.rates >= 0) {
+		uint16_t val = cpu_to_le16(btd_opts.hdt.rates);
+
+		if (!mgmt_tlv_add_fixed(list, 0x0023, &val))
+			return false;
+	}
+
+	if (btd_opts.hdt.eks_oppt >= 0) {
+		uint8_t val = btd_opts.hdt.eks_oppt ? 0x01 : 0x00;
+
+		if (!mgmt_tlv_add_fixed(list, 0x0024, &val))
+			return false;
+	}
+
 	return true;
 }
 
diff --git a/src/btd.h b/src/btd.h
index b059ab872764..9bf310271972 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -180,6 +180,13 @@ struct btd_opts {
 	struct btd_advmon_opts	advmon;
 
 	struct btd_csis csis;
+
+	struct {
+		int16_t	mic_len;	/* -1 = not set */
+		int16_t	format;		/* -1 = not set */
+		int32_t	rates;		/* -1 = not set */
+		int8_t	eks_oppt;	/* -1 = not set, 0/1 = off/on */
+	} hdt;
 };
 
 extern struct btd_opts btd_opts;
diff --git a/src/main.c b/src/main.c
index 8e58b6b58ae2..729a6faa0892 100644
--- a/src/main.c
+++ b/src/main.c
@@ -190,6 +190,14 @@ static const char *advmon_options[] = {
 	NULL
 };
 
+static const char *hdt_options[] = {
+	"DefaultMICLength",
+	"DefaultPacketFormat",
+	"DefaultRates",
+	"EKSOpportunistic",
+	NULL
+};
+
 static const struct group_table {
 	const char *name;
 	const char * const *options;
@@ -204,6 +212,7 @@ static const struct group_table {
 	{ "AVRCP",	avrcp_options },
 	{ "ChannelSounding",	bcs_options },
 	{ "AdvMon",	advmon_options },
+	{ "HDT",	hdt_options },
 	{ }
 };
 
@@ -1398,6 +1407,24 @@ static void parse_advmon(GKeyFile *config)
 				0, UINT8_MAX);
 }
 
+static void parse_hdt(GKeyFile *config)
+{
+	int val;
+	bool bval;
+
+	if (parse_config_int(config, "HDT", "DefaultMICLength", &val, 0, 2))
+		btd_opts.hdt.mic_len = val;
+
+	if (parse_config_int(config, "HDT", "DefaultPacketFormat", &val, 0, 2))
+		btd_opts.hdt.format = val;
+
+	if (parse_config_int(config, "HDT", "DefaultRates", &val, 0, 0x1f))
+		btd_opts.hdt.rates = val;
+
+	if (parse_config_bool(config, "HDT", "EKSOpportunistic", &bval))
+		btd_opts.hdt.eks_oppt = bval ? 1 : 0;
+}
+
 static void parse_config(GKeyFile *config)
 {
 	if (!config)
@@ -1417,6 +1444,7 @@ static void parse_config(GKeyFile *config)
 	parse_avrcp(config);
 	parse_le_cs_config(config);
 	parse_advmon(config);
+	parse_hdt(config);
 }
 
 static void init_defaults(void)
@@ -1444,6 +1472,11 @@ static void init_defaults(void)
 	btd_opts.defaults.le.addr_resolution = 0x01;
 	btd_opts.defaults.le.enable_advmon_interleave_scan = 0xFF;
 
+	btd_opts.hdt.mic_len = -1;
+	btd_opts.hdt.format = -1;
+	btd_opts.hdt.rates = -1;
+	btd_opts.hdt.eks_oppt = -1;
+
 	if (sscanf(VERSION, "%hhu.%hhu", &major, &minor) != 2)
 		return;
 
diff --git a/src/main.conf b/src/main.conf
index 7eb75d87163c..882b0755ac35 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -253,6 +253,33 @@ KernelExperimental = 6fbaf188-05e0-496a-9885-d6ddfdb4e03e
 # Defaults to 1
 #EnableAdvMonInterleaveScan=
 
+[HDT]
+# Default Parameters sent to the controller via HCI_LE_Set_HDT_Default_Parameters.
+
+# Default MIC Length
+# 0x00: 32-bit (no preference)
+# 0x01: 64-bit
+# 0x02: 128-bit
+#DefaultMICLength=0x02
+
+# Default Packet Format
+# 0x00: No preference
+# 0x01: Packet Format 0
+# 0x02: Packet Format 1
+#DefaultPacketFormat=0x00
+
+# Default Rates (bitmask)
+# Bit 0: HDT 2M
+# Bit 1: HDT 3M
+# Bit 2: HDT 4M
+# Bit 3: HDT 6M
+# Bit 4: HDT 7.5M
+#DefaultRates=0x001f
+
+# Enable EKS Opportunistic Encryption. When both sides support it and no
+# LTK is available, the link will be encrypted with an ephemeral key.
+#EKSOpportunistic=true
+
 [GATT]
 # GATT attribute cache.
 # Possible values:
-- 
2.56.0


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

* [PATCH BlueZ v2 8/9] l2cap-tester, iso-tester, mgmt-tester: Add HDT tests
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
                   ` (6 preceding siblings ...)
  2026-11-04 18:36 ` [PATCH BlueZ v2 7/9] main.conf: Add HDT configuration Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  2026-11-04 18:36 ` [PATCH BlueZ v2 9/9] l2test: Add HDT options Luiz Augusto von Dentz
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add tests for HDT on a 7.0 controller: L2CAP connections on each HDT
rate, MIC Length Too Short and MIC length downgrade on L2CAP, CIS with
HDT rates and default MIC length on ISO, and the HDT and EKS settings
and system configuration on MGMT.

Assisted-by: OpenCode:claude-opus-5
---
 tools/iso-tester.c   | 1638 +++++++++++++++++++++++++++++++++++++-----
 tools/l2cap-tester.c |  761 ++++++++++++++++++++
 tools/mgmt-tester.c  |  170 +++++
 3 files changed, 2403 insertions(+), 166 deletions(-)

diff --git a/tools/iso-tester.c b/tools/iso-tester.c
index 333c894ea06e..47b05c10df06 100644
--- a/tools/iso-tester.c
+++ b/tools/iso-tester.c
@@ -128,11 +128,41 @@
 	QOS_FULL(0x01, 0x02, \
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
 
+#define QOS_IO_EXT(_interval, _latency, _sdu, _phys, _rtn, _rates) \
+{ \
+	.interval = _interval, \
+	.latency = _latency, \
+	.sdu = _sdu, \
+	.phys = _phys, \
+	.rtn = _rtn, \
+	.rates = _rates, \
+}
+
+#define QOS_FULL_EXT(_cig, _cis, _in, _out) \
+{ \
+	.version = BT_ISO_QOS_VERSION_1, \
+	.ucast = { \
+		.cig = _cig, \
+		.cis = _cis, \
+		.sca = 0x07, \
+		.packing = 0x00, \
+		.framing = 0x00, \
+		.in = _in, \
+		.out = _out, \
+	},\
+}
+
+#define QOS_EXT(_interval, _latency, _sdu, _phy, _rtn, _rates) \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(_interval, _latency, _sdu, _phy, _rtn, _rates), \
+		QOS_IO_EXT(_interval, _latency, _sdu, _phy, _rtn, _rates))
+
 /* QoS Configuration settings for low latency audio data */
 #define QOS_8_1_1 QOS(7500, 8, 26, 0x02, 2)
 #define QOS_8_2_1 QOS(10000, 10, 30, 0x02, 2)
 #define QOS_16_1_1 QOS(7500, 8, 30, 0x02, 2)
 #define QOS_16_2_1 QOS(10000, 10, 40, 0x02, 2)
+#define HDT_16_2_1 QOS(10000, 10, 40, BIT(4), 2)
 #define QOS_1_16_2_1 QOS_1(10000, 10, 40, 0x02, 2)
 #define QOS_2_16_2_1 QOS_2(10000, 10, 40, 0x02, 2)
 #define QOS_1_1_16_2_1 QOS_1_1(10000, 10, 40, 0x02, 2)
@@ -179,6 +209,92 @@
 #define QOS_48_3_gr QOS(7500, 15, 90, 0x02, 1)
 #define QOS_48_4_gr QOS(10000, 20, 120, 0x02, 1)
 
+#define HDT_2M QOS_EXT(10000, 10, 40, BIT(4), 2, BIT(0))
+#define HDT_3M QOS_EXT(10000, 10, 40, BIT(4), 2, BIT(1))
+#define HDT_4M QOS_EXT(10000, 10, 40, BIT(4), 2, BIT(2))
+#define HDT_6M QOS_EXT(10000, 10, 40, BIT(4), 2, BIT(3))
+#define HDT_7_5M QOS_EXT(10000, 10, 40, BIT(4), 2, BIT(4))
+#define HDT_IN_2M_OUT_3M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)))
+#define HDT_IN_2M_OUT_4M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)))
+#define HDT_IN_2M_OUT_6M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)))
+#define HDT_IN_2M_OUT_7_5M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)))
+#define HDT_IN_3M_OUT_2M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)))
+#define HDT_IN_3M_OUT_4M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)))
+#define HDT_IN_3M_OUT_6M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)))
+#define HDT_IN_3M_OUT_7_5M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)))
+#define HDT_IN_4M_OUT_2M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)))
+#define HDT_IN_4M_OUT_3M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)))
+#define HDT_IN_4M_OUT_6M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)))
+#define HDT_IN_4M_OUT_7_5M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)))
+#define HDT_IN_6M_OUT_2M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)))
+#define HDT_IN_6M_OUT_3M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)))
+#define HDT_IN_6M_OUT_4M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)))
+#define HDT_IN_6M_OUT_7_5M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)))
+#define HDT_IN_7_5M_OUT_2M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(0)))
+#define HDT_IN_7_5M_OUT_3M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(1)))
+#define HDT_IN_7_5M_OUT_4M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(2)))
+#define HDT_IN_7_5M_OUT_6M \
+	QOS_FULL_EXT(BT_ISO_QOS_CIG_UNSET, BT_ISO_QOS_CIS_UNSET, \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(4)), \
+		QOS_IO_EXT(10000, 10, 40, BIT(4), 2, BIT(3)))
+
 /* One unidirectional CIS. Unicast Server is Audio Sink */
 #define AC_1_4 QOS_OUT(10000, 10, 40, 0x02, 2)
 /* One unidirectional CIS. Unicast Server is Audio Sink CIG 0x01 */
@@ -282,6 +398,28 @@
 	}, \
 }
 
+#define QOS_BCAST_FULL_EXT(_big, _bis, _encryption, _bcode, _in, _out) \
+{ \
+	.version = BT_ISO_QOS_VERSION_1, \
+	.bcast = { \
+		.big = _big, \
+		.bis = _bis, \
+		.sync_factor = 0x07, \
+		.packing = 0x00, \
+		.framing = 0x00, \
+		.in = _in, \
+		.out = _out, \
+		.encryption = _encryption, \
+		.bcode = _bcode, \
+		.options = 0x00, \
+		.skip = 0x0000, \
+		.sync_timeout = BT_ISO_SYNC_TIMEOUT, \
+		.sync_cte_type = 0x00, \
+		.mse = 0x00, \
+		.timeout = BT_ISO_SYNC_TIMEOUT, \
+	}, \
+}
+
 #define BCAST_QOS_OUT(_interval, _latency, _sdu, _phy, _rtn) \
 	QOS_BCAST_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
 		0x00, {0x00}, {}, \
@@ -307,16 +445,38 @@
 		0x00, {0x00}, \
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
 
+#define BCAST_QOS_IN_EXT(_interval, _latency, _sdu, _phy, _rtn, _rates) \
+	QOS_BCAST_FULL_EXT(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
+		0x00, {0x00}, \
+		QOS_IO_EXT(_interval, _latency, _sdu, _phy, _rtn, _rates), {})
+
 #define BCAST_QOS_IN_ENC(_interval, _latency, _sdu, _phy, _rtn) \
 	QOS_BCAST_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
 		0x01, BCODE, \
 		QOS_IO(_interval, _latency, _sdu, _phy, _rtn), {})
 
+#define BCAST_QOS_OUT_EXT(_interval, _latency, _sdu, _phy, _rtn, _rates) \
+	QOS_BCAST_FULL_EXT(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
+		0x00, {0x00}, {}, \
+		QOS_IO_EXT(_interval, _latency, _sdu, _phy, _rtn, _rates))
+
 #define QOS_OUT_16_2_1 BCAST_QOS_OUT(10000, 10, 40, 0x02, 2)
+#define HDT_OUT_16_2_1 BCAST_QOS_OUT(10000, 10, 40, BIT(4), 2)
+#define HDT_OUT_2M BCAST_QOS_OUT_EXT(10000, 10, 40, BIT(4), 2, BIT(0))
+#define HDT_OUT_3M BCAST_QOS_OUT_EXT(10000, 10, 40, BIT(4), 2, BIT(1))
+#define HDT_OUT_4M BCAST_QOS_OUT_EXT(10000, 10, 40, BIT(4), 2, BIT(2))
+#define HDT_OUT_6M BCAST_QOS_OUT_EXT(10000, 10, 40, BIT(4), 2, BIT(3))
+#define HDT_OUT_7_5M BCAST_QOS_OUT_EXT(10000, 10, 40, BIT(4), 2, BIT(4))
 #define QOS_OUT_ENC_16_2_1 BCAST_QOS_OUT_ENC(10000, 10, 40, 0x02, 2)
 #define QOS_OUT_1_16_2_1 BCAST_QOS_OUT_1(10000, 10, 40, 0x02, 2)
 #define QOS_OUT_1_1_16_2_1 BCAST_QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
 #define QOS_IN_16_2_1 BCAST_QOS_IN(10000, 10, 40, 0x02, 2)
+#define HDT_IN_16_2_1 BCAST_QOS_IN(10000, 10, 40, BIT(4), 2)
+#define HDT_IN_2M BCAST_QOS_IN_EXT(10000, 10, 40, BIT(4), 2, BIT(0))
+#define HDT_IN_3M BCAST_QOS_IN_EXT(10000, 10, 40, BIT(4), 2, BIT(1))
+#define HDT_IN_4M BCAST_QOS_IN_EXT(10000, 10, 40, BIT(4), 2, BIT(2))
+#define HDT_IN_6M BCAST_QOS_IN_EXT(10000, 10, 40, BIT(4), 2, BIT(3))
+#define HDT_IN_7_5M BCAST_QOS_IN_EXT(10000, 10, 40, BIT(4), 2, BIT(4))
 #define QOS_IN_ENC_16_2_1 BCAST_QOS_IN_ENC(10000, 10, 40, 0x02, 2)
 #define QOS_OUT_48_1_g BCAST_QOS_OUT(7500, 8, 75, 0x02, 1)
 #define QOS_OUT_48_2_g BCAST_QOS_OUT(10000, 10, 100, 0x02, 1)
@@ -483,8 +643,17 @@ struct test_data {
 	int seqnum;
 };
 
+enum {
+	BT_ISO_QOS_V1 = 0,
+	BT_ISO_QOS_EXT,
+};
+
 struct iso_client_data {
-	struct bt_iso_qos qos;
+	uint8_t qos_ver;
+	union {
+		struct bt_iso_qos qos;
+		struct bt_iso_qos_ext qos_ext;
+	};
 	struct bt_iso_qos qos_2;
 	int expect_err;
 	const struct iovec *send;
@@ -525,6 +694,13 @@ struct iso_client_data {
 	 * Used for testing TX timestamping OPT_ID.
 	 */
 	unsigned int repeat_send;
+
+	/* Configure def_mic_len as the default MIC length and check that
+	 * the resulting LE Set CIG Parameters or LE Create BIG carries it.
+	 * HDT is 64-bit or 128-bit only, 32-bit being GFSK, so 0x00 is not
+	 * a value to test for and doubles as unset.
+	 */
+	uint8_t def_mic_len;
 };
 
 typedef bool (*iso_defer_accept_t)(struct test_data *data, struct tester_io *io,
@@ -637,9 +813,9 @@ static void read_index_list_callback(uint8_t status, uint16_t length,
 	mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
 					index_removed_callback, NULL, NULL);
 
-	data->hciemu = hciemu_new_num(HCIEMU_TYPE_BREDRLE52, data->client_num);
+	data->hciemu = hciemu_new_num(data->hciemu_type, data->client_num);
 	if (!data->hciemu)
-		data->hciemu = hciemu_new_num_debug(HCIEMU_TYPE_BREDRLE52,
+		data->hciemu = hciemu_new_num_debug(data->hciemu_type,
 						data->client_num, hciemu_debug,
 						"hciemu: ", NULL);
 	if (!data->hciemu) {
@@ -753,13 +929,13 @@ static void test_data_free(void *test_data)
 	free(data);
 }
 
-#define test_iso_full(name, data, setup, func, num, reason) \
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
-		user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \
@@ -768,14 +944,21 @@ static void test_data_free(void *test_data)
 				test_post_teardown, 2, user, test_data_free); \
 	} while (0)
 
+#define test_le52(name, data, setup, func, num, reason) \
+	test_iso_full(name, HCIEMU_TYPE_BREDRLE52, data, setup, func, num, \
+			reason)
+
 #define test_iso(name, data, setup, func) \
-	test_iso_full(name, data, setup, func, 1, 0x00)
+	test_le52(name, data, setup, func, 1, 0x00)
 
 #define test_iso2(name, data, setup, func) \
-	test_iso_full(name, data, setup, func, 2, 0x00)
+	test_le52(name, data, setup, func, 2, 0x00)
 
 #define test_iso_rej(name, data, setup, func, reason) \
-	test_iso_full(name, data, setup, func, 1, reason)
+	test_le52(name, data, setup, func, 1, reason)
+
+#define test_bredrle70(name, data, setup, func) \
+	test_iso_full(name, HCIEMU_TYPE_BREDRLE70, data, setup, func, 1, 0x00)
 
 static const struct iso_client_data connect_8_1_1 = {
 	.qos = QOS_8_1_1,
@@ -797,6 +980,175 @@ static const struct iso_client_data connect_16_2_1 = {
 	.expect_err = 0
 };
 
+static const struct iso_client_data connect_hdt_16_2_1 = {
+	.qos = HDT_16_2_1,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_2m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_2M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_3m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_3M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_4m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_4M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_6m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_6M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_7_5m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_7_5M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_mic_len_64 = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_7_5M,
+	.expect_err = 0,
+	.def_mic_len = 0x01,
+};
+
+static const struct iso_client_data connect_hdt_mic_len_128 = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_7_5M,
+	.expect_err = 0,
+	.def_mic_len = 0x02,
+};
+
+static const struct iso_client_data connect_hdt_2m_3m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_3M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_2m_4m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_4M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_2m_6m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_6M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_2m_7_5m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_7_5M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_3m_2m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_2M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_3m_4m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_4M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_3m_6m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_6M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_3m_7_5m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_7_5M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_4m_2m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_2M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_4m_3m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_3M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_4m_6m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_6M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_4m_7_5m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_7_5M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_6m_2m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_2M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_6m_3m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_3M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_6m_4m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_4M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_6m_7_5m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_7_5M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_7_5m_2m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_2M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_7_5m_3m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_3M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_7_5m_4m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_4M,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_hdt_7_5m_6m = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_6M,
+	.expect_err = 0
+};
+
 static const struct iso_client_data connect_1_16_2_1 = {
 	.qos = QOS_1_16_2_1,
 	.expect_err = 0
@@ -1086,176 +1438,383 @@ static const struct iso_client_data listen_16_2_1_recv = {
 	.server = true,
 };
 
-static const struct iso_client_data listen_16_2_1_recv_frag = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_16_2_1_recv = {
+	.qos = HDT_16_2_1,
 	.expect_err = 0,
-	.recv = &send_large,
+	.recv = &send_16_2_1,
 	.server = true,
 };
 
-static const struct iso_client_data listen_16_2_1_recv_ts = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_2m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_2M,
 	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.server = true,
-	.ts = true,
 };
 
-static const struct iso_client_data listen_16_2_1_recv_pkt_status = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_3m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_3M,
 	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.server = true,
-	.pkt_status = 0x02,
 };
 
-static const struct iso_client_data listen_16_2_1_recv_pkt_seqnum = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_4m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_4M,
 	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.server = true,
-	.pkt_seqnum = true,
 };
 
-static const struct iso_client_data listen_16_2_1_recv_rx_timestamping = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_6m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_6M,
 	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.server = true,
-	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
-					SOF_TIMESTAMPING_RX_SOFTWARE),
 };
 
-static const struct iso_client_data listen_16_2_1_recv_hw_timestamping = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_7_5m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_7_5M,
 	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.server = true,
-	.ts = true,
-	.so_timestamping = (SOF_TIMESTAMPING_RAW_HARDWARE |
-					SOF_TIMESTAMPING_RX_HARDWARE),
 };
 
-static const struct iso_client_data listen_16_2_1_recv_frag_hw_timestamping = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_2m_3m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_3M,
 	.expect_err = 0,
-	.recv = &send_large,
+	.recv = &send_16_2_1,
 	.server = true,
-	.ts = true,
-	.so_timestamping = (SOF_TIMESTAMPING_RAW_HARDWARE |
-					SOF_TIMESTAMPING_RX_HARDWARE),
 };
 
-static const struct iso_client_data defer_16_2_1 = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_2m_4m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_4M,
 	.expect_err = 0,
-	.defer = true,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data defer_1_16_2_1 = {
-	.qos = QOS_1_16_2_1,
+static const struct iso_client_data listen_hdt_2m_6m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_6M,
 	.expect_err = 0,
-	.defer = true,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data connect_16_2_1_defer_send = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_2m_7_5m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M_OUT_7_5M,
 	.expect_err = 0,
-	.send = &send_16_2_1,
-	.defer = true,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data connect_48_2_1_defer_send = {
-	.qos = QOS_48_2_1,
+static const struct iso_client_data listen_hdt_3m_2m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_2M,
 	.expect_err = 0,
-	.send = &send_16_2_1,
-	.defer = true,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data listen_16_2_1_defer_recv = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_3m_4m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_4M,
 	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.server = true,
-	.defer = true,
 };
 
-static const struct iso_client_data listen_48_2_1_defer_recv = {
-	.qos = QOS_48_2_1,
+static const struct iso_client_data listen_hdt_3m_6m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_6M,
 	.expect_err = 0,
-	.recv = &send_48_2_1,
+	.recv = &send_16_2_1,
 	.server = true,
-	.defer = true,
 };
 
-static const struct iso_client_data listen_16_2_1_defer_reject = {
-	.qos = QOS_16_2_1,
-	.expect_err = -1,
+static const struct iso_client_data listen_hdt_3m_7_5m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M_OUT_7_5M,
+	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.server = true,
-	.defer = true,
 };
 
-static const struct iso_client_data connect_16_2_1_send_recv = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_4m_2m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_2M,
 	.expect_err = 0,
-	.send = &send_16_2_1,
 	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data disconnect_16_2_1 = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_4m_3m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_3M,
 	.expect_err = 0,
-	.disconnect = true,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data suspend_16_2_1 = {
-	.qos = QOS_16_2_1,
-	.suspend = true,
+static const struct iso_client_data listen_hdt_4m_6m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_6M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data reconnect_16_2_1 = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_4m_7_5m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M_OUT_7_5M,
 	.expect_err = 0,
-	.disconnect = true,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data reconnect_16_2_1_send_recv = {
-	.qos = QOS_16_2_1,
+static const struct iso_client_data listen_hdt_6m_2m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_2M,
 	.expect_err = 0,
-	.send = &send_16_2_1,
 	.recv = &send_16_2_1,
-	.disconnect = true,
+	.server = true,
 };
 
-static const struct iso_client_data connect_ac_1_4 = {
-	.qos = AC_1_4,
-	.expect_err = 0
+static const struct iso_client_data listen_hdt_6m_3m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_3M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data connect_ac_2_10 = {
-	.qos = AC_2_10,
-	.expect_err = 0
+static const struct iso_client_data listen_hdt_6m_4m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_4M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data connect_ac_3_5 = {
-	.qos = AC_3_5,
-	.expect_err = 0
+static const struct iso_client_data listen_hdt_6m_7_5m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M_OUT_7_5M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data connect_ac_6i = {
-	.qos = AC_6i_1,
-	.qos_2 = AC_6i_2,
+static const struct iso_client_data listen_hdt_7_5m_2m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_2M,
 	.expect_err = 0,
-	.mconn = true,
-	.defer = true,
+	.recv = &send_16_2_1,
+	.server = true,
 };
 
-static const struct iso_client_data reconnect_ac_6i = {
-	.qos = AC_6i_1,
-	.qos_2 = AC_6i_2,
+static const struct iso_client_data listen_hdt_7_5m_3m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_3M,
 	.expect_err = 0,
-	.mconn = true,
+	.recv = &send_16_2_1,
+	.server = true,
+};
+
+static const struct iso_client_data listen_hdt_7_5m_4m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_4M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+};
+
+static const struct iso_client_data listen_hdt_7_5m_6m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M_OUT_6M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+};
+
+static const struct iso_client_data listen_16_2_1_recv_frag = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_large,
+	.server = true,
+};
+
+static const struct iso_client_data listen_16_2_1_recv_ts = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.ts = true,
+};
+
+static const struct iso_client_data listen_16_2_1_recv_pkt_status = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.pkt_status = 0x02,
+};
+
+static const struct iso_client_data listen_16_2_1_recv_pkt_seqnum = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.pkt_seqnum = true,
+};
+
+static const struct iso_client_data listen_16_2_1_recv_rx_timestamping = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_RX_SOFTWARE),
+};
+
+static const struct iso_client_data listen_16_2_1_recv_hw_timestamping = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.ts = true,
+	.so_timestamping = (SOF_TIMESTAMPING_RAW_HARDWARE |
+					SOF_TIMESTAMPING_RX_HARDWARE),
+};
+
+static const struct iso_client_data listen_16_2_1_recv_frag_hw_timestamping = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_large,
+	.server = true,
+	.ts = true,
+	.so_timestamping = (SOF_TIMESTAMPING_RAW_HARDWARE |
+					SOF_TIMESTAMPING_RX_HARDWARE),
+};
+
+static const struct iso_client_data defer_16_2_1 = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+};
+
+static const struct iso_client_data defer_1_16_2_1 = {
+	.qos = QOS_1_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_16_2_1_defer_send = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_48_2_1_defer_send = {
+	.qos = QOS_48_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.defer = true,
+};
+
+static const struct iso_client_data listen_16_2_1_defer_recv = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.server = true,
+	.defer = true,
+};
+
+static const struct iso_client_data listen_48_2_1_defer_recv = {
+	.qos = QOS_48_2_1,
+	.expect_err = 0,
+	.recv = &send_48_2_1,
+	.server = true,
+	.defer = true,
+};
+
+static const struct iso_client_data listen_16_2_1_defer_reject = {
+	.qos = QOS_16_2_1,
+	.expect_err = -1,
+	.recv = &send_16_2_1,
+	.server = true,
+	.defer = true,
+};
+
+static const struct iso_client_data connect_16_2_1_send_recv = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.recv = &send_16_2_1,
+};
+
+static const struct iso_client_data disconnect_16_2_1 = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.disconnect = true,
+};
+
+static const struct iso_client_data suspend_16_2_1 = {
+	.qos = QOS_16_2_1,
+	.suspend = true,
+};
+
+static const struct iso_client_data reconnect_16_2_1 = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.disconnect = true,
+};
+
+static const struct iso_client_data reconnect_16_2_1_send_recv = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.recv = &send_16_2_1,
+	.disconnect = true,
+};
+
+static const struct iso_client_data connect_ac_1_4 = {
+	.qos = AC_1_4,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_ac_2_10 = {
+	.qos = AC_2_10,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_ac_3_5 = {
+	.qos = AC_3_5,
+	.expect_err = 0
+};
+
+static const struct iso_client_data connect_ac_6i = {
+	.qos = AC_6i_1,
+	.qos_2 = AC_6i_2,
+	.expect_err = 0,
+	.mconn = true,
+	.defer = true,
+};
+
+static const struct iso_client_data reconnect_ac_6i = {
+	.qos = AC_6i_1,
+	.qos_2 = AC_6i_2,
+	.expect_err = 0,
+	.mconn = true,
 	.defer = true,
 	.disconnect = true,
 };
@@ -1412,6 +1971,76 @@ static const struct iso_client_data bcast_16_2_1_send = {
 	.base_len = sizeof(base_lc3_16_2_1),
 };
 
+static const struct iso_client_data bcast_hdt_16_2_1_send = {
+	.qos = HDT_OUT_16_2_1,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_hdt_2m_send = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_OUT_2M,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_hdt_3m_send = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_OUT_3M,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_hdt_4m_send = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_OUT_4M,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_hdt_6m_send = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_OUT_6M,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
+static const struct iso_client_data bcast_hdt_mic_len_64_send = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_OUT_7_5M,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+	.def_mic_len = 0x01,
+};
+
+static const struct iso_client_data bcast_hdt_7_5m_send = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_OUT_7_5M,
+	.expect_err = 0,
+	.send = &send_16_2_1,
+	.bcast = true,
+	.base = base_lc3_16_2_1,
+	.base_len = sizeof(base_lc3_16_2_1),
+};
+
 static const struct iso_client_data past_16_2_1_send = {
 	.qos = QOS_OUT_16_2_1,
 	.expect_err = 0,
@@ -1490,8 +2119,67 @@ static const struct iso_client_data bcast_16_2_1_reconnect = {
 	.disconnect = true,
 };
 
-static const struct iso_client_data bcast_16_2_1_recv = {
-	.qos = QOS_IN_16_2_1,
+static const struct iso_client_data bcast_16_2_1_recv = {
+	.qos = QOS_IN_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_hdt_16_2_1_recv = {
+	.qos = HDT_IN_16_2_1,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_hdt_2m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_2M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_hdt_3m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_3M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_hdt_4m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_4M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_hdt_6m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_6M,
+	.expect_err = 0,
+	.recv = &send_16_2_1,
+	.bcast = true,
+	.server = true,
+	.big = true,
+};
+
+static const struct iso_client_data bcast_hdt_7_5m_recv = {
+	.qos_ver = BT_ISO_QOS_EXT,
+	.qos_ext = HDT_IN_7_5M,
 	.expect_err = 0,
 	.recv = &send_16_2_1,
 	.bcast = true,
@@ -1787,6 +2475,48 @@ static void acl_new_conn(uint16_t handle, void *user_data)
 	}
 }
 
+/* The QoS of the test as struct bt_iso_qos, converting struct bt_iso_qos_ext
+ * when the test uses it, for the emulated remote which takes the former. The
+ * unicast QoS is a prefix of the broadcast one, so converting the broadcast
+ * view converts either.
+ */
+static void iso_client_qos(const struct iso_client_data *isodata,
+						struct bt_iso_qos *qos)
+{
+	const struct bt_iso_bcast_qos_ext *ext = &isodata->qos_ext.bcast;
+	struct bt_iso_bcast_qos *b = &qos->bcast;
+
+	if (isodata->qos_ver != BT_ISO_QOS_EXT) {
+		*qos = isodata->qos;
+		return;
+	}
+
+	memset(qos, 0, sizeof(*qos));
+	b->big = ext->big;
+	b->bis = ext->bis;
+	b->sync_factor = ext->sync_factor;
+	b->packing = ext->packing;
+	b->framing = ext->framing;
+	b->in.interval = ext->in.interval;
+	b->in.latency = ext->in.latency;
+	b->in.sdu = ext->in.sdu;
+	b->in.phys = ext->in.phys;
+	b->in.rtn = ext->in.rtn;
+	b->out.interval = ext->out.interval;
+	b->out.latency = ext->out.latency;
+	b->out.sdu = ext->out.sdu;
+	b->out.phys = ext->out.phys;
+	b->out.rtn = ext->out.rtn;
+	b->encryption = ext->encryption;
+	memcpy(b->bcode, ext->bcode, sizeof(b->bcode));
+	b->options = ext->options;
+	b->skip = ext->skip;
+	b->sync_timeout = ext->sync_timeout;
+	b->sync_cte_type = ext->sync_cte_type;
+	b->mse = ext->mse;
+	b->timeout = ext->timeout;
+}
+
 static void setup_connect_recv(struct test_data *data, struct bthost *host)
 {
 	const uint8_t *bdaddr;
@@ -1884,10 +2614,13 @@ static void setup_powered_callback(uint8_t status, uint16_t length,
 							isodata->base_len);
 
 			if (isodata->big && (!isodata->past ||
-						i + 1 == data->client_num))
-				bthost_create_big(host, 1,
-						isodata->qos.bcast.encryption,
-						isodata->qos.bcast.bcode);
+						i + 1 == data->client_num)) {
+				struct bt_iso_qos qos;
+
+				iso_client_qos(isodata, &qos);
+				bthost_create_big(host, 1, qos.bcast.encryption,
+							qos.bcast.bcode);
+			}
 
 			if (isodata->past)
 				setup_past_recv(data, host);
@@ -1897,6 +2630,66 @@ static void setup_powered_callback(uint8_t status, uint16_t length,
 	}
 }
 
+static void check_mic_len(struct test_data *data, uint8_t mic_len)
+{
+	const struct iso_client_data *isodata = data->test_data;
+
+	tester_print("MIC length: 0x%02x", mic_len);
+
+	if (mic_len != isodata->def_mic_len) {
+		tester_warn("Expected MIC length 0x%02x, got 0x%02x",
+				isodata->def_mic_len, mic_len);
+		tester_test_failed();
+	}
+}
+
+static bool hook_cig_mic_len(const void *msg, uint16_t len, void *user_data)
+{
+	const struct bt_hci_cmd_le_set_cig_params_v2 *cmd = msg;
+
+	if (len < sizeof(*cmd) + sizeof(*cmd->cis))
+		return true;
+
+	check_mic_len(user_data, cmd->cis[0].mic_len);
+
+	return true;
+}
+
+static bool hook_big_mic_len(const void *msg, uint16_t len, void *user_data)
+{
+	const struct bt_hci_cmd_le_create_big_v2 *cmd = msg;
+
+	if (len < sizeof(*cmd))
+		return true;
+
+	check_mic_len(user_data, cmd->bis.mic_len);
+
+	return true;
+}
+
+static void setup_mic_len(struct test_data *data, uint8_t mic_len)
+{
+	uint8_t param[] = {
+		0x21, 0x00,	/* Type: LE HDT Default MIC Length */
+		0x01,		/* Length */
+		0x00,		/* Value */
+	};
+
+	param[3] = mic_len;
+
+	tester_print("Setting default MIC length to 0x%02x", mic_len);
+
+	mgmt_send(data->mgmt, MGMT_OP_SET_DEF_SYSTEM_CONFIG, data->mgmt_index,
+				sizeof(param), param, NULL, NULL, NULL);
+
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_CMD,
+				BT_HCI_CMD_LE_SET_CIG_PARAMS_V2,
+				hook_cig_mic_len, data);
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_CMD,
+				BT_HCI_CMD_LE_CREATE_BIG_V2,
+				hook_big_mic_len, data);
+}
+
 static void setup_powered(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
@@ -1905,6 +2698,9 @@ static void setup_powered(const void *test_data)
 
 	tester_print("Powering on controller");
 
+	if (isodata && isodata->def_mic_len)
+		setup_mic_len(data, isodata->def_mic_len);
+
 	if (!isodata || !isodata->bcast || isodata->past)
 		mgmt_send(data->mgmt, MGMT_OP_SET_CONNECTABLE, data->mgmt_index,
 					sizeof(param), param,
@@ -2108,6 +2904,7 @@ static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
 	struct hciemu_client *client;
 	const uint8_t *client_bdaddr = NULL;
 	const struct bt_iso_qos *qos = &isodata->qos;
+	const struct bt_iso_qos_ext *qos_ext = &isodata->qos_ext;
 	struct sockaddr_iso addr;
 	char str[18];
 	int err;
@@ -2146,7 +2943,21 @@ static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
 		}
 	}
 
-	err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, qos, sizeof(*qos));
+	switch (isodata->qos_ver) {
+	case BT_ISO_QOS_V1:
+		err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, qos,
+						sizeof(*qos));
+		break;
+	case BT_ISO_QOS_EXT:
+		err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, qos_ext,
+						sizeof(*qos_ext));
+		break;
+	default:
+		tester_warn("Undefined qos_ver %u", isodata->qos_ver);
+		tester_test_failed();
+		return -EINVAL;
+	}
+
 	if (err < 0) {
 		tester_warn("Can't set socket BT_ISO_QOS option : %s (%d)",
 							strerror(errno), errno);
@@ -2154,41 +2965,260 @@ static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
 		return -EINVAL;
 	}
 
-	if (isodata->defer || (isodata->bcast && isodata->mconn && !num)) {
-		int opt = 1;
-
-		if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &opt,
-							sizeof(opt)) < 0) {
-			tester_print("Can't enable deferred setup: %s (%d)",
-						strerror(errno), errno);
-			tester_test_failed();
-			return -EINVAL;
-		}
+	if (isodata->defer || (isodata->bcast && isodata->mconn && !num)) {
+		int opt = 1;
+
+		if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &opt,
+							sizeof(opt)) < 0) {
+			tester_print("Can't enable deferred setup: %s (%d)",
+						strerror(errno), errno);
+			tester_test_failed();
+			return -EINVAL;
+		}
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.iso_family = AF_BLUETOOTH;
+	bacpy(&addr.iso_bdaddr, client_bdaddr ? (void *) client_bdaddr :
+							BDADDR_ANY);
+	addr.iso_bdaddr_type = BDADDR_LE_PUBLIC;
+
+	ba2str(&addr.iso_bdaddr, str);
+
+	tester_print("Connecting to %s...", str);
+
+	err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
+		err = -errno;
+		tester_warn("Can't connect socket: %s (%d)", strerror(errno),
+									errno);
+		return err;
+	}
+
+	return 0;
+}
+
+static uint8_t bit_phy(uint8_t bits)
+{
+	uint8_t phy = 0x00;
+
+	/* Convert PHY bits to PHY values on a ascending order so if HDT bit is
+	 * set it takes precedence over LE 2M and LE 1M.
+	 */
+	if (bits & BIT(0))
+		phy = 0x01; /* LE 1M */
+
+	if (bits & BIT(1))
+		phy = 0x02; /* LE 2M */
+
+	if (bits & BIT(2))
+		phy = 0x03; /* LE Coded */
+
+	if (bits & BIT(4))
+		phy = 0x05; /* HDT */
+
+	return phy;
+}
+
+static bool check_io_qos(const struct bt_iso_io_qos *io1,
+				const struct bt_iso_io_qos *io2)
+{
+	if (io1->interval && io2->interval && io1->interval > io2->interval) {
+		tester_warn("Unexpected IO interval: %u > %u",
+				io1->interval, io2->interval);
+		return false;
+	}
+
+	if (io1->latency && io2->latency && io1->latency > io2->latency) {
+		tester_warn("Unexpected IO latency: %u > %u",
+				io1->latency, io2->latency);
+		return false;
+	}
+
+	if (io1->sdu && io2->sdu && io1->sdu != io2->sdu) {
+		tester_warn("Unexpected IO SDU: %u != %u", io1->sdu, io2->sdu);
+		return false;
+	}
+
+	if (io1->phys && io2->phys && io1->phys != io2->phys &&
+			io1->phys != bit_phy(io2->phys) &&
+			bit_phy(io1->phys) != io2->phys) {
+		tester_warn("Unexpected IO PHY: 0x%02x != 0x%02x",
+				io1->phys, io2->phys);
+		return false;
+	}
+
+	if (io1->rtn && io2->rtn && io1->rtn != io2->rtn) {
+		tester_warn("Unexpected IO RTN: %u != %u", io1->rtn, io2->rtn);
+		return false;
+	}
+
+	return true;
+}
+
+static bool check_ucast_qos(const struct bt_iso_qos *qos1,
+				const struct bt_iso_qos *qos2,
+				const struct bt_iso_qos *qos2_2)
+{
+	if (qos1->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
+			qos2->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
+			qos1->ucast.cig != qos2->ucast.cig) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
+		tester_warn("Unexpected CIG ID: 0x%02x != 0x%02x",
+				qos1->ucast.cig, qos2->ucast.cig);
+		return false;
+	}
+
+	if (qos1->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
+			qos2->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
+			qos1->ucast.cis != qos2->ucast.cis) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
+		tester_warn("Unexpected CIS ID: 0x%02x != 0x%02x",
+				qos1->ucast.cis, qos2->ucast.cis);
+		return false;
+	}
+
+	if (qos1->ucast.packing != qos2->ucast.packing) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
+		tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
+				qos1->ucast.packing, qos2->ucast.packing);
+		return false;
+	}
+
+	if (qos1->ucast.framing != qos2->ucast.framing) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
+		tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
+				qos1->ucast.framing, qos2->ucast.framing);
+		return false;
+	}
+
+	if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
+		tester_warn("Unexpected Input QoS");
+		return false;
+	}
+
+	if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
+		if (qos2_2)
+			return check_ucast_qos(qos1, qos2_2, NULL);
+
+		tester_warn("Unexpected Output QoS");
+		return false;
+	}
+
+	return true;
+}
+
+static bool check_bcast_qos(const struct bt_iso_qos *qos1,
+				const struct bt_iso_qos *qos2)
+{
+	if (qos1->bcast.big != BT_ISO_QOS_BIG_UNSET &&
+			qos2->bcast.big != BT_ISO_QOS_BIG_UNSET &&
+			qos1->bcast.big != qos2->bcast.big) {
+		tester_warn("Unexpected BIG ID: 0x%02x != 0x%02x",
+				qos1->bcast.big, qos2->bcast.big);
+		return false;
+	}
+
+	if (qos1->bcast.bis != BT_ISO_QOS_BIS_UNSET &&
+			qos2->bcast.bis != BT_ISO_QOS_BIS_UNSET &&
+			qos1->bcast.bis != qos2->bcast.bis) {
+		tester_warn("Unexpected BIS ID: 0x%02x != 0x%02x",
+				qos1->bcast.bis, qos2->bcast.bis);
+		return false;
+	}
+
+	if (qos1->bcast.sync_factor != qos2->bcast.sync_factor) {
+		tester_warn("Unexpected QoS sync interval: 0x%02x != 0x%02x",
+			qos1->bcast.sync_factor, qos2->bcast.sync_factor);
+		return false;
+	}
+
+	if (qos1->bcast.packing != qos2->bcast.packing) {
+		tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
+				qos1->bcast.packing, qos2->bcast.packing);
+		return false;
+	}
+
+	if (qos1->bcast.framing != qos2->bcast.framing) {
+		tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
+				qos1->bcast.framing, qos2->bcast.framing);
+		return false;
+	}
+
+	if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
+		tester_warn("Unexpected Input QoS");
+		return false;
+	}
+
+	if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
+		tester_warn("Unexpected Output QoS");
+		return false;
+	}
+
+	if (qos1->bcast.encryption != qos2->bcast.encryption) {
+		tester_warn("Unexpected QoS encryption: 0x%02x != 0x%02x",
+				qos1->bcast.encryption, qos2->bcast.encryption);
+		return false;
+	}
+
+	if (memcmp(qos1->bcast.bcode, qos2->bcast.bcode,
+				sizeof(qos1->bcast.bcode))) {
+		tester_warn("Unexpected QoS Broadcast Code");
+		return false;
+	}
+
+	if (qos1->bcast.options != qos2->bcast.options) {
+		tester_warn("Unexpected QoS options: 0x%02x != 0x%02x",
+				qos1->bcast.options, qos2->bcast.options);
+		return false;
+	}
+
+	if (qos1->bcast.skip != qos2->bcast.skip) {
+		tester_warn("Unexpected QoS skip: 0x%04x != 0x%04x",
+				qos1->bcast.skip, qos2->bcast.skip);
+		return false;
 	}
 
-	memset(&addr, 0, sizeof(addr));
-	addr.iso_family = AF_BLUETOOTH;
-	bacpy(&addr.iso_bdaddr, client_bdaddr ? (void *) client_bdaddr :
-							BDADDR_ANY);
-	addr.iso_bdaddr_type = BDADDR_LE_PUBLIC;
+	if (qos1->bcast.sync_timeout != qos2->bcast.sync_timeout) {
+		tester_warn("Unexpected QoS sync timeout: 0x%04x != 0x%04x",
+			qos1->bcast.sync_timeout, qos2->bcast.sync_timeout);
+		return false;
+	}
 
-	ba2str(&addr.iso_bdaddr, str);
+	if (qos1->bcast.sync_cte_type != qos2->bcast.sync_cte_type) {
+		tester_warn("Unexpected QoS sync cte type: 0x%02x != 0x%02x",
+			qos1->bcast.sync_cte_type, qos2->bcast.sync_cte_type);
+		return false;
+	}
 
-	tester_print("Connecting to %s...", str);
+	if (qos1->bcast.mse != qos2->bcast.mse) {
+		tester_warn("Unexpected QoS MSE: 0x%02x != 0x%02x",
+				qos1->bcast.mse, qos2->bcast.mse);
+		return false;
+	}
 
-	err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
-	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
-		err = -errno;
-		tester_warn("Can't connect socket: %s (%d)", strerror(errno),
-									errno);
-		return err;
+	if (qos1->bcast.timeout != qos2->bcast.timeout) {
+		tester_warn("Unexpected QoS MSE: 0x%04x != 0x%04x",
+				qos1->bcast.timeout, qos2->bcast.timeout);
+		return false;
 	}
 
-	return 0;
+	return true;
 }
 
-static bool check_io_qos(const struct bt_iso_io_qos *io1,
-				const struct bt_iso_io_qos *io2)
+static bool check_io_qos_ext(const struct bt_iso_io_qos_ext *io1,
+				const struct bt_iso_io_qos_ext *io2)
 {
 	if (io1->interval && io2->interval && io1->interval > io2->interval) {
 		tester_warn("Unexpected IO interval: %u > %u",
@@ -2207,8 +3237,10 @@ static bool check_io_qos(const struct bt_iso_io_qos *io1,
 		return false;
 	}
 
-	if (io1->phys && io2->phys && io1->phys != io2->phys) {
-		tester_warn("Unexpected IO PHY: 0x%02x != 0x%02x",
+	if (io1->phys && io2->phys && io1->phys != io2->phys &&
+			io1->phys != bit_phy(io2->phys) &&
+			bit_phy(io1->phys) != io2->phys) {
+		tester_warn("Unexpected IO PHYs: 0x%02x != 0x%02x",
 				io1->phys, io2->phys);
 		return false;
 	}
@@ -2218,19 +3250,21 @@ static bool check_io_qos(const struct bt_iso_io_qos *io1,
 		return false;
 	}
 
+	if (io1->rates && io2->rates && io1->rates != io2->rates) {
+		tester_warn("Unexpected IO rates: 0x%04x != 0x%04x",
+				io1->rates, io2->rates);
+		return false;
+	}
+
 	return true;
 }
 
-static bool check_ucast_qos(const struct bt_iso_qos *qos1,
-				const struct bt_iso_qos *qos2,
-				const struct bt_iso_qos *qos2_2)
+static bool check_ucast_qos_ext(const struct bt_iso_qos_ext *qos1,
+				const struct bt_iso_qos_ext *qos2)
 {
 	if (qos1->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
 			qos2->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
 			qos1->ucast.cig != qos2->ucast.cig) {
-		if (qos2_2)
-			return check_ucast_qos(qos1, qos2_2, NULL);
-
 		tester_warn("Unexpected CIG ID: 0x%02x != 0x%02x",
 				qos1->ucast.cig, qos2->ucast.cig);
 		return false;
@@ -2239,44 +3273,29 @@ static bool check_ucast_qos(const struct bt_iso_qos *qos1,
 	if (qos1->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
 			qos2->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
 			qos1->ucast.cis != qos2->ucast.cis) {
-		if (qos2_2)
-			return check_ucast_qos(qos1, qos2_2, NULL);
-
 		tester_warn("Unexpected CIS ID: 0x%02x != 0x%02x",
 				qos1->ucast.cis, qos2->ucast.cis);
 		return false;
 	}
 
 	if (qos1->ucast.packing != qos2->ucast.packing) {
-		if (qos2_2)
-			return check_ucast_qos(qos1, qos2_2, NULL);
-
 		tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
 				qos1->ucast.packing, qos2->ucast.packing);
 		return false;
 	}
 
 	if (qos1->ucast.framing != qos2->ucast.framing) {
-		if (qos2_2)
-			return check_ucast_qos(qos1, qos2_2, NULL);
-
 		tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
 				qos1->ucast.framing, qos2->ucast.framing);
 		return false;
 	}
 
-	if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
-		if (qos2_2)
-			return check_ucast_qos(qos1, qos2_2, NULL);
-
+	if (!check_io_qos_ext(&qos1->ucast.in, &qos2->ucast.in)) {
 		tester_warn("Unexpected Input QoS");
 		return false;
 	}
 
-	if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
-		if (qos2_2)
-			return check_ucast_qos(qos1, qos2_2, NULL);
-
+	if (!check_io_qos_ext(&qos1->ucast.out, &qos2->ucast.out)) {
 		tester_warn("Unexpected Output QoS");
 		return false;
 	}
@@ -2284,8 +3303,8 @@ static bool check_ucast_qos(const struct bt_iso_qos *qos1,
 	return true;
 }
 
-static bool check_bcast_qos(const struct bt_iso_qos *qos1,
-				const struct bt_iso_qos *qos2)
+static bool check_bcast_qos_ext(const struct bt_iso_qos_ext *qos1,
+				const struct bt_iso_qos_ext *qos2)
 {
 	if (qos1->bcast.big != BT_ISO_QOS_BIG_UNSET &&
 			qos2->bcast.big != BT_ISO_QOS_BIG_UNSET &&
@@ -2321,12 +3340,12 @@ static bool check_bcast_qos(const struct bt_iso_qos *qos1,
 		return false;
 	}
 
-	if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
+	if (!check_io_qos_ext(&qos1->ucast.in, &qos2->ucast.in)) {
 		tester_warn("Unexpected Input QoS");
 		return false;
 	}
 
-	if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
+	if (!check_io_qos_ext(&qos1->ucast.out, &qos2->ucast.out)) {
 		tester_warn("Unexpected Output QoS");
 		return false;
 	}
@@ -2888,15 +3907,30 @@ static bool iso_connect(struct tester_io *io, uint32_t cond,
 	int err, sk_err, sk;
 	socklen_t len;
 	struct bt_iso_qos qos;
+	struct bt_iso_qos_ext qos_ext;
 	bool ret = true;
 	uint8_t base[BASE_MAX_LENGTH] = {0};
 
 	sk = tester_io_get_fd(io);
 
-	len = sizeof(qos);
-	memset(&qos, 0, len);
+	switch (isodata->qos_ver) {
+	case BT_ISO_QOS_V1:
+		len = sizeof(qos);
+		memset(&qos, 0, len);
+		err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len);
+		break;
+	case BT_ISO_QOS_EXT:
+		len = sizeof(qos_ext);
+		memset(&qos_ext, 0, len);
+		err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos_ext, &len);
+		break;
+	default:
+		tester_warn("Invalid BT_ISO_QOS version");
+		data->step = 0;
+		tester_test_failed();
+		return false;
+	}
 
-	err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len);
 	if (err < 0) {
 		tester_warn("Can't get socket option : %s (%d)",
 							strerror(errno), errno);
@@ -2906,12 +3940,26 @@ static bool iso_connect(struct tester_io *io, uint32_t cond,
 	}
 
 	if (!isodata->bcast) {
-		ret = check_ucast_qos(&qos, &isodata->qos,
+		switch (isodata->qos_ver) {
+		case BT_ISO_QOS_V1:
+			ret = check_ucast_qos(&qos, &isodata->qos,
 				      isodata->mconn ? &isodata->qos_2 : NULL);
+			break;
+		case BT_ISO_QOS_EXT:
+			ret = check_ucast_qos_ext(&qos_ext, &isodata->qos_ext);
+			break;
+		}
 	} else if (!isodata->server) {
-		ret = check_bcast_qos(&qos, &isodata->qos);
-		if (ret && isodata->past)
-			ret = iso_rebind_bcast_dst(data, sk) == 0;
+		switch (isodata->qos_ver) {
+		case BT_ISO_QOS_V1:
+			ret = check_bcast_qos(&qos, &isodata->qos);
+			if (ret && isodata->past)
+				ret = iso_rebind_bcast_dst(data, sk) == 0;
+			break;
+		case BT_ISO_QOS_EXT:
+			ret = check_bcast_qos_ext(&qos_ext, &isodata->qos_ext);
+			break;
+		}
 	}
 
 	if (!ret) {
@@ -3305,8 +4353,22 @@ static int listen_iso_sock(struct test_data *data, uint8_t num)
 		}
 	}
 
-	if (setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &isodata->qos,
-						sizeof(isodata->qos)) < 0) {
+	switch (isodata->qos_ver) {
+	case BT_ISO_QOS_V1:
+		err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &isodata->qos,
+				sizeof(isodata->qos));
+		break;
+	case BT_ISO_QOS_EXT:
+		err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS,
+				&isodata->qos_ext, sizeof(isodata->qos_ext));
+		break;
+	default:
+		tester_warn("Unexpected BT_ISO_QOS version");
+		err = -EINVAL;
+		goto fail;
+	}
+
+	if (err < 0) {
 		tester_print("Can't set socket BT_ISO_QOS option: %s (%d)",
 					strerror(errno), errno);
 		goto fail;
@@ -3378,6 +4440,7 @@ static void setup_listen_many(struct test_data *data, uint8_t n, uint8_t *num,
 	if (!isodata->bcast) {
 		struct hciemu_client *client;
 		struct bthost *host;
+		struct bt_iso_qos qos;
 
 		if (!data->acl_handle) {
 			tester_print("ACL handle not set");
@@ -3388,7 +4451,8 @@ static void setup_listen_many(struct test_data *data, uint8_t n, uint8_t *num,
 		client = hciemu_get_client(data->hciemu, 0);
 		host = hciemu_client_host(client);
 
-		bthost_set_cig_params(host, 0x01, 0x01, &isodata->qos);
+		iso_client_qos(isodata, &qos);
+		bthost_set_cig_params(host, 0x01, 0x01, &qos);
 		bthost_create_cis(host, 256, data->acl_handle);
 	} else if (isodata->past) {
 		if (!data->acl_handle) {
@@ -3973,6 +5037,9 @@ int main(int argc, char *argv[])
 	test_iso("Basic Framework - Success", NULL, setup_powered,
 							test_framework);
 
+	test_bredrle70("HDT Framework - Success", NULL, setup_powered,
+							test_framework);
+
 	test_iso("Basic ISO Socket - Success", NULL, setup_powered,
 							test_socket);
 
@@ -4003,6 +5070,94 @@ int main(int argc, char *argv[])
 							setup_powered,
 							test_connect);
 
+	test_bredrle70("ISO QoS 16_2_1 HDT - Success", &connect_hdt_16_2_1,
+							setup_powered,
+							test_connect);
+
+	test_bredrle70("ISO QoS HDT 2M - Success", &connect_hdt_2m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 3M - Success", &connect_hdt_3m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 4M - Success", &connect_hdt_4m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 6M - Success", &connect_hdt_6m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 7.5M - Success", &connect_hdt_7_5m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT MIC Length 64 - Success",
+							&connect_hdt_mic_len_64,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT MIC Length 128 - Success",
+						&connect_hdt_mic_len_128,
+						setup_powered,
+						test_connect);
+	test_bredrle70("ISO QoS HDT 2M:3M - Success", &connect_hdt_2m_3m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 2M:4M - Success", &connect_hdt_2m_4m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 2M:6M - Success", &connect_hdt_2m_6m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 2M:7.5M - Success", &connect_hdt_2m_7_5m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 3M:2M - Success", &connect_hdt_3m_2m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 3M:4M - Success", &connect_hdt_3m_4m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 3M:6M - Success", &connect_hdt_3m_6m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 3M:7.5M - Success", &connect_hdt_3m_7_5m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 4M:2M - Success", &connect_hdt_4m_2m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 4M:3M - Success", &connect_hdt_4m_3m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 4M:6M - Success", &connect_hdt_4m_6m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 4M:7.5M - Success", &connect_hdt_4m_7_5m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 6M:2M - Success", &connect_hdt_6m_2m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 6M:3M - Success", &connect_hdt_6m_3m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 6M:4M - Success", &connect_hdt_6m_4m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 6M:7.5M - Success", &connect_hdt_6m_7_5m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 7.5M:2M - Success", &connect_hdt_7_5m_2m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 7.5M:3M - Success", &connect_hdt_7_5m_3m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 7.5M:4M - Success", &connect_hdt_7_5m_4m,
+							setup_powered,
+							test_connect);
+	test_bredrle70("ISO QoS HDT 7.5M:6M - Success", &connect_hdt_7_5m_6m,
+							setup_powered,
+							test_connect);
+
 	test_iso("ISO QoS 24_1_1 - Success", &connect_24_1_1, setup_powered,
 							test_connect);
 
@@ -4162,6 +5317,110 @@ int main(int argc, char *argv[])
 	test_iso("ISO Receive - Success", &listen_16_2_1_recv, setup_powered,
 							test_listen);
 
+	test_iso("ISO Receive HDT - Success", &listen_hdt_16_2_1_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 2M - Success", &listen_hdt_2m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 3M - Success", &listen_hdt_3m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 4M - Success", &listen_hdt_4m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 6M - Success", &listen_hdt_6m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 7.5M - Success", &listen_hdt_7_5m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 2M:3M - Success", &listen_hdt_2m_3m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 2M:4M - Success", &listen_hdt_2m_4m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 2M:6M - Success", &listen_hdt_2m_6m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 2M:7.5M - Success", &listen_hdt_2m_7_5m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 3M:2M - Success", &listen_hdt_3m_2m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 3M:4M - Success", &listen_hdt_3m_4m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 3M:6M - Success", &listen_hdt_3m_6m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 3M:7.5M - Success", &listen_hdt_3m_7_5m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 4M:2M - Success", &listen_hdt_4m_2m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 4M:3M - Success", &listen_hdt_4m_3m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 4M:6M - Success", &listen_hdt_4m_6m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 4M:7.5M - Success", &listen_hdt_4m_7_5m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 6M:2M - Success", &listen_hdt_6m_2m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 6M:3M - Success", &listen_hdt_6m_3m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 6M:4M - Success", &listen_hdt_6m_4m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 6M:7.5M - Success", &listen_hdt_6m_7_5m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 7.5M:2M - Success", &listen_hdt_7_5m_2m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 7.5M:3M - Success", &listen_hdt_7_5m_3m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 7.5M:4M - Success", &listen_hdt_7_5m_4m_recv,
+							setup_powered,
+							test_listen);
+
+	test_iso("ISO Receive HDT 7.5M:6M - Success", &listen_hdt_7_5m_6m_recv,
+							setup_powered,
+							test_listen);
+
 	test_iso("ISO Receive Fragmented - Success", &listen_16_2_1_recv_frag,
 							setup_powered,
 							test_listen);
@@ -4340,6 +5599,29 @@ int main(int argc, char *argv[])
 
 	test_iso("ISO Broadcaster - Success", &bcast_16_2_1_send, setup_powered,
 							test_bcast);
+	test_bredrle70("ISO Broadcaster HDT - Success", &bcast_hdt_16_2_1_send,
+							setup_powered,
+							test_bcast);
+	test_bredrle70("ISO Broadcaster HDT 2M - Success", &bcast_hdt_2m_send,
+							setup_powered,
+							test_bcast);
+	test_bredrle70("ISO Broadcaster HDT 3M - Success", &bcast_hdt_3m_send,
+							setup_powered,
+							test_bcast);
+	test_bredrle70("ISO Broadcaster HDT 4M - Success", &bcast_hdt_4m_send,
+							setup_powered,
+							test_bcast);
+	test_bredrle70("ISO Broadcaster HDT 6M - Success", &bcast_hdt_6m_send,
+							setup_powered,
+							test_bcast);
+	test_bredrle70("ISO Broadcaster HDT 7.5M - Success",
+							&bcast_hdt_7_5m_send,
+							setup_powered,
+							test_bcast);
+	test_bredrle70("ISO Broadcaster HDT MIC Length 64 - Success",
+						&bcast_hdt_mic_len_64_send,
+						setup_powered,
+						test_bcast);
 	test_iso("ISO Broadcaster PAST Info - Success", &past_16_2_1_send,
 							setup_powered,
 							test_past);
@@ -4372,6 +5654,30 @@ int main(int argc, char *argv[])
 	test_iso("ISO Broadcaster Receiver - Success", &bcast_16_2_1_recv,
 							setup_powered,
 							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver HDT - Success",
+							&bcast_hdt_16_2_1_recv,
+							setup_powered,
+							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver HDT 2M - Success",
+							&bcast_hdt_2m_recv,
+							setup_powered,
+							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver HDT 3M - Success",
+							&bcast_hdt_3m_recv,
+							setup_powered,
+							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver HDT 4M - Success",
+							&bcast_hdt_4m_recv,
+							setup_powered,
+							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver HDT 6M - Success",
+							&bcast_hdt_6m_recv,
+							setup_powered,
+							test_bcast_recv);
+	test_iso("ISO Broadcaster Receiver HDT 7.5M - Success",
+							&bcast_hdt_7_5m_recv,
+							setup_powered,
+							test_bcast_recv);
 	test_iso("ISO Broadcaster PAST Receiver - Success",
 							&past_16_2_1_recv,
 							setup_powered,
diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index 4002ca561db8..06676c0dd5fb 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -52,6 +52,7 @@ struct test_data {
 	uint32_t phys;
 	int sk;
 	int sk2;
+	int reencrypt_sk;
 	bool host_disconnected;
 	int step;
 	struct queue *io_channels;
@@ -95,6 +96,11 @@ struct l2cap_data {
 	int sec_level;
 	bool reject_ssp;
 
+	uint8_t mic_len;
+	uint8_t client_mic_len;
+	bool client_encrypt;
+	uint8_t reencrypt_mic_len;
+
 	bool expect_pin;
 	uint8_t pin_len;
 	const void *pin;
@@ -331,6 +337,9 @@ static void test_data_free(void *test_data)
 #define test_l2cap_le_62(name, data, setup, func) \
 	test_l2cap(name, HCIEMU_TYPE_BREDRLE62, data, setup, func)
 
+#define test_l2cap_bredrle70(name, data, setup, func) \
+	test_l2cap(name, HCIEMU_TYPE_BREDRLE70, data, setup, func)
+
 static uint8_t pair_device_pin[] = { 0x30, 0x30, 0x30, 0x30 }; /* "0000" */
 
 static const struct l2cap_data client_connect_success_test = {
@@ -921,6 +930,19 @@ static const struct l2cap_data le_client_connect_phy_2m_coded_test_1 = {
 		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX),
 };
 
+static const struct l2cap_data le_client_connect_phy_hdt_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+};
+
 static const struct l2cap_data le_client_set_phy_1m_test = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
@@ -948,6 +970,76 @@ static const struct l2cap_data le_client_set_phy_coded_test = {
 	.phy = BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX,
 };
 
+static const struct l2cap_data le_client_set_hdt_2m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX,
+};
+
+static const struct l2cap_data le_client_set_hdt_3m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX,
+};
+
+static const struct l2cap_data le_client_set_hdt_4m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX,
+};
+
+static const struct l2cap_data le_client_set_hdt_6m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX,
+};
+
+static const struct l2cap_data le_client_set_hdt_7_5m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX,
+};
+
 static uint8_t nonexisting_bdaddr[] = {0x00, 0xAA, 0x01, 0x02, 0x03, 0x00};
 static const struct l2cap_data le_client_close_socket_test_1 = {
 	.client_psm = 0x0080,
@@ -1049,6 +1141,24 @@ static const struct l2cap_data le_server_phy_2m_coded_test = {
 		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX),
 };
 
+static const struct l2cap_data le_server_phy_hdt_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = le_connect_rsp,
+	.expect_cmd_len = sizeof(le_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+};
+
 static const struct l2cap_data le_server_set_phy_1m_test = {
 	.server_psm = 0x0080,
 	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
@@ -1077,6 +1187,101 @@ static const struct l2cap_data le_server_set_phy_2m_test = {
 	.phy = BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX,
 };
 
+static const struct l2cap_data le_server_set_hdt_2m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = le_connect_rsp,
+	.expect_cmd_len = sizeof(le_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX,
+};
+
+static const struct l2cap_data le_server_set_hdt_3m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = le_connect_rsp,
+	.expect_cmd_len = sizeof(le_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX,
+};
+
+static const struct l2cap_data le_server_set_hdt_4m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = le_connect_rsp,
+	.expect_cmd_len = sizeof(le_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX,
+};
+
+static const struct l2cap_data le_server_set_hdt_6m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = le_connect_rsp,
+	.expect_cmd_len = sizeof(le_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX,
+};
+
+static const struct l2cap_data le_server_set_hdt_7_5m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = le_connect_rsp,
+	.expect_cmd_len = sizeof(le_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX,
+};
+
 static const struct l2cap_data le_server_set_phy_coded_test = {
 	.server_psm = 0x0080,
 	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
@@ -1091,6 +1296,117 @@ static const struct l2cap_data le_server_set_phy_coded_test = {
 	.phy = BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX,
 };
 
+static const uint8_t nval_mic_len_connect_rsp[] = {
+						0x00, 0x00, /* DCID */
+						0x00, 0x00, /* MTU */
+						0x00, 0x00, /* MPS */
+						0x00, 0x00, /* Credits */
+						0x0c, 0x00, /* Result */
+};
+
+static const struct l2cap_data le_server_nval_mic_len_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = nval_mic_len_connect_rsp,
+	.expect_cmd_len = sizeof(nval_mic_len_connect_rsp),
+	.sec_level = BT_SECURITY_MEDIUM,
+	.mic_len = 0x02,
+	.client_mic_len = 0x01,
+};
+
+static const uint8_t ecred_mic_len_connect_req[] = {
+						0x80, 0x00, /* PSM */
+						0x40, 0x00, /* MTU */
+						0x40, 0x00, /* MPS */
+						0x05, 0x00, /* Credits */
+						0x41, 0x00, /* SCID #1 */
+};
+
+static const uint8_t nval_mic_len_ecred_connect_rsp[] = {
+						0x00, 0x00, /* MTU */
+						0x00, 0x00, /* MPS */
+						0x00, 0x00, /* Credits */
+						0x10, 0x00, /* Result */
+						0x00, 0x00, /* DCID #1 */
+};
+
+/* HDT, 64-bit MIC, Enhanced Credit Based, server requires 128-bit */
+static const struct l2cap_data le_server_nval_mic_len_ecred_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_mic_len_connect_req,
+	.send_cmd_len = sizeof(ecred_mic_len_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = nval_mic_len_ecred_connect_rsp,
+	.expect_cmd_len = sizeof(nval_mic_len_ecred_connect_rsp),
+	.sec_level = BT_SECURITY_MEDIUM,
+	.mic_len = 0x02,
+	.client_mic_len = 0x01,
+};
+
+/* LE 1M, 32-bit MIC (implicit), LE Credit Based, server requires
+ * 64-bit
+ */
+static const struct l2cap_data le_server_nval_mic_len_1m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_LE_CONN_RSP,
+	.expect_cmd = nval_mic_len_connect_rsp,
+	.expect_cmd_len = sizeof(nval_mic_len_connect_rsp),
+	.sec_level = BT_SECURITY_MEDIUM,
+	.mic_len = 0x01,
+	.client_encrypt = true,
+};
+
+/* LE 1M, 32-bit MIC (implicit), Enhanced Credit Based, server
+ * requires 64-bit
+ */
+static const struct l2cap_data le_server_nval_mic_len_1m_ecred_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_mic_len_connect_req,
+	.send_cmd_len = sizeof(ecred_mic_len_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = nval_mic_len_ecred_connect_rsp,
+	.expect_cmd_len = sizeof(nval_mic_len_ecred_connect_rsp),
+	.sec_level = BT_SECURITY_MEDIUM,
+	.mic_len = 0x01,
+	.client_encrypt = true,
+};
+
+/* HDT, 128-bit MIC, LE Credit Based, re-encrypting asking for a 64-bit MIC
+ * keeps the 128-bit MIC since only one side prefers 64-bit.
+ */
+static const struct l2cap_data le_server_reencrypt_mic_len_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_LE_CONN_REQ,
+	.send_cmd = le_connect_req,
+	.send_cmd_len = sizeof(le_connect_req),
+	.sec_level = BT_SECURITY_MEDIUM,
+	.mic_len = 0x02,
+	.client_mic_len = 0x02,
+	.reencrypt_mic_len = 0x01,
+};
+
+/* HDT, 128-bit MIC, Enhanced Credit Based, re-encrypting asking for a 64-bit
+ * MIC keeps the 128-bit MIC since only one side prefers 64-bit.
+ */
+static const struct l2cap_data le_server_reencrypt_mic_len_ecred_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_mic_len_connect_req,
+	.send_cmd_len = sizeof(ecred_mic_len_connect_req),
+	.sec_level = BT_SECURITY_MEDIUM,
+	.mic_len = 0x02,
+	.client_mic_len = 0x02,
+	.reencrypt_mic_len = 0x01,
+};
+
 static const uint8_t ecred_connect_req[] = {	0x80, 0x00, /* PSM */
 						0x40, 0x00, /* MTU */
 						0x40, 0x00, /* MPS */
@@ -1197,6 +1513,24 @@ static const struct l2cap_data ext_flowctl_server_phy_2m_coded_test = {
 		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX),
 };
 
+static const struct l2cap_data ext_flowctl_server_phy_hdt_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_connect_req,
+	.send_cmd_len = sizeof(ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = ecred_connect_rsp,
+	.expect_cmd_len = sizeof(ecred_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+};
+
 static const struct l2cap_data ext_flowctl_server_set_phy_1m_test = {
 	.server_psm = 0x0080,
 	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
@@ -1239,6 +1573,101 @@ static const struct l2cap_data ext_flowctl_server_set_phy_coded_test = {
 	.phy = BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX,
 };
 
+static const struct l2cap_data ext_flowctl_server_set_hdt_2m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_connect_req,
+	.send_cmd_len = sizeof(ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = ecred_connect_rsp,
+	.expect_cmd_len = sizeof(ecred_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_server_set_hdt_3m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_connect_req,
+	.send_cmd_len = sizeof(ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = ecred_connect_rsp,
+	.expect_cmd_len = sizeof(ecred_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_server_set_hdt_4m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_connect_req,
+	.send_cmd_len = sizeof(ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = ecred_connect_rsp,
+	.expect_cmd_len = sizeof(ecred_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_server_set_hdt_6m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_connect_req,
+	.send_cmd_len = sizeof(ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = ecred_connect_rsp,
+	.expect_cmd_len = sizeof(ecred_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_server_set_hdt_7_5m_test = {
+	.server_psm = 0x0080,
+	.send_cmd_code = BT_L2CAP_PDU_ECRED_CONN_REQ,
+	.send_cmd = ecred_connect_req,
+	.send_cmd_len = sizeof(ecred_connect_req),
+	.expect_cmd_code = BT_L2CAP_PDU_ECRED_CONN_RSP,
+	.expect_cmd = ecred_connect_rsp,
+	.expect_cmd_len = sizeof(ecred_connect_rsp),
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX,
+};
+
 static const struct l2cap_data le_att_client_connect_success_test_1 = {
 	.cid = 0x0004,
 	.sec_level = BT_SECURITY_LOW,
@@ -1395,6 +1824,20 @@ static const struct l2cap_data ext_flowctl_client_phy_2m_coded_test_1 = {
 		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX),
 };
 
+static const struct l2cap_data ext_flowctl_client_phy_hdt_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+};
+
 static const struct l2cap_data ext_flowctl_client_set_phy_1m_test = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
@@ -1425,6 +1868,81 @@ static const struct l2cap_data ext_flowctl_client_set_phy_coded_test = {
 	.phy = BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX,
 };
 
+static const struct l2cap_data ext_flowctl_client_set_hdt_2m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_client_set_hdt_3m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_client_set_hdt_4m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_client_set_hdt_6m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX,
+};
+
+static const struct l2cap_data ext_flowctl_client_set_hdt_7_5m_test = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.phys = (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX |
+		 BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX |
+		 BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX |
+		 BT_PHY_HDT_2M_TX | BT_PHY_HDT_2M_RX |
+		 BT_PHY_HDT_3M_TX | BT_PHY_HDT_3M_RX |
+		 BT_PHY_HDT_4M_TX | BT_PHY_HDT_4M_RX |
+		 BT_PHY_HDT_6M_TX | BT_PHY_HDT_6M_RX |
+		 BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX),
+	.phy = BT_PHY_HDT_7_5M_TX | BT_PHY_HDT_7_5M_RX,
+};
+
 static const struct l2cap_data ext_flowctl_client_defer_limit = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
@@ -1734,6 +2252,7 @@ static void setup_powered_client(const void *test_data)
 static void setup_powered_server(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct l2cap_data *l2data = data->test_data;
 	unsigned char param[] = { 0x01 };
 
 	setup_powered_common();
@@ -1743,6 +2262,36 @@ static void setup_powered_server(const void *test_data)
 	mgmt_send(data->mgmt, MGMT_OP_SET_CONNECTABLE, data->mgmt_index,
 				sizeof(param), param, NULL, NULL, NULL);
 
+	/* A 64-bit MIC is only used if both sides prefer it, so make this
+	 * side prefer it too when the client asks for one, while the channel
+	 * still requires what the test sets.
+	 */
+	if (l2data && l2data->client_mic_len == 0x01) {
+		uint8_t mic_param[] = {
+			0x21, 0x00,	/* Type: LE HDT Default MIC Length */
+			0x01,		/* Length */
+			0x01,		/* Value: 64-bit */
+		};
+
+		mgmt_send(data->mgmt, MGMT_OP_SET_DEF_SYSTEM_CONFIG,
+				data->mgmt_index, sizeof(mic_param),
+				mic_param, NULL, NULL, NULL);
+	}
+
+	/* Re-encrypting needs the LTK on both sides, which Secure
+	 * Connections pairing gives with EDIV and Rand set to zero.
+	 */
+	if (l2data && l2data->reencrypt_mic_len) {
+		struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+		mgmt_send(data->mgmt, MGMT_OP_SET_SSP, data->mgmt_index,
+				sizeof(param), param, NULL, NULL, NULL);
+		mgmt_send(data->mgmt, MGMT_OP_SET_SECURE_CONN,
+				data->mgmt_index, sizeof(param), param, NULL,
+				NULL, NULL);
+		bthost_set_sc_support(bthost, true);
+	}
+
 	if (data->hciemu_type > HCIEMU_TYPE_LE)
 		mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index,
 				sizeof(param), param, NULL, NULL, NULL);
@@ -1925,6 +2474,59 @@ static bool check_mtu(struct test_data *data, int sk)
 	return true;
 }
 
+static bool check_reencrypt_mic_len(void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct l2cap_data *l2data = data->test_data;
+	struct bt_security sec;
+	socklen_t optlen = sizeof(sec);
+	/* A 64-bit MIC is only used if both sides prefer it, so the
+	 * refresh keeps the 128-bit MIC the channel requires.
+	 */
+	memset(&sec, 0, sizeof(sec));
+	if (getsockopt(data->reencrypt_sk, SOL_BLUETOOTH, BT_SECURITY, &sec,
+							&optlen) < 0) {
+		tester_warn("getsockopt(BT_SECURITY): %s (%d)",
+						strerror(errno), errno);
+		tester_test_failed();
+		return false;
+	}
+
+	if (sec.mic_len != l2data->mic_len) {
+		tester_warn("MIC length changed: 0x%02x != 0x%02x",
+						sec.mic_len, l2data->mic_len);
+		tester_test_failed();
+		return false;
+	}
+
+	tester_print("MIC length unchanged: 0x%02x", sec.mic_len);
+	tester_test_passed();
+
+	return false;
+}
+
+static bool hook_reencrypt_complete(const void *msg, uint16_t len,
+							void *user_data)
+{
+	const uint8_t *status = msg;
+
+	if (len < 1)
+		return true;
+
+	if (*status) {
+		tester_warn("Re-encryption failed: status 0x%02x", *status);
+		tester_test_failed();
+		return true;
+	}
+
+	tester_print("Re-encryption complete");
+
+	/* Let the host process the event before checking */
+	timeout_add(50, check_reencrypt_mic_len, NULL, NULL);
+
+	return true;
+}
+
 static bool check_phy_and_sec(void *args)
 {
 	int sk = PTR_TO_INT(args);
@@ -2304,6 +2906,9 @@ static int create_l2cap_sock(struct test_data *data, uint16_t psm,
 		memset(&sec, 0, sizeof(sec));
 		sec.level = sec_level;
 
+		if (l2data)
+			sec.mic_len = l2data->mic_len;
+
 		if (setsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &sec,
 							sizeof(sec)) < 0) {
 			err = -errno;
@@ -3075,6 +3680,30 @@ static bool l2cap_accept_cb(struct tester_io *io, uint32_t cond,
 
 	tester_print("Successfully connected");
 
+	if (l2data->reencrypt_mic_len) {
+		struct bthost *bthost;
+
+		tester_print("Re-encrypting with mic_len 0x%02x"
+					" (expect the MIC to be kept)",
+					l2data->reencrypt_mic_len);
+
+		/* The check runs once the refresh reaches the host, as
+		 * Encryption Change v3 or Key Refresh Complete v2.
+		 */
+		data->reencrypt_sk = sk;
+		hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_EVT,
+					BT_HCI_EVT_ENCRYPT_CHANGE_V3,
+					hook_reencrypt_complete, data);
+		hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_EVT,
+					BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE_V2,
+					hook_reencrypt_complete, data);
+
+		bthost = hciemu_client_get_host(data->hciemu);
+		bthost_le_reencrypt(bthost, data->handle,
+						l2data->reencrypt_mic_len);
+		return false;
+	}
+
 	tester_test_passed();
 
 	return false;
@@ -3209,6 +3838,26 @@ failed:
 	tester_test_failed();
 }
 
+static void send_l2cap_req_after_encrypt(uint16_t handle, void *user_data)
+{
+	struct test_data *data = user_data;
+	const struct l2cap_data *l2data = data->test_data;
+	struct bthost *bthost;
+	bthost_l2cap_rsp_cb cb;
+
+	if (l2data->expect_cmd_code)
+		cb = client_l2cap_rsp;
+	else
+		cb = NULL;
+
+	tester_print("Sending L2CAP Request from client after encryption");
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_l2cap_req(bthost, handle, l2data->send_cmd_code,
+				l2data->send_cmd, l2data->send_cmd_len,
+				cb, data);
+}
+
 static void send_req_new_conn(uint16_t handle, void *user_data)
 {
 	struct test_data *data = user_data;
@@ -3240,6 +3889,25 @@ static void send_req_new_conn(uint16_t handle, void *user_data)
 	if (l2data->send_cmd) {
 		bthost_l2cap_rsp_cb cb;
 
+		if (l2data->client_mic_len) {
+			bthost = hciemu_client_get_host(data->hciemu);
+			/* Set HDT PHY first, then encrypt, then send L2CAP */
+			bthost_le_set_phy(bthost, handle, 0x17, 0x17);
+			bthost_set_encrypt_cb(bthost,
+					send_l2cap_req_after_encrypt, data);
+			bthost_request_auth(bthost, handle);
+			return;
+		}
+
+		if (l2data->client_encrypt) {
+			bthost = hciemu_client_get_host(data->hciemu);
+			/* Encrypt (no PHY change), then send L2CAP */
+			bthost_set_encrypt_cb(bthost,
+					send_l2cap_req_after_encrypt, data);
+			bthost_request_auth(bthost, handle);
+			return;
+		}
+
 		if (l2data->expect_cmd_code)
 			cb = client_l2cap_rsp;
 		else
@@ -3313,6 +3981,9 @@ static void start_test_server(const void *test_data, bthost_new_conn_cb conn_cb,
 	bthost = hciemu_client_get_host(data->hciemu);
 	bthost_set_connect_cb(bthost, conn_cb, data);
 
+	if (l2data->client_mic_len)
+		bthost_set_mic_len(bthost, l2data->client_mic_len);
+
 	if (data->hciemu_type == HCIEMU_TYPE_BREDR)
 		addr_type = BDADDR_BREDR;
 	else
@@ -3756,6 +4427,9 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP LE Client - PHY 2M/Coded",
 				&le_client_connect_phy_2m_coded_test_1,
 				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP LE Client - PHY HDT",
+				&le_client_connect_phy_hdt_test,
+				setup_powered_client, test_connect);
 	test_l2cap_le_52("L2CAP LE Client - Set PHY 1M",
 				&le_client_set_phy_1m_test,
 				setup_powered_client, test_connect);
@@ -3765,6 +4439,21 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP LE Client - Set PHY Coded",
 				&le_client_set_phy_coded_test,
 				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP LE Client - Set HDT 2M",
+				&le_client_set_hdt_2m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP LE Client - Set HDT 3M",
+				&le_client_set_hdt_3m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP LE Client - Set HDT 4M",
+				&le_client_set_hdt_4m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP LE Client - Set HDT 6M",
+				&le_client_set_hdt_6m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP LE Client - Set HDT 7.5M",
+				&le_client_set_hdt_7_5m_test,
+				setup_powered_client, test_connect);
 
 	test_l2cap_le("L2CAP LE Client - Close socket 1",
 				&le_client_close_socket_test_1,
@@ -3798,6 +4487,9 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP LE Server - PHY 2M/Coded",
 					&le_server_phy_2m_coded_test,
 					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - PHY HDT",
+					&le_server_phy_hdt_test,
+					setup_powered_server, test_server);
 	test_l2cap_le_52("L2CAP LE Server - Set PHY 1M",
 					&le_server_set_phy_1m_test,
 					setup_powered_server, test_server);
@@ -3807,6 +4499,39 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP LE Server - Set PHY Coded",
 					&le_server_set_phy_coded_test,
 					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - Set HDT 2M",
+					&le_server_set_hdt_2m_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - Set HDT 3M",
+					&le_server_set_hdt_3m_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - Set HDT 4M",
+					&le_server_set_hdt_4m_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - Set HDT 6M",
+					&le_server_set_hdt_6m_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - Set HDT 7.5M",
+					&le_server_set_hdt_7_5m_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - MIC Length Too Short HDT/CFC",
+					&le_server_nval_mic_len_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - MIC Length Too Short HDT/ECFC",
+					&le_server_nval_mic_len_ecred_test,
+					setup_powered_server, test_server);
+	test_l2cap_le("L2CAP LE Server - MIC Length Too Short 1M/CFC",
+					&le_server_nval_mic_len_1m_test,
+					setup_powered_server, test_server);
+	test_l2cap_le("L2CAP LE Server - MIC Length Too Short 1M/ECFC",
+					&le_server_nval_mic_len_1m_ecred_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - MIC Length Downgrade HDT/CFC",
+					&le_server_reencrypt_mic_len_test,
+					setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP LE Server - MIC Length Downgrade HDT/ECFC",
+					&le_server_reencrypt_mic_len_ecred_test,
+					setup_powered_server, test_server);
 
 	test_l2cap_le("L2CAP Ext-Flowctl Client - Success",
 				&ext_flowctl_client_connect_success_test_1,
@@ -3843,6 +4568,9 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP Ext-Flowctl Client - PHY 2M/Coded",
 				&ext_flowctl_client_phy_2m_coded_test_1,
 				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Client - PHY HDT",
+				&ext_flowctl_client_phy_hdt_test,
+				setup_powered_client, test_connect);
 	test_l2cap_le_52("L2CAP Ext-Flowctl Client - Set PHY 1M",
 				&ext_flowctl_client_set_phy_1m_test,
 				setup_powered_client, test_connect);
@@ -3852,6 +4580,21 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP Ext-Flowctl Client - Set PHY Coded",
 				&ext_flowctl_client_set_phy_coded_test,
 				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Client - Set HDT 2M",
+				&ext_flowctl_client_set_hdt_2m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Client - Set HDT 3M",
+				&ext_flowctl_client_set_hdt_3m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Client - Set HDT 4M",
+				&ext_flowctl_client_set_hdt_4m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Client - Set HDT 6M",
+				&ext_flowctl_client_set_hdt_6m_test,
+				setup_powered_client, test_connect);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Client - Set HDT 7.5M",
+				&ext_flowctl_client_set_hdt_7_5m_test,
+				setup_powered_client, test_connect);
 
 	test_l2cap_le("L2CAP Ext-Flowctl Client - Defer limit",
 				&ext_flowctl_client_defer_limit,
@@ -3874,6 +4617,9 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP Ext-Flowctl Server - PHY 2M/Coded",
 				&ext_flowctl_server_phy_2m_coded_test,
 				setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Server - PHY HDT",
+				&ext_flowctl_server_phy_hdt_test,
+				setup_powered_server, test_server);
 	test_l2cap_le_52("L2CAP Ext-Flowctl Server - Set PHY 1M",
 				&ext_flowctl_server_set_phy_1m_test,
 				setup_powered_server, test_server);
@@ -3883,6 +4629,21 @@ int main(int argc, char *argv[])
 	test_l2cap_le_52("L2CAP Ext-Flowctl Server - Set PHY Coded",
 				&ext_flowctl_server_set_phy_coded_test,
 				setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Server - Set HDT 2M",
+				&ext_flowctl_server_set_hdt_2m_test,
+				setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Server - Set HDT 3M",
+				&ext_flowctl_server_set_hdt_3m_test,
+				setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Server - Set HDT 4M",
+				&ext_flowctl_server_set_hdt_4m_test,
+				setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Server - Set HDT 6M",
+				&ext_flowctl_server_set_hdt_6m_test,
+				setup_powered_server, test_server);
+	test_l2cap_bredrle70("L2CAP Ext-Flowctl Server - Set HDT 7.5M",
+				&ext_flowctl_server_set_hdt_7_5m_test,
+				setup_powered_server, test_server);
 
 	test_l2cap_le_52("L2CAP Ext-Flowctl Server - Nval Conn Req",
 				&ext_flowctl_server_nval_conn_req_test,
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index 201bd4396c84..c7e5595cf21c 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -703,6 +703,13 @@ static void test_condition_complete(struct test_data *data)
 #define test_bredrle62(name, data, setup, func) \
 	test_bredrle62_full(name, data, setup, func, 2)
 
+#define test_bredrle70_full(name, data, setup, func, timeout) \
+	test_full(name, data, setup, func, timeout, HCIEMU_TYPE_BREDRLE70, \
+					0x10, 0x0601beff, 0x00000080)
+
+#define test_bredrle70(name, data, setup, func) \
+	test_bredrle70_full(name, data, setup, func, 2)
+
 #define test_hs_full(name, data, setup, func, timeout) \
 	test_full(name, data, setup, func, timeout, HCIEMU_TYPE_BREDRLE, \
 					0x09, 0x0001bfff, 0x00000080)
@@ -4709,6 +4716,21 @@ static const struct generic_data set_le_on_success_sci = {
 	.expect_hci_len = sizeof(set_le_on_write_le_host_param),
 };
 
+static const char set_le_settings_param_hdt[] = { 0x81, 0x02, 0xfc, 0x07 };
+static const struct generic_data set_le_on_success_hdt = {
+	.setup_settings = settings_le,
+	.send_opcode = MGMT_OP_SET_POWERED,
+	.send_param = set_powered_on_param,
+	.send_len = sizeof(set_powered_on_param),
+	.expect_status = MGMT_STATUS_SUCCESS,
+	.expect_param = set_le_settings_param_hdt,
+	.expect_len = sizeof(set_le_settings_param_hdt),
+	.expect_settings_set = MGMT_SETTING_LE,
+	.expect_hci_command = BT_HCI_CMD_WRITE_LE_HOST_SUPPORTED,
+	.expect_hci_param = set_le_on_write_le_host_param,
+	.expect_hci_len = sizeof(set_le_on_write_le_host_param),
+};
+
 static const uint8_t load_conn_subrate_nval_1[16] = { 0x12, 0x11 };
 static const struct generic_data load_conn_subrate_fail_1 = {
 	.send_opcode = MGMT_OP_LOAD_CONN_SUBRATE,
@@ -14253,6 +14275,131 @@ static void test_hci_devcd(const void *test_data)
 	tester_wait(test->dump_data->timeout + 1, verify_devcd, NULL);
 }
 
+/* HDT Default Parameters - Set Default System Config with TLVs 0x0021-0x0023 */
+static const uint8_t set_def_system_config_hdt_mic_len_param[] = {
+	0x21, 0x00,	/* Type: LE HDT Default MIC Length */
+	0x01,		/* Length */
+	0x02,		/* Value: 128-bit */
+};
+
+static const struct generic_data set_def_system_config_hdt_mic_len = {
+	.send_opcode = MGMT_OP_SET_DEF_SYSTEM_CONFIG,
+	.send_param = set_def_system_config_hdt_mic_len_param,
+	.send_len = sizeof(set_def_system_config_hdt_mic_len_param),
+	.expect_status = MGMT_STATUS_SUCCESS,
+};
+
+static const uint8_t set_def_system_config_hdt_format_param[] = {
+	0x22, 0x00,	/* Type: LE HDT Default Packet Format */
+	0x01,		/* Length */
+	0x01,		/* Value: Format 1 */
+};
+
+static const struct generic_data set_def_system_config_hdt_format = {
+	.send_opcode = MGMT_OP_SET_DEF_SYSTEM_CONFIG,
+	.send_param = set_def_system_config_hdt_format_param,
+	.send_len = sizeof(set_def_system_config_hdt_format_param),
+	.expect_status = MGMT_STATUS_SUCCESS,
+};
+
+static const uint8_t set_def_system_config_hdt_rates_param[] = {
+	0x23, 0x00,	/* Type: LE HDT Default Rates */
+	0x02,		/* Length */
+	0x1f, 0x00,	/* Value: All rates (bits 0-4) */
+};
+
+static const struct generic_data set_def_system_config_hdt_rates = {
+	.send_opcode = MGMT_OP_SET_DEF_SYSTEM_CONFIG,
+	.send_param = set_def_system_config_hdt_rates_param,
+	.send_len = sizeof(set_def_system_config_hdt_rates_param),
+	.expect_status = MGMT_STATUS_SUCCESS,
+};
+
+/* EKS Opportunistic Encryption - Set Default System Config with TLV 0x0024 */
+static const uint8_t set_def_system_config_eks_oppt_param[] = {
+	0x24, 0x00,	/* Type: LE Opportunistic Encryption */
+	0x01,		/* Length */
+	0x01,		/* Value: enabled */
+};
+
+static const struct generic_data set_def_system_config_eks_oppt_on = {
+	.send_opcode = MGMT_OP_SET_DEF_SYSTEM_CONFIG,
+	.send_param = set_def_system_config_eks_oppt_param,
+	.send_len = sizeof(set_def_system_config_eks_oppt_param),
+	.expect_status = MGMT_STATUS_SUCCESS,
+};
+
+static const uint8_t set_def_system_config_eks_oppt_off_param[] = {
+	0x24, 0x00,	/* Type: LE Opportunistic Encryption */
+	0x01,		/* Length */
+	0x00,		/* Value: disabled */
+};
+
+static const struct generic_data set_def_system_config_eks_oppt_off = {
+	.send_opcode = MGMT_OP_SET_DEF_SYSTEM_CONFIG,
+	.send_param = set_def_system_config_eks_oppt_off_param,
+	.send_len = sizeof(set_def_system_config_eks_oppt_off_param),
+	.expect_status = MGMT_STATUS_SUCCESS,
+};
+
+/* EKS Opportunistic Encryption - Verify encryption happens on connect */
+static const void *add_device_auto_connect_func(uint16_t *len)
+{
+	struct test_data *data = tester_get_data();
+	static struct mgmt_cp_add_device cp;
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.addr.bdaddr, hciemu_get_client_bdaddr(data->hciemu), 6);
+	cp.addr.type = BDADDR_LE_PUBLIC;
+	cp.action = 0x02; /* Auto connect */
+
+	*len = sizeof(cp);
+
+	return &cp;
+}
+
+static int check_encrypt_v2_opportunistic(const void *param, uint16_t length)
+{
+	const struct {
+		uint16_t handle;
+		uint64_t rand;
+		uint16_t ediv;
+		uint8_t  ltk[16];
+		uint8_t  mic_len;
+		uint8_t  encryption;
+	} __attribute__((packed)) *cmd = param;
+
+	if (length < sizeof(*cmd))
+		return -1;
+
+	/* Verify encryption field is 0x01 (opportunistic) */
+	if (cmd->encryption != 0x01) {
+		tester_warn("Expected encryption=0x01 (opportunistic), "
+					"got 0x%02x", cmd->encryption);
+		return -1;
+	}
+
+	return 0;
+}
+
+static uint16_t settings_powered_le_ssp[] = {
+	MGMT_OP_SET_LE,
+	MGMT_OP_SET_SSP,
+	MGMT_OP_SET_POWERED,
+	0 };
+
+static const struct generic_data eks_oppt_connect_encrypt_test = {
+	.setup_settings = settings_powered_le_ssp,
+	.client_enable_adv = true,
+	.send_opcode = MGMT_OP_ADD_DEVICE,
+	.send_func = add_device_auto_connect_func,
+	.expect_status = MGMT_STATUS_SUCCESS,
+	.expect_ignore_param = true,
+	.expect_hci_command = BT_HCI_CMD_LE_ENABLE_ENCRYPT_V2,
+	.expect_hci_len = sizeof(struct bt_hci_cmd_le_enable_encrypt_v2),
+	.expect_hci_param_check_func = check_encrypt_v2_opportunistic,
+};
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
@@ -14601,6 +14748,9 @@ int main(int argc, char *argv[])
 	test_bredrle62("Set Low Energy on 6.2 - SCI Setting",
 				&set_le_on_success_sci,
 				NULL, test_command_generic);
+	test_bredrle70("Set Low Energy on HDT - HDT Setting",
+				&set_le_on_success_hdt,
+				NULL, test_command_generic);
 	test_bredrle("Set Low Energy on - Invalid parameters 1",
 				&set_le_on_invalid_param_test_1,
 				NULL, test_command_generic);
@@ -16486,5 +16636,25 @@ int main(int argc, char *argv[])
 	test_bredrle_full("HCI Devcoredump - Dump Timeout", &dump_timeout, NULL,
 				test_hci_devcd, 3);
 
+	/* EKS Opportunistic Encryption */
+	test_bredrle70("Set Default System Config - HDT MIC Length",
+				&set_def_system_config_hdt_mic_len,
+				NULL, test_command_generic);
+	test_bredrle70("Set Default System Config - HDT Packet Format",
+				&set_def_system_config_hdt_format,
+				NULL, test_command_generic);
+	test_bredrle70("Set Default System Config - HDT Rates",
+				&set_def_system_config_hdt_rates,
+				NULL, test_command_generic);
+	test_bredrle70("Set Default System Config - EKS Opportunistic on",
+				&set_def_system_config_eks_oppt_on,
+				NULL, test_command_generic);
+	test_bredrle70("Set Default System Config - EKS Opportunistic off",
+				&set_def_system_config_eks_oppt_off,
+				NULL, test_command_generic);
+	test_bredrle70_full("EKS Opportunistic - Auto Encrypt on Connect",
+				&eks_oppt_connect_encrypt_test,
+				NULL, test_command_generic, 5);
+
 	return tester_run();
 }
-- 
2.56.0


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

* [PATCH BlueZ v2 9/9] l2test: Add HDT options
  2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
                   ` (7 preceding siblings ...)
  2026-11-04 18:36 ` [PATCH BlueZ v2 8/9] l2cap-tester, iso-tester, mgmt-tester: Add HDT tests Luiz Augusto von Dentz
@ 2026-11-04 18:36 ` Luiz Augusto von Dentz
  8 siblings, 0 replies; 13+ messages in thread
From: Luiz Augusto von Dentz @ 2026-11-04 18:36 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add options to select the PHY, including the HDT rates, and to request a
MIC length through BT_SECURITY, documented in l2cap-protocol.rst.
---
 doc/l2cap-protocol.rst |  42 +++++++++--
 tools/l2test.c         | 153 +++++++++++++++++++++++++++++++++--------
 2 files changed, 164 insertions(+), 31 deletions(-)

diff --git a/doc/l2cap-protocol.rst b/doc/l2cap-protocol.rst
index d53438924448..821de0d1beea 100644
--- a/doc/l2cap-protocol.rst
+++ b/doc/l2cap-protocol.rst
@@ -76,7 +76,17 @@ with **getsockopt(2)** with the socket level set to SOL_BLUETOOTH.
 BT_SECURITY (since Linux 2.6.30)
 --------------------------------
 
-Channel security level, possible values:
+Channel security level, set via ``struct bt_security``:
+
+.. code-block::
+
+    struct bt_security {
+        uint8_t level;
+        uint8_t key_size;
+        uint8_t mic_len;
+    };
+
+Possible values for ``level``:
 
 .. csv-table::
     :header: "Value", "Security Level", "Link Key Type", "Encryption"
@@ -88,13 +98,37 @@ Channel security level, possible values:
     **BT_SECURITY_HIGH**, 3 (High), Authenticated, Required
     **BT_SECURITY_FIPS** (since Linux 3.15), 4 (Secure Only), Authenticated (P-256 based Secure Simple Pairing and Secure Authentication), Required
 
+Possible values for ``mic_len`` (LE only):
+
+.. csv-table::
+    :header: "Value", "MIC Length", "Description"
+    :widths: auto
+
+    0x00, 32 bits, Don't care (default; initiator requests 128 bits)
+    0x01, 64 bits, Require at least 64-bit MIC
+    0x02, 128 bits, Require 128-bit MIC
+
+When set on a **server** (listening) socket, incoming LE Credit Based or
+Enhanced Credit Based connection requests are rejected with result
+``MIC Length Too Short`` (0x000D) if the connection's MIC length is shorter
+than the required value.
+
+When set on a **client** (initiating) socket, the value is used in the
+``LE Enable Encryption V2`` HCI command to request the specified MIC length
+from the controller. A value of 0x00 is treated as "don't care" and defaults
+to requesting 128 bits.
+
 Example:
 
 .. code-block::
 
-    int level = BT_SECURITY_HIGH;
-    int err = setsockopt(l2cap_socket, SOL_BLUETOOTH, BT_SECURITY, &level,
-                         sizeof(level));
+    struct bt_security sec = {0};
+
+    sec.level = BT_SECURITY_MEDIUM;
+    sec.mic_len = 0x02; /* Require 128-bit MIC */
+
+    int err = setsockopt(l2cap_socket, SOL_BLUETOOTH, BT_SECURITY, &sec,
+                         sizeof(sec));
     if (err == -1) {
         perror("setsockopt");
         return 1;
diff --git a/tools/l2test.c b/tools/l2test.c
index 2e2606db13b9..86749ff39d62 100644
--- a/tools/l2test.c
+++ b/tools/l2test.c
@@ -122,8 +122,9 @@ static int timestamp = 0;
 static int defer_setup = 0;
 static int priority = -1;
 static int rcvbuf = 0;
-static int chan_policy = -1;
+static int32_t phy = -1;
 static int bdaddr_type = 0;
+static int mic_len = 0;
 
 struct lookup_table {
 	const char *name;
@@ -142,11 +143,33 @@ static struct lookup_table l2cap_modes[] = {
 	{ 0 }
 };
 
-static struct lookup_table chan_policies[] = {
-	{ "bredr",	BT_CHANNEL_POLICY_BREDR_ONLY		},
-	{ "bredr_pref",	BT_CHANNEL_POLICY_BREDR_PREFERRED	},
-	{ "amp_pref",	BT_CHANNEL_POLICY_AMP_PREFERRED		},
-	{ NULL,		0					},
+static struct lookup_table phys[] = {
+	{ "BR1M1SLOT", BT_PHY_BR_1M_1SLOT },
+	{ "BR1M3SLOT", BT_PHY_BR_1M_3SLOT },
+	{ "BR1M5SLOT", BT_PHY_BR_1M_5SLOT },
+	{ "EDR2M1SLOT",	BT_PHY_EDR_2M_1SLOT },
+	{ "EDR2M3SLOT",	BT_PHY_EDR_2M_3SLOT },
+	{ "EDR2M5SLOT",	BT_PHY_EDR_2M_5SLOT },
+	{ "EDR3M1SLOT", BT_PHY_EDR_3M_1SLOT },
+	{ "EDR3M3SLOT", BT_PHY_EDR_3M_3SLOT },
+	{ "EDR3M5SLOT", BT_PHY_EDR_3M_5SLOT },
+	{ "LE1MTX", BT_PHY_LE_1M_TX },
+	{ "LE1MRX", BT_PHY_LE_1M_RX },
+	{ "LE2MTX", BT_PHY_LE_2M_TX },
+	{ "LE2MRX", BT_PHY_LE_2M_RX },
+	{ "LECODEDTX", BT_PHY_LE_CODED_TX },
+	{ "LECODEDRX", BT_PHY_LE_CODED_RX },
+	{ "HDT2MTX", BT_PHY_HDT_2M_TX },
+	{ "HDT2MRX", BT_PHY_HDT_2M_RX },
+	{ "HDT3MTX", BT_PHY_HDT_3M_TX },
+	{ "HDT3MRX", BT_PHY_HDT_3M_RX },
+	{ "HDT4MTX", BT_PHY_HDT_4M_TX },
+	{ "HDT4MRX", BT_PHY_HDT_4M_RX },
+	{ "HDT6MTX", BT_PHY_HDT_6M_TX },
+	{ "HDT6MRX", BT_PHY_HDT_6M_RX },
+	{ "HDT75MTX", BT_PHY_HDT_7_5M_TX },
+	{ "HDT75MRX", BT_PHY_HDT_7_5M_RX },
+	{ NULL,		0},
 };
 
 static struct lookup_table bdaddr_types[] = {
@@ -283,6 +306,36 @@ static void hexdump(unsigned char *s, unsigned long l)
 	}
 }
 
+/* Require the MIC length, keeping the security level already set with
+ * -A, -E or -S and only raising it to what encryption needs.
+ */
+static int set_mic_len(int sk)
+{
+	struct bt_security sec;
+	socklen_t optlen = sizeof(sec);
+
+	memset(&sec, 0, sizeof(sec));
+	if (getsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &sec, &optlen) < 0) {
+		syslog(LOG_ERR, "Can't get security: %s (%d)",
+						strerror(errno), errno);
+		return -errno;
+	}
+
+	if (sec.level < BT_SECURITY_MEDIUM)
+		sec.level = BT_SECURITY_MEDIUM;
+
+	sec.mic_len = mic_len;
+
+	if (setsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &sec,
+							sizeof(sec)) < 0) {
+		syslog(LOG_ERR, "Can't set security: %s (%d)",
+						strerror(errno), errno);
+		return -errno;
+	}
+
+	return 0;
+}
+
 static int getopts(int sk, struct l2cap_options *opts, bool connected)
 {
 	socklen_t optlen;
@@ -360,16 +413,45 @@ static const struct bitfield_data phy_table[] = {
 	{ 12, "LE2MRX" },
 	{ 13, "LECODEDTX" },
 	{ 14, "LECODEDRX" },
+	{ 15, "HDT2MTX" },
+	{ 16, "HDT2MRX" },
+	{ 17, "HDT3MTX" },
+	{ 18, "HDT3MRX" },
+	{ 19, "HDT4MTX" },
+	{ 20, "HDT4MRX" },
+	{ 21, "HDT6MTX" },
+	{ 22, "HDT6MRX" },
+	{ 23, "HDT75MTX" },
+	{ 24, "HDT75MRX" },
 	{},
 };
 
+static void print_security(int sk)
+{
+	struct bt_security sec;
+	socklen_t optlen = sizeof(sec);
+
+	memset(&sec, 0, sizeof(sec));
+
+	if (!getsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &sec, &optlen)) {
+		if (optlen < sizeof(sec))
+			syslog(LOG_INFO, "Security [level %d, key_size %d, "
+				"mic_len not available]", sec.level,
+				sec.key_size);
+		else
+			syslog(LOG_INFO, "Security [level %d, key_size %d, "
+				"mic_len %d]", sec.level, sec.key_size,
+					sec.mic_len);
+	}
+}
+
 static int print_info(int sk, struct l2cap_options *opts)
 {
 	struct sockaddr_l2 addr;
 	socklen_t optlen;
+	uint32_t cur_phy;
 	struct l2cap_conninfo conn;
 	int prio;
-	uint32_t phy;
 	char ba[18];
 
 	/* Get connection information */
@@ -425,13 +507,24 @@ static int print_info(int sk, struct l2cap_options *opts)
 		conn.dev_class[0], prio, rcvbuf);
 
 
-	optlen = sizeof(phy);
+	if (phy != -1) {
+		syslog(LOG_INFO, "Setting PHY: 0x%08x", phy);
+		if (setsockopt(sk, SOL_BLUETOOTH, BT_PHY, &phy,
+				sizeof(phy)) < 0) {
+			syslog(LOG_ERR, "setsockopt(BT_PHY): %s (%d)",
+							strerror(errno), errno);
+			return -errno;
+		}
+	}
 
-	if (!getsockopt(sk, SOL_BLUETOOTH, BT_PHY, &phy, &optlen)) {
-		syslog(LOG_INFO, "Supported PHY: 0x%08x", phy);
-		print_bitfield(2, phy, phy_table);
+	optlen = sizeof(cur_phy);
+	if (!getsockopt(sk, SOL_BLUETOOTH, BT_PHY, &cur_phy, &optlen)) {
+		syslog(LOG_INFO, "Supported PHY: 0x%08x", cur_phy);
+		print_bitfield(2, cur_phy, phy_table);
 	}
 
+	print_security(sk);
+
 	return 0;
 }
 
@@ -499,15 +592,6 @@ static int do_connect(char *svr)
 	}
 #endif
 
-	if (chan_policy != -1) {
-		if (setsockopt(sk, SOL_BLUETOOTH, BT_CHANNEL_POLICY,
-				&chan_policy, sizeof(chan_policy)) < 0) {
-			syslog(LOG_ERR, "Can't enable chan policy : %s (%d)",
-							strerror(errno), errno);
-			goto error;
-		}
-	}
-
 	/* Enable SO_LINGER */
 	if (linger) {
 		struct linger l = { .l_onoff = 1, .l_linger = linger };
@@ -538,6 +622,10 @@ static int do_connect(char *svr)
 		goto error;
 	}
 
+	/* Set BT_SECURITY with mic_len */
+	if (mic_len && set_mic_len(sk) < 0)
+		goto error;
+
 	/* Set receive buffer size */
 	if (rcvbuf && setsockopt(sk, SOL_SOCKET, SO_RCVBUF,
 						&rcvbuf, sizeof(rcvbuf)) < 0) {
@@ -641,6 +729,10 @@ static void do_listen(void (*handler)(int sk))
 		goto error;
 	}
 
+	/* Set BT_SECURITY with mic_len */
+	if (mic_len && set_mic_len(sk) < 0)
+		goto error;
+
 	/* Get default options */
 	if (getopts(sk, &opts, false) < 0) {
 		syslog(LOG_ERR, "Can't get default L2CAP options: %s (%d)",
@@ -1355,7 +1447,7 @@ static void usage(void)
 		"\t[-K milliseconds] delay before receiving (default = 0)\n"
 		"\t[-g milliseconds] delay before disconnecting (default = 0)\n"
 		"\t[-X mode] l2cap mode (help for list, default = basic)\n"
-		"\t[-a policy] chan policy (help for list, default = bredr)\n"
+		"\t[-a phy] select PHY (help for list, default = all)\n"
 		"\t[-F fcs] use CRC16 check (default = 1, affects BR/EDR only)\n"
 		"\t[-Q num] Max Transmit value (default = 3)\n"
 		"\t[-Z size] Transmission Window size (default = 63)\n"
@@ -1370,7 +1462,8 @@ static void usage(void)
 		"\t[-M] become central\n"
 		"\t[-T] enable timestamps\n"
 		"\t[-V type] address type (help for list, default = bredr)\n"
-		"\t[-e seq] initial sequence value (default = 0)\n");
+		"\t[-e seq] initial sequence value (default = 0)\n"
+		"\t[-f mic_len] required MIC length (0=32bit, 1=64bit, 2=128bit)\n");
 }
 
 int main(int argc, char *argv[])
@@ -1380,7 +1473,7 @@ int main(int argc, char *argv[])
 
 	bacpy(&bdaddr, BDADDR_ANY);
 
-	while ((opt = getopt(argc, argv, "a:b:cde:g:i:mnpqrstuwxyz"
+	while ((opt = getopt(argc, argv, "a:b:cde:f:g:i:mnpqrstuwxyz"
 		"AB:C:D:EF:GH:I:J:K:L:MN:O:P:Q:RSTUV:W:X:Y:Z:")) != EOF) {
 		switch (opt) {
 		case 'r':
@@ -1510,11 +1603,13 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'a':
-			chan_policy = get_lookup_flag(chan_policies, optarg);
+			if (phy == -1)
+				phy = get_lookup_flag(phys, optarg);
+			else
+				phy |= get_lookup_flag(phys, optarg);
 
-			if (chan_policy == -1) {
-				print_lookup_values(chan_policies,
-						"List L2CAP chan policies:");
+			if (phy == -1) {
+				print_lookup_values(phys, "List L2CAP phys:");
 				exit(1);
 			}
 
@@ -1591,6 +1686,10 @@ int main(int argc, char *argv[])
 			seq_start = atoi(optarg);
 			break;
 
+		case 'f':
+			mic_len = atoi(optarg);
+			break;
+
 		case 'g':
 			disc_delay = atoi(optarg) * 1000;
 			break;
-- 
2.56.0


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

* RE: Add support for HDT and EKS
  2026-11-04 18:36 ` [PATCH BlueZ v2 1/9] lib: Add HDT definitions Luiz Augusto von Dentz
@ 2026-11-04 23:07   ` bluez.test.bot
  0 siblings, 0 replies; 13+ messages in thread
From: bluez.test.bot @ 2026-11-04 23:07 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

[-- Attachment #1: Type: text/plain, Size: 67783 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1202167/

---Test result---

Test Summary:
CheckPatch                    FAIL      7.02 seconds
GitLint                       PASS      2.04 seconds
BuildEll                      PASS      20.81 seconds
BluezMake                     PASS      319.48 seconds
MakeCheck                     PASS      14.74 seconds
MakeDistcheck                 PASS      151.08 seconds
CheckValgrind                 PASS      353.41 seconds
CheckSmatch                   WARNING   347.21 seconds
bluezmakeextell               PASS      103.04 seconds
TestFunctional                FAIL      1232.30 seconds
IncrementalBuild              PASS      575.94 seconds
ScanBuild                     PASS      1204.25 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,v2,2/9] monitor: Add HCI decoding for HDT
WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#161: FILE: monitor/bt.h:259:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#167: FILE: monitor/bt.h:265:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#177: FILE: monitor/bt.h:275:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#182: FILE: monitor/bt.h:280:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#190: FILE: monitor/bt.h:288:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#198: FILE: monitor/bt.h:296:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#205: FILE: monitor/bt.h:303:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#212: FILE: monitor/bt.h:310:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#217: FILE: monitor/bt.h:315:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#233: FILE: monitor/bt.h:3318:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#239: FILE: monitor/bt.h:3324:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#245: FILE: monitor/bt.h:3330:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#256: FILE: monitor/bt.h:3341:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#262: FILE: monitor/bt.h:3347:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#273: FILE: monitor/bt.h:3358:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#282: FILE: monitor/bt.h:3367:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#287: FILE: monitor/bt.h:3372:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#305: FILE: monitor/bt.h:3390:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#318: FILE: monitor/bt.h:3403:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#325: FILE: monitor/bt.h:3410:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#348: FILE: monitor/bt.h:3433:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#363: FILE: monitor/bt.h:3448:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#381: FILE: monitor/bt.h:3466:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#388: FILE: monitor/bt.h:3473:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#411: FILE: monitor/bt.h:3496:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#418: FILE: monitor/bt.h:3503:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#426: FILE: monitor/bt.h:3511:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#436: FILE: monitor/bt.h:3521:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#441: FILE: monitor/bt.h:3526:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#448: FILE: monitor/bt.h:3533:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#454: FILE: monitor/bt.h:3539:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#473: FILE: monitor/bt.h:4528:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#483: FILE: monitor/bt.h:4538:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#494: FILE: monitor/bt.h:4549:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#527: FILE: monitor/bt.h:4582:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#548: FILE: monitor/bt.h:4603:
+} __attribute__ ((packed));

WARNING:LINE_SPACING: Missing a blank line after declarations
#1143: FILE: monitor/packet.c:10542:
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)

WARNING:SPACING: Unnecessary space before function pointer arguments
#1465: FILE: monitor/packet.c:10864:
+	void (*cmd_func) (uint16_t index, const void *data, uint8_t size);

WARNING:SPACING: Unnecessary space before function pointer arguments
#1468: FILE: monitor/packet.c:10867:
+	void (*rsp_func) (uint16_t index, const void *data, uint8_t size);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1589: FILE: monitor/packet.c:10988:
+				enhanced_accept_sync_conn_request_cmd, 63, true },

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1740: FILE: monitor/packet.c:12039:
+				sizeof(struct bt_hci_cmd_le_create_big_v2), true,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1964: FILE: monitor/packet.c:15003:
+				i < (int) (size / sizeof(*evt->bis_handle)); i++)

/home/runner/work/bluez/bluez/src/patch/14946300.patch total: 0 errors, 42 warnings, 1855 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14946300.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v2,3/9] monitor: Add LL decoding for HDT
WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#154: FILE: monitor/ll.c:570:
+				"64 bits" : "128 bits", (v2->flags >> 1) & 0x01);

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#174: FILE: monitor/ll.c:605:
+				"64 bits" : "128 bits", (v2->flags >> 1) & 0x01);

WARNING:LINE_SPACING: Missing a blank line after declarations
#212: FILE: monitor/ll.c:704:
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#241: FILE: monitor/ll.c:777:
+				"64 bits" : "128 bits", (v2->flags >> 4) & 0x01);

/home/runner/work/bluez/bluez/src/patch/14946299.patch total: 0 errors, 4 warnings, 284 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14946299.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v2,4/9] emulator: Add HDT support to btdev
WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#610: FILE: emulator/btdev.c:7220:
+static void le_cis_estabilished_fill(struct bt_hci_evt_le_cis_established_v3 *evt,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#724: FILE: emulator/btdev.c:7306:
+		le_cis_estabilished_fill(&evt, &conn->link->dev->le_cig[cig_idx],

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#858: FILE: emulator/btdev.c:8414:
+	} __attribute__ ((packed)) rsp;

/home/runner/work/bluez/bluez/src/patch/14946302.patch total: 0 errors, 3 warnings, 1207 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14946302.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v2,6/9] shared/gatt: Add MIC length permission checks
WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#572: FILE: unit/test-gatt.c:4735:
+	define_test_server("/robustness/mic-len/read-multiple-variable", test_server,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#593: FILE: unit/test-gatt.c:4756:
+	define_test_server("/robustness/mic-len/read-by-group-type", test_server,

/home/runner/work/bluez/bluez/src/patch/14946316.patch total: 0 errors, 2 warnings, 379 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14946316.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v2,7/9] main.conf: Add HDT configuration
WARNING:STATIC_CONST_CHAR_ARRAY: static const char * array should probably be static const char * const
#213: FILE: src/main.c:193:
+static const char *hdt_options[] = {

/home/runner/work/bluez/bluez/src/patch/14946317.patch total: 0 errors, 1 warnings, 152 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14946317.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v2,8/9] l2cap-tester, iso-tester, mgmt-tester: Add HDT tests
WARNING:MACRO_ARG_UNUSED: Argument 'name' is not used in function-like macro
#392: FILE: tools/iso-tester.c:932:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:MACRO_ARG_UNUSED: Argument 'setup' is not used in function-like macro
#392: FILE: tools/iso-tester.c:932:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:MACRO_ARG_UNUSED: Argument 'func' is not used in function-like macro
#392: FILE: tools/iso-tester.c:932:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#2922: FILE: tools/l2cap-tester.c:3698:
+					BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE_V2,

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#3279: FILE: tools/mgmt-tester.c:14370:
+	} __attribute__((packed)) *cmd = param;

/home/runner/work/bluez/bluez/src/patch/14946319.patch total: 0 errors, 5 warnings, 3136 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14946319.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v2,9/9] l2test: Add HDT options
ERROR:INITIALISED_STATIC: do not initialise statics to 0
#204: FILE: tools/l2test.c:127:
+static int mic_len = 0;

/home/runner/work/bluez/bluez/src/patch/14946318.patch total: 1 errors, 0 warnings, 303 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14946318.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/packet.c:2292:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:4216:52: warning: array of flexible structuresmonitor/bt.h:4204:40: warning: array of flexible structuresemulator/bthost.c:707:28: warning: Variable length array is used.emulator/bthost.c:708:32: warning: Variable length array is used.emulator/bthost.c:961:28: warning: Variable length array is used.emulator/bthost.c:995:28: warning: Variable length array is used.emulator/bthost.c:996:32: warning: Variable length array is used.src/main.c: note: in included file (through src/device.h):
##############################
Test: TestFunctional - FAIL
Desc: Run test-functional
Output:
FAIL functional.test_bearer::test_bearer_le_conn_update[hosts14-vm2]: failed on teardown with "pytest_bluezenv.plugin.CoredumpWarning: Core dump: test-bluezenv-hosts14.1-bluetoothd-1793831616-189.core
        /usr/bin/gdb: warning: Couldn't determine a path for the index cache directory.
        [New LWP 189]
        [Thread debugging using libthread_db enabled]
        Using host libthread_db library "/usr/lib/x86_64-linux-gnu/libthread_db.so.1".
        Core was generated by `/home/runner/work/bluez/bluez/src/src/src/bluetoothd --nodetach -f /run/bluetoo'.
        Program terminated with signal SIGABRT, Aborted.
        #0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=0) at ./nptl/pthread_kill.c:44

        warning: 44	./nptl/pthread_kill.c: No such file or directory

        Thread 1 (Thread 0x7fcc95cd3900 (LWP 189)):
        #0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=0) at ./nptl/pthread_kill.c:44
                tid = <optimized out>
                ret = 0
                pd = <optimized out>
                old_mask = {__val = {4412750543122677053}}
                ret = <optimized out>
        #1  __pthread_kill_internal (threadid=<optimized out>, signo=6) at ./nptl/pthread_kill.c:89
        No locals.
        #2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:100
        No locals.
        #3  0x00007fcc9642eb7e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
                ret = <optimized out>
        #4  0x00007fcc964118ec in __GI_abort () at ./stdlib/abort.c:77
                act = {__sigaction_handler = {sa_handler = 0x0, sa_sigaction = 0x0}, sa_mask = {__val = {0, 136118580285088, 11575157580189038336, 140729153238016, 140729153238304, 140729153238160, 22, 140516667927504, 0, 140729153238096, 140516684772886, 140516659306496, 4096, 0, 11575157580189038336, 140516658184216}}, sa_flags = -1753899008, sa_restorer = 0x16}
        #5  0x00007fcc97039a0f in __sanitizer::Abort () at ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp:165
        No locals.
        #6  0x00007fcc9715fc2d in __sanitizer::Die () at ../../../../src/libsanitizer/sanitizer_common/sanitizer_termination.cpp:58
        No locals.
        #7  0x00007fcc9713493c in __asan::ScopedInErrorReport::~ScopedInErrorReport (this=0x7ffe0f3035c6) at ../../../../src/libsanitizer/asan/asan_report.cpp:221
                buffer_copy = {buffer_ = {<__sanitizer::InternalMmapVectorNoCtor<char, false>> = {data_ = 0x7bcc8ff9b000 '=' <repeats 65 times>, "\n==189==ERROR: AddressSanitizer: heap-use-after-free on address 0x7cdc951e1720 at pc 0x55d5fef5c4cd bp 0x7ffe0f304240 sp 0x7ffe0f304230"..., capacity_bytes_ = 8192, size_ = 4349}, <No data fields>}}
                buffer_copy = <optimized out>
                l = <optimized out>
        #8  0x00007fcc97133e02 in __asan::ReportGenericError (pc=94377593914573, bp=140729153241664, sp=sp@entry=140729153241648, addr=137286836426528, is_write=is_write@entry=false, access_size=8, fatal=true, exp=<optimized out>) at ../../../../src/libsanitizer/asan/asan_report.cpp:536
                in_report = {error_report_lock_ = {<No data fields>}, static current_error_ = {kind = __asan::kErrorKindGeneric, {Base = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, DeadlySignal = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, signal = {siginfo = 0x7fcc00000002, context = 0x7cdc951e1720, addr = 0, pc = 0, sp = 6103148528072, bp = 137286836426528, is_memory_access = 96, write_flag = __sanitizer::SignalContext::Unknown, is_true_faulting_addr = 192}}, DoubleFree = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, second_free_stack = 0x7fcc00000002, addr_description = {addr = 137286836426528, alloc_tid = 0, free_tid = 0, alloc_stack_id = 456, free_stack_id = 1421, chunk_access = {bad_addr = 137286836426528, offset = 96, chunk_begin = 137286836426432, chunk_size = 232, user_requested_alignment = 8, access_type = 2, alloc_type = 1}}}, NewDeleteTypeMismatch = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, free_stack = 0x7fcc00000002, addr_description = {addr = 137286836426528, alloc_tid = 0, free_tid = 0, alloc_stack_id = 456, free_stack_id = 1421, chunk_access = {bad_addr = 137286836426528, offset = 96, chunk_begin = 137286836426432, chunk_size = 232, user_requested_alignment = 8, access_type = 2, alloc_type = 1}}, delete_size = 0, delete_alignment = 140729153239696}, FreeNotMalloced = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, free_stack = 0x7fcc00000002, addr_description = {data = {kind = 2501777184, {shadow = {addr = 0, kind = __asan::kShadowKindLow, shadow_byte = 0 '\000'}, heap = {addr = 0, alloc_tid = 0, free_tid = 6103148528072, alloc_stack_id = 2501777184, free_stack_id = 31964, chunk_access = {bad_addr = 96, offset = 137286836426432, chunk_begin = 232, chunk_size = 140514150080520, user_requested_alignment = 0, access_type = 0, alloc_type = 0}}, stack = {addr = 0, tid = 0, offset = 6103148528072, frame_pc = 137286836426528, access_size = 96, frame_descr = 0x7cdc951e16c0 "\215\005"}, global = {addr = 0, static kMaxGlobals = 4, globals = {{beg = 0, size = 6103148528072, size_with_redzone = 137286836426528, name = 0x60 <error: Cannot access memory at address 0x60>, module_name = 0x7cdc951e16c0 "\215\005", has_dynamic_init = 232, gcc_location = 0x7fcc00006008, odr_indicator = 0}, {beg = 140729153239696, size = 140516684812594, size_with_redzone = 140729153239776, name = 0x2 <error: Cannot access memory at address 0x2>, module_name = 0x7fcc00000000 "", has_dynamic_init = 140516690451664, gcc_location = 0x7ffe0000058f, odr_indicator = 140516655126768}, {beg = 140729153239824, size = 2, size_with_redzone = 140516685340608, name = 0x7cac951e0b90 "\003\021", module_name = 0x7ffe0f303ae0 "0C0\017\376\177", has_dynamic_init = 140516683691832, gcc_location = 0xa0, odr_indicator = 137080677993360}, {beg = 140516659417296, size = 140729153239808, size_with_redzone = 137080677993376, name = 0x55d5fee70a40 <device_free> "\363\017\036\372USH\211\373H\203\354\030H\205\377\017\204-\n", module_name = 0x7ffe0f304410 "", has_dynamic_init = 136118585380640, gcc_location = 0x7ffe0f304330, odr_indicator = 140516684620737}}, reg_sites = {254819072, 32766, 2522642050, 30}, access_size = 140729153239824, size = 205 '\315'}, wild = {addr = 0, access_size = 0}}}}}, AllocTypeMismatch = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, dealloc_stack = 0x7fcc00000002, alloc_type = 2501777184, dealloc_type = 31964, addr_description = {data = {kind = __asan::kAddressKindWild, {shadow = {addr = 0, kind = (unknown: 0xc8), shadow_byte = 1 '\001'}, heap = {addr = 0, alloc_tid = 6103148528072, free_tid = 137286836426528, alloc_stack_id = 96, free_stack_id = 0, chunk_access = {bad_addr = 137286836426432, offset = 232, chunk_begin = 140514150080520, chunk_size = 0, user_requested_alignment = 2704, access_type = 3, alloc_type = 0}}, stack = {addr = 0, tid = 6103148528072, offset = 137286836426528, frame_pc = 96, access_size = 137286836426432, frame_descr = 0xe8 <error: Cannot access memory at address 0xe8>}, global = {addr = 0, static kMaxGlobals = 4, globals = {{beg = 6103148528072, size = 137286836426528, size_with_redzone = 96, name = 0x7cdc951e16c0 "\215\005", module_name = 0xe8 <error: Cannot access memory at address 0xe8>, has_dynamic_init = 140514150080520, gcc_location = 0x0, odr_indicator = 140729153239696}, {beg = 140516684812594, size = 140729153239776, size_with_redzone = 2, name = 0x7fcc00000000 "", module_name = 0x7fcc976b5cd0 <__sanitizer::theDepot+4178832> "\217\005", has_dynamic_init = 140728898422159, gcc_location = 0x7fcc955058f0, odr_indicator = 140729153239824}, {beg = 2, size = 140516685340608, size_with_redzone = 137080677993360, name = 0x7ffe0f303ae0 "0C0\017\376\177", module_name = 0x7fcc97043738 <__sanitizer::Quarantine<__asan::QuarantineCallback, __asan::AsanChunk>::Put(__sanitizer::QuarantineCache<__asan::QuarantineCallback>*, __asan::QuarantineCallback, __asan::AsanChunk*, unsigned long)+248> "H\203;", has_dynamic_init = 160, gcc_location = 0x7cac951e0b90, odr_indicator = 140516659417296}, {beg = 140729153239808, size = 137080677993376, size_with_redzone = 94377592949312, name = 0x7ffe0f304410 "", module_name = 0x7bcc93edcf20 "0W\036\225<|", has_dynamic_init = 140729153241904, gcc_location = 0x7fcc971263c1 <___interceptor_free(void*)+113>, odr_indicator = 140729153239808}}, reg_sites = {2522642050, 30, 254819088, 32766}, access_size = 94377593914573, size = 64 '@'}, wild = {addr = 0, access_size = 6103148528072}}}}}, MallocUsableSizeNotOwned = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, addr_description = {data = {kind = 2501777184, {shadow = {addr = 0, kind = __asan::kShadowKindLow, shadow_byte = 0 '\000'}, heap = {addr = 0, alloc_tid = 0, free_tid = 6103148528072, alloc_stack_id = 2501777184, free_stack_id = 31964, chunk_access = {bad_addr = 96, offset = 137286836426432, chunk_begin = 232, chunk_size = 140514150080520, user_requested_alignment = 0, access_type = 0, alloc_type = 0}}, stack = {addr = 0, tid = 0, offset = 6103148528072, frame_pc = 137286836426528, access_size = 96, frame_descr = 0x7cdc951e16c0 "\215\005"}, global = {addr = 0, static kMaxGlobals = 4, globals = {{beg = 0, size = 6103148528072, size_with_redzone = 137286836426528, name = 0x60 <error: Cannot access memory at address 0x60>, module_name = 0x7cdc951e16c0 "\215\005", has_dynamic_init = 232, gcc_location = 0x7fcc00006008, odr_indicator = 0}, {beg = 140729153239696, size = 140516684812594, size_with_redzone = 140729153239776, name = 0x2 <error: Cannot access memory at address 0x2>, module_name = 0x7fcc00000000 "", has_dynamic_init = 140516690451664, gcc_location = 0x7ffe0000058f, odr_indicator = 140516655126768}, {beg = 140729153239824, size = 2, size_with_redzone = 140516685340608, name = 0x7cac951e0b90 "\003\021", module_name = 0x7ffe0f303ae0 "0C0\017\376\177", has_dynamic_init = 140516683691832, gcc_location = 0xa0, odr_indicator = 137080677993360}, {beg = 140516659417296, size = 140729153239808, size_with_redzone = 137080677993376, name = 0x55d5fee70a40 <device_free> "\363\017\036\372USH\211\373H\203\354\030H\205\377\017\204-\n", module_name = 0x7ffe0f304410 "", has_dynamic_init = 136118585380640, gcc_location = 0x7ffe0f304330, odr_indicator = 140516684620737}}, reg_sites = {254819072, 32766, 2522642050, 30}, access_size = 140729153239824, size = 205 '\315'}, wild = {addr = 0, access_size = 0}}}}}, SanitizerGetAllocatedSizeNotOwned = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, addr_description = {data = {kind = 2501777184, {shadow = {addr = 0, kind = __asan::kShadowKindLow, shadow_byte = 0 '\000'}, heap = {addr = 0, alloc_tid = 0, free_tid = 6103148528072, alloc_stack_id = 2501777184, free_stack_id = 31964, chunk_access = {bad_addr = 96, offset = 137286836426432, chunk_begin = 232, chunk_size = 140514150080520, user_requested_alignment = 0, access_type = 0, alloc_type = 0}}, stack = {addr = 0, tid = 0, offset = 6103148528072, frame_pc = 137286836426528, access_size = 96, frame_descr = 0x7cdc951e16c0 "\215\005"}, global = {addr = 0, static kMaxGlobals = 4, globals = {{beg = 0, size = 6103148528072, size_with_redzone = 137286836426528, name = 0x60 <error: Cannot access memory at address 0x60>, module_name = 0x7cdc951e16c0 "\215\005", has_dynamic_init = 232, gcc_location = 0x7fcc00006008, odr_indicator = 0}, {beg = 140729153239696, size = 140516684812594, size_with_redzone = 140729153239776, name = 0x2 <error: Cannot access memory at address 0x2>, module_name = 0x7fcc00000000 "", has_dynamic_init = 140516690451664, gcc_location = 0x7ffe0000058f, odr_indicator = 140516655126768}, {beg = 140729153239824, size = 2, size_with_redzone = 140516685340608, name = 0x7cac951e0b90 "\003\021", module_name = 0x7ffe0f303ae0 "0C0\017\376\177", has_dynamic_init = 140516683691832, gcc_location = 0xa0, odr_indicator = 137080677993360}, {beg = 140516659417296, size = 140729153239808, size_with_redzone = 137080677993376, name = 0x55d5fee70a40 <device_free> "\363\017\036\372USH\211\373H\203\354\030H\205\377\017\204-\n", module_name = 0x7ffe0f304410 "", has_dynamic_init = 136118585380640, gcc_location = 0x7ffe0f304330, odr_indicator = 140516684620737}}, reg_sites = {254819072, 32766, 2522642050, 30}, access_size = 140729153239824, size = 205 '\315'}, wild = {addr = 0, access_size = 0}}}}}, CallocOverflow = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, count = 137286836426528, size = 0}, ReallocArrayOverflow = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, count = 137286836426528, size = 0}, PvallocOverflow = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, size = 137286836426528}, InvalidAllocationAlignment = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, alignment = 137286836426528}, InvalidAlignedAllocAlignment = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, size = 137286836426528, alignment = 0}, InvalidPosixMemalignAlignment = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, alignment = 137286836426528}, AllocationSizeTooBig = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, user_size = 137286836426528, total_size = 0, max_size = 0}, RssLimitExceeded = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002}, OutOfMemory = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, requested_size = 137286836426528}, StringFunctionMemoryRangesOverlap = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, length1 = 137286836426528, length2 = 0, addr1_description = {data = {kind = __asan::kAddressKindWild, {shadow = {addr = 6103148528072, kind = (unknown: 0x20), shadow_byte = 23 '\027'}, heap = {addr = 6103148528072, alloc_tid = 137286836426528, free_tid = 96, alloc_stack_id = 2501777088, free_stack_id = 31964, chunk_access = {bad_addr = 232, offset = 140514150080520, chunk_begin = 0, chunk_size = 140729153239696, user_requested_alignment = 306, access_type = 1, alloc_type = 1}}, stack = {addr = 6103148528072, tid = 137286836426528, offset = 96, frame_pc = 137286836426432, access_size = 232, frame_descr = 0x7fcc00006008 ""}, global = {addr = 6103148528072, static kMaxGlobals = 4, globals = {{beg = 137286836426528, size = 96, size_with_redzone = 137286836426432, name = 0xe8 <error: Cannot access memory at address 0xe8>, module_name = 0x7fcc00006008 "", has_dynamic_init = 0, gcc_location = 0x7ffe0f303a90, odr_indicator = 140516684812594}, {beg = 140729153239776, size = 2, size_with_redzone = 140514150055936, name = 0x7fcc976b5cd0 <__sanitizer::theDepot+4178832> "\217\005", module_name = 0x7ffe0000058f <error: Cannot access memory at address 0x7ffe0000058f>, has_dynamic_init = 140516655126768, gcc_location = 0x7ffe0f303b10, odr_indicator = 2}, {beg = 140516685340608, size = 137080677993360, size_with_redzone = 140729153239776, name = 0x7fcc97043738 <__sanitizer::Quarantine<__asan::QuarantineCallback, __asan::AsanChunk>::Put(__sanitizer::QuarantineCache<__asan::QuarantineCallback>*, __asan::QuarantineCallback, __asan::AsanChunk*, unsigned long)+248> "H\203;", module_name = 0xa0 <error: Cannot access memory at address 0xa0>, has_dynamic_init = 137080677993360, gcc_location = 0x7fcc9591d0d0, odr_indicator = 140729153239808}, {beg = 137080677993376, size = 94377592949312, size_with_redzone = 140729153242128, name = 0x7bcc93edcf20 "0W\036\225<|", module_name = 0x7ffe0f304330 "\200\t\036\225<}", has_dynamic_init = 140516684620737, gcc_location = 0x7ffe0f303b00, odr_indicator = 131371660930}}, reg_sites = {254819088, 32766, 4277519565, 21973}, access_size = 140729153241664, size = 48 '0'}, wild = {addr = 6103148528072, access_size = 137286836426528}}}}, addr2_description = {data = {kind = 8, {shadow = {addr = 140516685051799, kind = __asan::kShadowKindLow, shadow_byte = 253 '\375'}, heap = {addr = 140516685051799, alloc_tid = 140516672929024, free_tid = 136118586522784, alloc_stack_id = 4279184864, free_stack_id = 21973, chunk_access = {bad_addr = 30064771156, offset = 140516684881789, chunk_begin = 136118586522912, chunk_size = 140516684881789, user_requested_alignment = 264, access_type = 0, alloc_type = 1}}, stack = {addr = 140516685051799, tid = 140516672929024, offset = 136118586522784, frame_pc = 94377595579872, access_size = 30064771156, frame_descr = 0x7fcc97165f7d <__sanitizer::DTLS_on_tls_get_addr(void*, void*, unsigned long, unsigned long)+125> "I\211\302H\205\300u\035\351\213"}, global = {addr = 140516685051799, static kMaxGlobals = 4, globals = {{beg = 140516672929024, size = 136118586522784, size_with_redzone = 94377595579872, name = 0x700000054 <error: Cannot access memory at address 0x700000054>, module_name = 0x7fcc97165f7d <__sanitizer::DTLS_on_tls_get_addr(void*, void*, unsigned long, unsigned long)+125> "I\211\302H\205\300u\035\351\213", has_dynamic_init = 136118586522912, gcc_location = 0x7fcc97165f7d <__sanitizer::DTLS_on_tls_get_addr(void*, void*, unsigned long, unsigned long)+125>, odr_indicator = 140729153241352}, {beg = 11575157580189038336, size = 140729153241368, size_with_redzone = 140516685315960, name = 0x0, module_name = 0x7bec951f6350 "\240|\036\225,|", has_dynamic_init = 140516663310520, gcc_location = 0x7bfc951ea510, odr_indicator = 140729153241408}, {beg = 136668361135648, size = 136118585380800, size_with_redzone = 136256044352240, name = 0x7bcc93edcfe0 "", module_name = 0xb <error: Cannot access memory at address 0xb>, has_dynamic_init = 136118585380800, gcc_location = 0x0, odr_indicator = 94377593838688}, {beg = 0, size = 136668361135648, size_with_redzone = 94377593880292, name = 0x7ccc951e1440 "", module_name = 0x7bcc93edd020 "", has_dynamic_init = 17014823172600, gcc_location = 0x7ffe0f3041b0, odr_indicator = 137218116949064}}, reg_sites = {2534825853, 32716, 2513254584, 32716}, access_size = 94377593309536, size = 224 '\340'}, wild = {addr = 140516685051799, access_size = 140516672929024}}}}, function = 0xa0a3387dca567700 <error: Cannot access memory at address 0xa0a3387dca567700>}, StringFunctionSizeOverflow = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, addr_description = {data = {kind = 2501777184, {shadow = {addr = 0, kind = __asan::kShadowKindLow, shadow_byte = 0 '\000'}, heap = {addr = 0, alloc_tid = 0, free_tid = 6103148528072, alloc_stack_id = 2501777184, free_stack_id = 31964, chunk_access = {bad_addr = 96, offset = 137286836426432, chunk_begin = 232, chunk_size = 140514150080520, user_requested_alignment = 0, access_type = 0, alloc_type = 0}}, stack = {addr = 0, tid = 0, offset = 6103148528072, frame_pc = 137286836426528, access_size = 96, frame_descr = 0x7cdc951e16c0 "\215\005"}, global = {addr = 0, static kMaxGlobals = 4, globals = {{beg = 0, size = 6103148528072, size_with_redzone = 137286836426528, name = 0x60 <error: Cannot access memory at address 0x60>, module_name = 0x7cdc951e16c0 "\215\005", has_dynamic_init = 232, gcc_location = 0x7fcc00006008, odr_indicator = 0}, {beg = 140729153239696, size = 140516684812594, size_with_redzone = 140729153239776, name = 0x2 <error: Cannot access memory at address 0x2>, module_name = 0x7fcc00000000 "", has_dynamic_init = 140516690451664, gcc_location = 0x7ffe0000058f, odr_indicator = 140516655126768}, {beg = 140729153239824, size = 2, size_with_redzone = 140516685340608, name = 0x7cac951e0b90 "\003\021", module_name = 0x7ffe0f303ae0 "0C0\017\376\177", has_dynamic_init = 140516683691832, gcc_location = 0xa0, odr_indicator = 137080677993360}, {beg = 140516659417296, size = 140729153239808, size_with_redzone = 137080677993376, name = 0x55d5fee70a40 <device_free> "\363\017\036\372USH\211\373H\203\354\030H\205\377\017\204-\n", module_name = 0x7ffe0f304410 "", has_dynamic_init = 136118585380640, gcc_location = 0x7ffe0f304330, odr_indicator = 140516684620737}}, reg_sites = {254819072, 32766, 2522642050, 30}, access_size = 140729153239824, size = 205 '\315'}, wild = {addr = 0, access_size = 0}}}}, size = 140729153241664}, BadParamsToAnnotateContiguousContainer = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, beg = 137286836426528, end = 0, old_mid = 0, new_mid = 6103148528072}, BadParamsToAnnotateDoubleEndedContiguousContainer = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, storage_beg = 137286836426528, storage_end = 0, old_container_beg = 0, old_container_end = 6103148528072, new_container_beg = 137286836426528, new_container_end = 96}, BadParamsToCopyContiguousContainerAnnotations = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, stack = 0x7fcc00000002, old_storage_beg = 137286836426528, old_storage_end = 0, new_storage_beg = 0, new_storage_end = 6103148528072}, ODRViolation = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, global1 = {beg = 140514150055938, size = 137286836426528, size_with_redzone = 0, name = 0x0, module_name = 0x58d000001c8 <error: Cannot access memory at address 0x58d000001c8>, has_dynamic_init = 137286836426528, gcc_location = 0x60, odr_indicator = 137286836426432}, global2 = {beg = 232, size = 140514150080520, size_with_redzone = 0, name = 0x7ffe0f303a90 "\340:0\017\376\177", module_name = 0x7fcc97155132 <__sanitizer::StackDepotBase<__sanitizer::StackDepotNode, 1, 20>::Put(__sanitizer::StackTrace, bool*)+690> "H\213E\330D\213E\300D\211@\bD\213U\320L\213]\310E\211\023M\205\366\017\204\256\376\377\377A\306\006\001H\213]\360L\213u\370\351\245\376\377\377\203\372\t~+L\211M\300\211U\310H\211M\320L\211]\330\350\3649\377\377L\213M\300\213U\310H\213M\320L\213]\330\203\302\001\351\217\376\377\377\270\n", has_dynamic_init = 140729153239776, gcc_location = 0x2, odr_indicator = 140514150055936}, stack_id1 = 2540395728, stack_id2 = 32716}, InvalidPointerPair = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, pc = 140514150055938, bp = 137286836426528, sp = 0, addr1_description = {data = {kind = __asan::kAddressKindWild, {shadow = {addr = 6103148528072, kind = (unknown: 0x20), shadow_byte = 23 '\027'}, heap = {addr = 6103148528072, alloc_tid = 137286836426528, free_tid = 96, alloc_stack_id = 2501777088, free_stack_id = 31964, chunk_access = {bad_addr = 232, offset = 140514150080520, chunk_begin = 0, chunk_size = 140729153239696, user_requested_alignment = 306, access_type = 1, alloc_type = 1}}, stack = {addr = 6103148528072, tid = 137286836426528, offset = 96, frame_pc = 137286836426432, access_size = 232, frame_descr = 0x7fcc00006008 ""}, global = {addr = 6103148528072, static kMaxGlobals = 4, globals = {{beg = 137286836426528, size = 96, size_with_redzone = 137286836426432, name = 0xe8 <error: Cannot access memory at address 0xe8>, module_name = 0x7fcc00006008 "", has_dynamic_init = 0, gcc_location = 0x7ffe0f303a90, odr_indicator = 140516684812594}, {beg = 140729153239776, size = 2, size_with_redzone = 140514150055936, name = 0x7fcc976b5cd0 <__sanitizer::theDepot+4178832> "\217\005", module_name = 0x7ffe0000058f <error: Cannot access memory at address 0x7ffe0000058f>, has_dynamic_init = 140516655126768, gcc_location = 0x7ffe0f303b10, odr_indicator = 2}, {beg = 140516685340608, size = 137080677993360, size_with_redzone = 140729153239776, name = 0x7fcc97043738 <__sanitizer::Quarantine<__asan::QuarantineCallback, __asan::AsanChunk>::Put(__sanitizer::QuarantineCache<__asan::QuarantineCallback>*, __asan::QuarantineCallback, __asan::AsanChunk*, unsigned long)+248> "H\203;", module_name = 0xa0 <error: Cannot access memory at address 0xa0>, has_dynamic_init = 137080677993360, gcc_location = 0x7fcc9591d0d0, odr_indicator = 140729153239808}, {beg = 137080677993376, size = 94377592949312, size_with_redzone = 140729153242128, name = 0x7bcc93edcf20 "0W\036\225<|", module_name = 0x7ffe0f304330 "\200\t\036\225<}", has_dynamic_init = 140516684620737, gcc_location = 0x7ffe0f303b00, odr_indicator = 131371660930}}, reg_sites = {254819088, 32766, 4277519565, 21973}, access_size = 140729153241664, size = 48 '0'}, wild = {addr = 6103148528072, access_size = 137286836426528}}}}, addr2_description = {data = {kind = 8, {shadow = {addr = 140516685051799, kind = __asan::kShadowKindLow, shadow_byte = 253 '\375'}, heap = {addr = 140516685051799, alloc_tid = 140516672929024, free_tid = 136118586522784, alloc_stack_id = 4279184864, free_stack_id = 21973, chunk_access = {bad_addr = 30064771156, offset = 140516684881789, chunk_begin = 136118586522912, chunk_size = 140516684881789, user_requested_alignment = 264, access_type = 0, alloc_type = 1}}, stack = {addr = 140516685051799, tid = 140516672929024, offset = 136118586522784, frame_pc = 94377595579872, access_size = 30064771156, frame_descr = 0x7fcc97165f7d <__sanitizer::DTLS_on_tls_get_addr(void*, void*, unsigned long, unsigned long)+125> "I\211\302H\205\300u\035\351\213"}, global = {addr = 140516685051799, static kMaxGlobals = 4, globals = {{beg = 140516672929024, size = 136118586522784, size_with_redzone = 94377595579872, name = 0x700000054 <error: Cannot access memory at address 0x700000054>, module_name = 0x7fcc97165f7d <__sanitizer::DTLS_on_tls_get_addr(void*, void*, unsigned long, unsigned long)+125> "I\211\302H\205\300u\035\351\213", has_dynamic_init = 136118586522912, gcc_location = 0x7fcc97165f7d <__sanitizer::DTLS_on_tls_get_addr(void*, void*, unsigned long, unsigned long)+125>, odr_indicator = 140729153241352}, {beg = 11575157580189038336, size = 140729153241368, size_with_redzone = 140516685315960, name = 0x0, module_name = 0x7bec951f6350 "\240|\036\225,|", has_dynamic_init = 140516663310520, gcc_location = 0x7bfc951ea510, odr_indicator = 140729153241408}, {beg = 136668361135648, size = 136118585380800, size_with_redzone = 136256044352240, name = 0x7bcc93edcfe0 "", module_name = 0xb <error: Cannot access memory at address 0xb>, has_dynamic_init = 136118585380800, gcc_location = 0x0, odr_indicator = 94377593838688}, {beg = 0, size = 136668361135648, size_with_redzone = 94377593880292, name = 0x7ccc951e1440 "", module_name = 0x7bcc93edd020 "", has_dynamic_init = 17014823172600, gcc_location = 0x7ffe0f3041b0, odr_indicator = 137218116949064}}, reg_sites = {2534825853, 32716, 2513254584, 32716}, access_size = 94377593309536, size = 224 '\340'}, wild = {addr = 140516685051799, access_size = 140516672929024}}}}}, Generic = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, addr_description = {data = {kind = __asan::kAddressKindHeap, {shadow = {addr = 137286836426528, kind = __asan::kShadowKindLow, shadow_byte = 0 '\000'}, heap = {addr = 137286836426528, alloc_tid = 0, free_tid = 0, alloc_stack_id = 456, free_stack_id = 1421, chunk_access = {bad_addr = 137286836426528, offset = 96, chunk_begin = 137286836426432, chunk_size = 232, user_requested_alignment = 8, access_type = 2, alloc_type = 1}}, stack = {addr = 137286836426528, tid = 0, offset = 0, frame_pc = 6103148528072, access_size = 137286836426528, frame_descr = 0x60 <error: Cannot access memory at address 0x60>}, global = {addr = 137286836426528, static kMaxGlobals = 4, globals = {{beg = 0, size = 0, size_with_redzone = 6103148528072, name = 0x7cdc951e1720 "\240\025\036\225L|", module_name = 0x60 <error: Cannot access memory at address 0x60>, has_dynamic_init = 137286836426432, gcc_location = 0xe8, odr_indicator = 140514150080520}, {beg = 0, size = 140729153239696, size_with_redzone = 140516684812594, name = 0x7ffe0f303ae0 "0C0\017\376\177", module_name = 0x2 <error: Cannot access memory at address 0x2>, has_dynamic_init = 140514150055936, gcc_location = 0x7fcc976b5cd0 <__sanitizer::theDepot+4178832>, odr_indicator = 140728898422159}, {beg = 140516655126768, size = 140729153239824, size_with_redzone = 2, name = 0x7fcc971d5fc0 <__asan::instance> "", module_name = 0x7cac951e0b90 "\003\021", has_dynamic_init = 140729153239776, gcc_location = 0x7fcc97043738 <__sanitizer::Quarantine<__asan::QuarantineCallback, __asan::AsanChunk>::Put(__sanitizer::QuarantineCache<__asan::QuarantineCallback>*, __asan::QuarantineCallback, __asan::AsanChunk*, unsigned long)+248>, odr_indicator = 160}, {beg = 137080677993360, size = 140516659417296, size_with_redzone = 140729153239808, name = 0x7cac951e0ba0 "\217\005", module_name = 0x55d5fee70a40 <device_free> "\363\017\036\372USH\211\373H\203\354\030H\205\377\017\204-\n", has_dynamic_init = 140729153242128, gcc_location = 0x7bcc93edcf20, odr_indicator = 140729153241904}}, reg_sites = {2534564801, 32716, 254819072, 32766}, access_size = 131371660930, size = 16 '\020'}, wild = {addr = 137286836426528, access_size = 0}}}}, pc = 94377593914573, bp = 140729153241664, sp = 140729153241648, access_size = 8, bug_descr = 0x7fcc9718f797 "heap-use-after-free", is_write = false, shadow_val = 253 '\375'}}}, halt_on_error_ = true}
                error = {<__asan::ErrorBase> = {scariness = {score = 51, descr = "8-byte-read-heap-use-after-free\000\314{\000\000\260>0\017\376\177\000\0000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\220>0\017\376\177\000\000\034\313\r\227\314\177", '\000' <repeats 26 times>, "\305\374\023\227\314\177\000\000\340~\036\225,|\000\000:\000\000\000\000\000\000\000\300~\036\225,|\000\000\320~\036\225,|\000\000\36060\017\376\177\000\000\005\\\b\227\314\177\000\000P\b!\224\314{\000\000\000\320\221\225\314\177\000\000\001\000\000\000\000\000\000\000\001\000\000\000\325\000\001\001\000\000\000\000\000\000\000\000\370\377\377\377"...}, tid = 0}, addr_description = {data = {kind = __asan::kAddressKindHeap, {shadow = {addr = 137286836426528, kind = __asan::kShadowKindLow, shadow_byte = 0 '\000'}, heap = {addr = 137286836426528, alloc_tid = 0, free_tid = 0, alloc_stack_id = 456, free_stack_id = 1421, chunk_access = {bad_addr = 137286836426528, offset = 96, chunk_begin = 137286836426432, chunk_size = 232, user_requested_alignment = 8, access_type = 2, alloc_type = 1}}, stack = {addr = 137286836426528, tid = 0, offset = 0, frame_pc = 6103148528072, access_size = 137286836426528, frame_descr = 0x60 <error: Cannot access memory at address 0x60>}, global = {addr = 137286836426528, static kMaxGlobals = 4, globals = {{beg = 0, size = 0, size_with_redzone = 6103148528072, name = 0x7cdc951e1720 "\240\025\036\225L|", module_name = 0x60 <error: Cannot access memory at address 0x60>, has_dynamic_init = 137286836426432, gcc_location = 0xe8, odr_indicator = 140514150080520}, {beg = 0, size = 140729153239696, size_with_redzone = 140516684812594, name = 0x7ffe0f303ae0 "0C0\017\376\177", module_name = 0x2 <error: Cannot access memory at address 0x2>, has_dynamic_init = 140514150055936, gcc_location = 0x7fcc976b5cd0 <__sanitizer::theDepot+4178832>, odr_indicator = 140728898422159}, {beg = 140516655126768, size = 140729153239824, size_with_redzone = 2, name = 0x7fcc971d5fc0 <__asan::instance> "", module_name = 0x7cac951e0b90 "\003\021", has_dynamic_init = 140729153239776, gcc_location = 0x7fcc97043738 <__sanitizer::Quarantine<__asan::QuarantineCallback, __asan::AsanChunk>::Put(__sanitizer::QuarantineCache<__asan::QuarantineCallback>*, __asan::QuarantineCallback, __asan::AsanChunk*, unsigned long)+248>, odr_indicator = 160}, {beg = 137080677993360, size = 140516659417296, size_with_redzone = 140729153239808, name = 0x7cac951e0ba0 "\217\005", module_name = 0x55d5fee70a40 <device_free> "\363\017\036\372USH\211\373H\203\354\030H\205\377\017\204-\n", has_dynamic_init = 140729153242128, gcc_location = 0x7bcc93edcf20, odr_indicator = 140729153241904}}, reg_sites = {2534564801, 32716, 254819072, 32766}, access_size = 131371660930, size = 16 '\020'}, wild = {addr = 137286836426528, access_size = 0}}}}, pc = 94377593914573, bp = 140729153241664, sp = 140729153241648, access_size = 8, bug_descr = 0x7fcc9718f797 "heap-use-after-free", is_write = false, shadow_val = 253 '\375'}
        #9  0x00007fcc97133f8d in __asan::ReportGenericError (pc=<optimized out>, bp=bp@entry=140729153241664, sp=sp@entry=140729153241648, addr=<optimized out>, is_write=is_write@entry=false, access_size=access_size@entry=8, exp=<optimized out>, fatal=true) at ../../../../src/libsanitizer/asan/asan_report.cpp:536
                in_report = <optimized out>
                error = <optimized out>
                enable_fp = <optimized out>
        #10 0x00007fcc971353f9 in __asan::__asan_report_load8 (addr=<optimized out>) at ../../../../src/libsanitizer/asan/asan_rtl.cpp:131
                bp = 140729153241664
                pc = <optimized out>
                local_stack = 136256044360528
                sp = 140729153241648
        #11 0x000055d5fef5c4cd in discovery_op_free (op=0x7c4c951e16a0) at src/shared/gatt-client.c:407
        No locals.
        #12 0x000055d5ff08986a in bt_gatt_request_unref (req=0x7c4c951e1fa0) at src/shared/gatt-helpers.c:577
        No locals.
        #13 bt_gatt_request_unref (req=0x7c4c951e1fa0) at src/shared/gatt-helpers.c:566
        No locals.
        #14 0x000055d5fef4a1d4 in destroy_att_send_op (data=0x7c2c951e7ca0) at src/shared/att.c:216
                op = 0x7c2c951e7ca0
        #15 0x000055d5fef07e52 in queue_remove_all (queue=0x7bfc951ea510, function=function@entry=0x0, user_data=user_data@entry=0x0, destroy=destroy@entry=0x55d5fef4a0f0 <destroy_att_send_op>) at src/shared/queue.c:341
                tmp = 0x7bec951f6350
                entry = 0x0
                count = <optimized out>
        #16 0x000055d5fef54556 in bt_att_cancel_all (att=0x7ccc951e1440) at src/shared/att.c:1940
                entry = <optimized out>
        #17 bt_att_cancel_all (att=0x7ccc951e1440) at src/shared/att.c:1933
                entry = <optimized out>
                chan = <optimized out>
        #18 0x000055d5fef55490 in bt_att_unref (att=0x7ccc951e1440) at src/shared/att.c:1351
        No locals.
        #19 bt_att_unref (att=0x7ccc951e1440) at src/shared/att.c:1342
        No locals.
        #20 0x000055d5fee706af in attio_cleanup (device=device@entry=0x7d3c951e0780) at src/device.c:873
        No locals.
        #21 0x000055d5fee70be7 in device_free (user_data=0x7d3c951e0780) at src/device.c:918
                device = 0x7d3c951e0780
                __func__ = "device_free"
        #22 0x000055d5feef19aa in remove_interface (data=0x7c3c951e5730, name=name@entry=0x55d5ff117500 "org.bluez.Device1") at gdbus/object.c:742
                iface = 0x7c2c951e6260
        #23 0x000055d5feef456c in g_dbus_unregister_interface (connection=<optimized out>, path=<optimized out>, name=<optimized out>) at gdbus/object.c:1499
                data = <optimized out>
        #24 0x000055d5fee2682b in remove_temporary_devices (adapter=adapter@entry=0x7cfc951e0200) at src/adapter.c:826
                dev = 0x7d3c951e0780
                l = <optimized out>
                next = 0x0
        #25 0x000055d5fee27b8a in adapter_shutdown () at src/adapter.c:11531
                adapter = 0x7cfc951e0200
                list = 0x7bfc951e3a00 = {0x7cfc951e0200}
                __func__ = "adapter_shutdown"
        #26 0x000055d5feec89dc in signal_callback (signum=<optimized out>, user_data=<optimized out>) at src/main.c:1550
                terminated = false
        #27 signal_callback (signum=<optimized out>, user_data=<optimized out>) at src/main.c:1537
                terminated = false
        #28 0x000055d5ff07ddfe in signal_read (io=<optimized out>, user_data=0x7bfc951e35b0) at src/shared/mainloop-notify.c:145
                data = <optimized out>
                si = <optimized out>
                result = <optimized out>
                fd = <optimized out>
        #29 0x000055d5ff07acf5 in watch_callback (channel=<optimized out>, cond=<optimized out>, user_data=<optimized out>) at src/shared/io-glib.c:173
                watch = <optimized out>
                result = <optimized out>
                destroy = <optimized out>
        #30 0x00007fcc96e3fb9b in ?? () from /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
        No symbol table info available.
        #31 0x00007fcc96e411d7 in ?? () from /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
        No symbol table info available.
        #32 0x00007fcc96e41577 in g_main_loop_run () from /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
        No symbol table info available.
        #33 0x000055d5ff07dc59 in mainloop_run () at src/shared/mainloop-glib.c:65
        No locals.
        #34 0x000055d5ff07e58b in mainloop_run_with_signal (func=func@entry=0x55d5feec8960 <signal_callback>, user_data=user_data@entry=0x0) at src/shared/mainloop-notify.c:196
                data = 0x7bfc951e35b0
                io = 0x7c0c951f9690
                ret = <optimized out>
        #35 0x000055d5febf93ac in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:1778
                context = <optimized out>
                err = <optimized out>
                sdp_mtu = 0
                sdp_flags = <optimized out>
                gdbus_flags = <optimized out>
                __func__ = "main""


https://github.com/bluez/bluez/pull/2761

---
Regards,
Linux Bluetooth


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

* RE: Add support for HDT and EKS
  2026-11-04 22:20 [PATCH BlueZ v3 01/10] lib: Add HDT definitions Luiz Augusto von Dentz
@ 2026-11-05  3:06 ` bluez.test.bot
  0 siblings, 0 replies; 13+ messages in thread
From: bluez.test.bot @ 2026-11-05  3:06 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

[-- Attachment #1: Type: text/plain, Size: 16240 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1202520/

---Test result---

Test Summary:
CheckPatch                    FAIL      9.11 seconds
GitLint                       PASS      2.90 seconds
BuildEll                      PASS      20.41 seconds
BluezMake                     PASS      315.36 seconds
MakeCheck                     PASS      19.60 seconds
MakeDistcheck                 PASS      149.23 seconds
CheckValgrind                 PASS      351.95 seconds
CheckSmatch                   WARNING   338.11 seconds
bluezmakeextell               PASS      99.95 seconds
TestFunctional                PASS      1186.21 seconds
IncrementalBuild              PASS      575.08 seconds
ScanBuild                     PASS      1185.30 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,v3,03/10] monitor: Add HCI decoding for HDT
WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#161: FILE: monitor/bt.h:259:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#167: FILE: monitor/bt.h:265:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#177: FILE: monitor/bt.h:275:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#182: FILE: monitor/bt.h:280:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#190: FILE: monitor/bt.h:288:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#198: FILE: monitor/bt.h:296:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#205: FILE: monitor/bt.h:303:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#212: FILE: monitor/bt.h:310:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#217: FILE: monitor/bt.h:315:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#233: FILE: monitor/bt.h:3318:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#239: FILE: monitor/bt.h:3324:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#245: FILE: monitor/bt.h:3330:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#256: FILE: monitor/bt.h:3341:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#262: FILE: monitor/bt.h:3347:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#273: FILE: monitor/bt.h:3358:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#282: FILE: monitor/bt.h:3367:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#287: FILE: monitor/bt.h:3372:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#305: FILE: monitor/bt.h:3390:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#318: FILE: monitor/bt.h:3403:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#325: FILE: monitor/bt.h:3410:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#348: FILE: monitor/bt.h:3433:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#363: FILE: monitor/bt.h:3448:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#381: FILE: monitor/bt.h:3466:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#388: FILE: monitor/bt.h:3473:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#411: FILE: monitor/bt.h:3496:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#418: FILE: monitor/bt.h:3503:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#426: FILE: monitor/bt.h:3511:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#436: FILE: monitor/bt.h:3521:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#441: FILE: monitor/bt.h:3526:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#448: FILE: monitor/bt.h:3533:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#454: FILE: monitor/bt.h:3539:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#473: FILE: monitor/bt.h:4528:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#483: FILE: monitor/bt.h:4538:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#494: FILE: monitor/bt.h:4549:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#527: FILE: monitor/bt.h:4582:
+} __attribute__ ((packed));

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#548: FILE: monitor/bt.h:4603:
+} __attribute__ ((packed));

WARNING:LINE_SPACING: Missing a blank line after declarations
#1143: FILE: monitor/packet.c:10542:
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)

WARNING:SPACING: Unnecessary space before function pointer arguments
#1465: FILE: monitor/packet.c:10864:
+	void (*cmd_func) (uint16_t index, const void *data, uint8_t size);

WARNING:SPACING: Unnecessary space before function pointer arguments
#1468: FILE: monitor/packet.c:10867:
+	void (*rsp_func) (uint16_t index, const void *data, uint8_t size);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1589: FILE: monitor/packet.c:10988:
+				enhanced_accept_sync_conn_request_cmd, 63, true },

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1740: FILE: monitor/packet.c:12039:
+				sizeof(struct bt_hci_cmd_le_create_big_v2), true,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1964: FILE: monitor/packet.c:15003:
+				i < (int) (size / sizeof(*evt->bis_handle)); i++)

/home/runner/work/bluez/bluez/src/patch/14951052.patch total: 0 errors, 42 warnings, 1855 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14951052.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v3,04/10] monitor: Add LL decoding for HDT
WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#154: FILE: monitor/ll.c:570:
+				"64 bits" : "128 bits", (v2->flags >> 1) & 0x01);

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#174: FILE: monitor/ll.c:605:
+				"64 bits" : "128 bits", (v2->flags >> 1) & 0x01);

WARNING:LINE_SPACING: Missing a blank line after declarations
#212: FILE: monitor/ll.c:704:
+		uint16_t mask = print_bitfield(2, rates, fields);
+		if (mask)

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#241: FILE: monitor/ll.c:777:
+				"64 bits" : "128 bits", (v2->flags >> 4) & 0x01);

/home/runner/work/bluez/bluez/src/patch/14951051.patch total: 0 errors, 4 warnings, 284 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14951051.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v3,05/10] emulator: Add HDT support to btdev
WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#652: FILE: emulator/btdev.c:7262:
+static void le_cis_estabilished_fill(struct bt_hci_evt_le_cis_established_v3 *evt,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#766: FILE: emulator/btdev.c:7348:
+		le_cis_estabilished_fill(&evt, &conn->link->dev->le_cig[cig_idx],

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#900: FILE: emulator/btdev.c:8456:
+	} __attribute__ ((packed)) rsp;

/home/runner/work/bluez/bluez/src/patch/14951054.patch total: 0 errors, 3 warnings, 1249 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14951054.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v3,07/10] shared/gatt: Add MIC length permission checks
WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#572: FILE: unit/test-gatt.c:4735:
+	define_test_server("/robustness/mic-len/read-multiple-variable", test_server,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#593: FILE: unit/test-gatt.c:4756:
+	define_test_server("/robustness/mic-len/read-by-group-type", test_server,

/home/runner/work/bluez/bluez/src/patch/14951055.patch total: 0 errors, 2 warnings, 379 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14951055.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v3,08/10] main.conf: Add HDT configuration
WARNING:STATIC_CONST_CHAR_ARRAY: static const char * array should probably be static const char * const
#213: FILE: src/main.c:193:
+static const char *hdt_options[] = {

/home/runner/work/bluez/bluez/src/patch/14951056.patch total: 0 errors, 1 warnings, 152 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14951056.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v3,09/10] l2cap-tester, iso-tester, mgmt-tester: Add HDT tests
WARNING:MACRO_ARG_UNUSED: Argument 'name' is not used in function-like macro
#414: FILE: tools/iso-tester.c:954:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:MACRO_ARG_UNUSED: Argument 'setup' is not used in function-like macro
#414: FILE: tools/iso-tester.c:954:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:MACRO_ARG_UNUSED: Argument 'func' is not used in function-like macro
#414: FILE: tools/iso-tester.c:954:
+#define test_iso_full(name, type, data, setup, func, num, reason) \
 	do { \
 		struct test_data *user; \
 		user = new0(struct test_data, 1); \
 		if (!user) \
 			break; \
+		user->hciemu_type = type; \
 		user->test_data = data; \
 		user->client_num = num; \
 		user->accept_reason = reason; \

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#1937: FILE: tools/iso-tester.c:5119:
+							&connect_hdt_type_mismatch,

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#3110: FILE: tools/l2cap-tester.c:3858:
+					BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE_V2,

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#3474: FILE: tools/mgmt-tester.c:14370:
+	} __attribute__((packed)) *cmd = param;

/home/runner/work/bluez/bluez/src/patch/14951058.patch total: 0 errors, 6 warnings, 3329 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14951058.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v3,10/10] l2test: Add HDT options
ERROR:INITIALISED_STATIC: do not initialise statics to 0
#204: FILE: tools/l2test.c:127:
+static int mic_len = 0;

/home/runner/work/bluez/bluez/src/patch/14951057.patch total: 1 errors, 0 warnings, 303 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluez/bluez/src/patch/14951057.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/packet.c:2292:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:4216:52: warning: array of flexible structuresmonitor/bt.h:4204:40: warning: array of flexible structuresemulator/bthost.c:707:28: warning: Variable length array is used.emulator/bthost.c:708:32: warning: Variable length array is used.emulator/bthost.c:961:28: warning: Variable length array is used.emulator/bthost.c:995:28: warning: Variable length array is used.emulator/bthost.c:996:32: warning: Variable length array is used.src/main.c: note: in included file (through src/device.h):


https://github.com/bluez/bluez/pull/2762

---
Regards,
Linux Bluetooth


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

end of thread, other threads:[~2026-11-05  3:06 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04 18:36 [PATCH BlueZ v2 0/9] Add support for HDT and EKS Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 1/9] lib: Add HDT definitions Luiz Augusto von Dentz
2026-11-04 23:07   ` Add support for HDT and EKS bluez.test.bot
2026-11-04 18:36 ` [PATCH BlueZ v2 2/9] monitor: Add HCI decoding for HDT Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 3/9] monitor: Add LL " Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 4/9] emulator: Add HDT support to btdev Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 5/9] emulator: Add HDT support to bthost Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 6/9] shared/gatt: Add MIC length permission checks Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 7/9] main.conf: Add HDT configuration Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 8/9] l2cap-tester, iso-tester, mgmt-tester: Add HDT tests Luiz Augusto von Dentz
2026-11-04 18:36 ` [PATCH BlueZ v2 9/9] l2test: Add HDT options Luiz Augusto von Dentz
  -- strict thread matches above, loose matches on Subject: below --
2026-11-04 22:20 [PATCH BlueZ v3 01/10] lib: Add HDT definitions Luiz Augusto von Dentz
2026-11-05  3:06 ` Add support for HDT and EKS bluez.test.bot
2026-11-03 22:19 [PATCH BlueZ v1 1/9] lib: Add HDT definitions Luiz Augusto von Dentz
2026-11-04  2:34 ` Add support for HDT and EKS bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox