diff --git a/tools/hci_throughput/hci.py b/tools/hci_throughput/hci.py index 69b363745..6ed45625f 100644 --- a/tools/hci_throughput/hci.py +++ b/tools/hci_throughput/hci.py @@ -21,6 +21,7 @@ from dataclasses import dataclass import struct from binascii import unhexlify import random +import ctypes ############ # DEFINES @@ -57,6 +58,7 @@ OCF_READ_BD_ADDR = 0x0009 OGF_LE_CTL = 0x08 OCF_LE_SET_EVENT_MASK = 0x0001 OCF_LE_READ_BUFFER_SIZE_V1 = 0x0002 +OCF_LE_READ_LOCAL_SUPPORTED_FEATURES = 0x0003 OCF_LE_READ_BUFFER_SIZE_V2 = 0x0060 OCF_LE_SET_RANDOM_ADDRESS = 0x0005 OCF_LE_SET_ADVERTISING_PARAMETERS = 0x0006 @@ -80,6 +82,9 @@ STATIC_RANDOM_ADDRESS_TYPE = 1 WAIT_FOR_EVENT_TIMEOUT = 5 WAIT_FOR_EVENT_CONN_TIMEOUT = 25 +LE_FEATURE_2M_PHY = ctypes.c_uint64(0x0100).value +LE_FEATURE_CODED_PHY = ctypes.c_uint64(0x0800).value + ############ # GLOBAL VAR ############ @@ -99,6 +104,8 @@ phy = None ev_num_comp_pkts = None num_of_completed_packets_cnt = 0 num_of_completed_packets_time = 0 +read_local_commands = None +le_read_local_supported_features = None ############ # FUNCTIONS @@ -203,6 +210,29 @@ class LE_Read_PHY: self.tx_phy = tx_phy self.rx_phy = rx_phy +@dataclass +class Read_Local_Commands: + status: int + supported_commands: bytes + + def __init__(self): + self.set() + + def set(self, rcv_bytes = bytes(65)): + self.status = int(rcv_bytes[0]) + self.supported_commands = rcv_bytes[1:] + +@dataclass +class LE_Read_Local_Supported_Features: + status: int + le_features: bytes + + def __init__(self): + self.set() + + def set(self, rcv_bytes = bytes(9)): + self.status = int(rcv_bytes[0]) + self.le_features = ctypes.c_uint64.from_buffer_copy(rcv_bytes[1:]).value ############ # EVENTS diff --git a/tools/hci_throughput/hci_commands.py b/tools/hci_throughput/hci_commands.py index 286f45060..a6040ef0f 100644 --- a/tools/hci_throughput/hci_commands.py +++ b/tools/hci_throughput/hci_commands.py @@ -131,6 +131,14 @@ class HCI_Commands(): await self.async_ev_cmd_end.wait() self.async_ev_cmd_end.clear() + async def cmd_le_read_local_supported_features(self): + async with self.async_sem_cmd: + self.hci_send_cmd.set(hci.OGF_LE_CTL, hci.OCF_LE_READ_LOCAL_SUPPORTED_FEATURES) + logging.debug("%s %s", self.cmd_le_read_local_supported_features.__name__, self.hci_send_cmd) + await self.send(self.hci_send_cmd.ba_full_message) + await self.async_ev_cmd_end.wait() + self.async_ev_cmd_end.clear() + async def cmd_le_set_random_addr(self, addr: str): async with self.async_sem_cmd: addr_ba = hci.cmd_addr_to_ba(addr) @@ -382,6 +390,8 @@ class HCI_Commands(): elif ogf == hci.OGF_INFO_PARAM: if ocf == hci.OCF_READ_LOCAL_COMMANDS: + hci.read_local_commands = hci.Read_Local_Commands() + hci.read_local_commands.set(bytes(current_ev.return_parameters)) return status() elif ocf == hci.OCF_READ_BD_ADDR: hci.bdaddr = hci.ba_addr_to_str( @@ -397,6 +407,10 @@ class HCI_Commands(): current_ev.return_parameters)) logging.info(f"LE Buffer size: {hci.le_read_buffer_size}") return hci.le_read_buffer_size.status + elif ocf == hci.OCF_LE_READ_LOCAL_SUPPORTED_FEATURES: + hci.le_read_local_supported_features = hci.LE_Read_Local_Supported_Features() + hci.le_read_local_supported_features.set(current_ev.return_parameters) + return status() elif ocf == hci.OCF_LE_SET_RANDOM_ADDRESS: return status() elif ocf == hci.OCF_LE_SET_ADVERTISING_PARAMETERS: