diff options
Diffstat (limited to 'bumble/hci.py')
-rw-r--r-- | bumble/hci.py | 2046 |
1 files changed, 1302 insertions, 744 deletions
diff --git a/bumble/hci.py b/bumble/hci.py index 057c04a..013a2d3 100644 --- a/bumble/hci.py +++ b/bumble/hci.py @@ -17,11 +17,15 @@ # ----------------------------------------------------------------------------- from __future__ import annotations import collections +import dataclasses +import enum import functools import logging +import secrets import struct -from typing import Any, Dict, Callable, Optional, Type, Union +from typing import Any, Callable, Dict, Iterable, List, Optional, Type, Union +from bumble import crypto from .colors import color from .core import ( BT_BR_EDR_TRANSPORT, @@ -148,6 +152,7 @@ HCI_COMMAND_PACKET = 0x01 HCI_ACL_DATA_PACKET = 0x02 HCI_SYNCHRONOUS_DATA_PACKET = 0x03 HCI_EVENT_PACKET = 0x04 +HCI_ISO_DATA_PACKET = 0x05 # HCI Event Codes HCI_INQUIRY_COMPLETE_EVENT = 0x01 @@ -218,41 +223,47 @@ HCI_VENDOR_EVENT = 0xFF # HCI Subevent Codes -HCI_LE_CONNECTION_COMPLETE_EVENT = 0x01 -HCI_LE_ADVERTISING_REPORT_EVENT = 0x02 -HCI_LE_CONNECTION_UPDATE_COMPLETE_EVENT = 0x03 -HCI_LE_READ_REMOTE_FEATURES_COMPLETE_EVENT = 0x04 -HCI_LE_LONG_TERM_KEY_REQUEST_EVENT = 0x05 -HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_EVENT = 0x06 -HCI_LE_DATA_LENGTH_CHANGE_EVENT = 0x07 -HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT = 0x08 -HCI_LE_GENERATE_DHKEY_COMPLETE_EVENT = 0x09 -HCI_LE_ENHANCED_CONNECTION_COMPLETE_EVENT = 0x0A -HCI_LE_DIRECTED_ADVERTISING_REPORT_EVENT = 0x0B -HCI_LE_PHY_UPDATE_COMPLETE_EVENT = 0x0C -HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT = 0x0D -HCI_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_EVENT = 0x0E -HCI_LE_PERIODIC_ADVERTISING_REPORT_EVENT = 0x0F -HCI_LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT = 0x10 -HCI_LE_SCAN_TIMEOUT_EVENT = 0x11 -HCI_LE_ADVERTISING_SET_TERMINATED_EVENT = 0x12 -HCI_LE_SCAN_REQUEST_RECEIVED_EVENT = 0x13 -HCI_LE_CHANNEL_SELECTION_ALGORITHM_EVENT = 0x14 -HCI_LE_CONNECTIONLESS_IQ_REPORT_EVENT = 0X15 -HCI_LE_CONNECTION_IQ_REPORT_EVENT = 0X16 -HCI_LE_CTE_REQUEST_FAILED_EVENT = 0X17 -HCI_LE_PERIODIC_ADVERTISING_SYNC_TRANSFER_RECEIVED_EVENT = 0X18 -HCI_LE_CIS_ESTABLISHED_EVENT = 0X19 -HCI_LE_CIS_REQUEST_EVENT = 0X1A -HCI_LE_CREATE_BIG_COMPLETE_EVENT = 0X1B -HCI_LE_TERMINATE_BIG_COMPLETE_EVENT = 0X1C -HCI_LE_BIG_SYNC_ESTABLISHED_EVENT = 0X1D -HCI_LE_BIG_SYNC_LOST_EVENT = 0X1E -HCI_LE_REQUEST_PEER_SCA_COMPLETE_EVENT = 0X1F -HCI_LE_PATH_LOSS_THRESHOLD_EVENT = 0X20 -HCI_LE_TRANSMIT_POWER_REPORTING_EVENT = 0X21 -HCI_LE_BIGINFO_ADVERTISING_REPORT_EVENT = 0X22 -HCI_LE_SUBRATE_CHANGE_EVENT = 0X23 +HCI_LE_CONNECTION_COMPLETE_EVENT = 0x01 +HCI_LE_ADVERTISING_REPORT_EVENT = 0x02 +HCI_LE_CONNECTION_UPDATE_COMPLETE_EVENT = 0x03 +HCI_LE_READ_REMOTE_FEATURES_COMPLETE_EVENT = 0x04 +HCI_LE_LONG_TERM_KEY_REQUEST_EVENT = 0x05 +HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_EVENT = 0x06 +HCI_LE_DATA_LENGTH_CHANGE_EVENT = 0x07 +HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT = 0x08 +HCI_LE_GENERATE_DHKEY_COMPLETE_EVENT = 0x09 +HCI_LE_ENHANCED_CONNECTION_COMPLETE_EVENT = 0x0A +HCI_LE_DIRECTED_ADVERTISING_REPORT_EVENT = 0x0B +HCI_LE_PHY_UPDATE_COMPLETE_EVENT = 0x0C +HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT = 0x0D +HCI_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_EVENT = 0x0E +HCI_LE_PERIODIC_ADVERTISING_REPORT_EVENT = 0x0F +HCI_LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT = 0x10 +HCI_LE_SCAN_TIMEOUT_EVENT = 0x11 +HCI_LE_ADVERTISING_SET_TERMINATED_EVENT = 0x12 +HCI_LE_SCAN_REQUEST_RECEIVED_EVENT = 0x13 +HCI_LE_CHANNEL_SELECTION_ALGORITHM_EVENT = 0x14 +HCI_LE_CONNECTIONLESS_IQ_REPORT_EVENT = 0X15 +HCI_LE_CONNECTION_IQ_REPORT_EVENT = 0X16 +HCI_LE_CTE_REQUEST_FAILED_EVENT = 0X17 +HCI_LE_PERIODIC_ADVERTISING_SYNC_TRANSFER_RECEIVED_EVENT = 0X18 +HCI_LE_CIS_ESTABLISHED_EVENT = 0X19 +HCI_LE_CIS_REQUEST_EVENT = 0X1A +HCI_LE_CREATE_BIG_COMPLETE_EVENT = 0X1B +HCI_LE_TERMINATE_BIG_COMPLETE_EVENT = 0X1C +HCI_LE_BIG_SYNC_ESTABLISHED_EVENT = 0X1D +HCI_LE_BIG_SYNC_LOST_EVENT = 0X1E +HCI_LE_REQUEST_PEER_SCA_COMPLETE_EVENT = 0X1F +HCI_LE_PATH_LOSS_THRESHOLD_EVENT = 0X20 +HCI_LE_TRANSMIT_POWER_REPORTING_EVENT = 0X21 +HCI_LE_BIGINFO_ADVERTISING_REPORT_EVENT = 0X22 +HCI_LE_SUBRATE_CHANGE_EVENT = 0X23 +HCI_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_V2_EVENT = 0X24 +HCI_LE_PERIODIC_ADVERTISING_REPORT_V2_EVENT = 0X25 +HCI_LE_PERIODIC_ADVERTISING_SYNC_TRANSFER_RECEIVED_V2_EVENT = 0X26 +HCI_LE_PERIODIC_ADVERTISING_SUBEVENT_DATA_REQUEST_EVENT = 0X27 +HCI_LE_PERIODIC_ADVERTISING_RESPONSE_REPORT_EVENT = 0X28 +HCI_LE_ENHANCED_CONNECTION_COMPLETE_V2_EVENT = 0X29 # HCI Command @@ -558,6 +569,12 @@ HCI_LE_TRANSMITTER_TEST_V4_COMMAND = hci_c HCI_LE_SET_DATA_RELATED_ADDRESS_CHANGES_COMMAND = hci_command_op_code(0x08, 0x007C) HCI_LE_SET_DEFAULT_SUBRATE_COMMAND = hci_command_op_code(0x08, 0x007D) HCI_LE_SUBRATE_REQUEST_COMMAND = hci_command_op_code(0x08, 0x007E) +HCI_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2_COMMAND = hci_command_op_code(0x08, 0x007F) +HCI_LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA_COMMAND = hci_command_op_code(0x08, 0x0082) +HCI_LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA_COMMAND = hci_command_op_code(0x08, 0x0083) +HCI_LE_SET_PERIODIC_SYNC_SUBEVENT_COMMAND = hci_command_op_code(0x08, 0x0084) +HCI_LE_EXTENDED_CREATE_CONNECTION_V2_COMMAND = hci_command_op_code(0x08, 0x0085) +HCI_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2_COMMAND = hci_command_op_code(0x08, 0x0086) # HCI Error Codes @@ -639,47 +656,6 @@ HCI_ERROR_NAMES[HCI_SUCCESS] = 'HCI_SUCCESS' # Command Status codes HCI_COMMAND_STATUS_PENDING = 0 -# LE Event Masks -HCI_LE_CONNECTION_COMPLETE_EVENT_MASK = (1 << 0) -HCI_LE_ADVERTISING_REPORT_EVENT_MASK = (1 << 1) -HCI_LE_CONNECTION_UPDATE_COMPLETE_EVENT_MASK = (1 << 2) -HCI_LE_READ_REMOTE_FEATURES_COMPLETE_EVENT_MASK = (1 << 3) -HCI_LE_LONG_TERM_KEY_REQUEST_EVENT_MASK = (1 << 4) -HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_EVENT_MASK = (1 << 5) -HCI_LE_DATA_LENGTH_CHANGE_EVENT_MASK = (1 << 6) -HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT_MASK = (1 << 7) -HCI_LE_GENERATE_DHKEY_COMPLETE_EVENT_MASK = (1 << 8) -HCI_LE_ENHANCED_CONNECTION_COMPLETE_EVENT_MASK = (1 << 9) -HCI_LE_DIRECTED_ADVERTISING_REPORT_EVENT_MASK = (1 << 10) -HCI_LE_PHY_UPDATE_COMPLETE_EVENT_MASK = (1 << 11) -HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT_MASK = (1 << 12) -HCI_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_EVENT_MASK = (1 << 13) -HCI_LE_PERIODIC_ADVERTISING_REPORT_EVENT_MASK = (1 << 14) -HCI_LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT_MASK = (1 << 15) -HCI_LE_EXTENDED_SCAN_TIMEOUT_EVENT_MASK = (1 << 16) -HCI_LE_EXTENDED_ADVERTISING_SET_TERMINATED_EVENT_MASK = (1 << 17) -HCI_LE_SCAN_REQUEST_RECEIVED_EVENT_MASK = (1 << 18) -HCI_LE_CHANNEL_SELECTION_ALGORITHM_EVENT_MASK = (1 << 19) -HCI_LE_CONNECTIONLESS_IQ_REPORT_EVENT_MASK = (1 << 20) -HCI_LE_CONNECTION_IQ_REPORT_EVENT_MASK = (1 << 21) -HCI_LE_CTE_REQUEST_FAILED_EVENT_MASK = (1 << 22) -HCI_LE_PERIODIC_ADVERTISING_SYNC_TRANSFER_RECEIVED_EVENT_MASK = (1 << 23) -HCI_LE_CIS_ESTABLISHED_EVENT_MASK = (1 << 24) -HCI_LE_CIS_REQUEST_EVENT_MASK = (1 << 25) -HCI_LE_CREATE_BIG_COMPLETE_EVENT_MASK = (1 << 26) -HCI_LE_TERMINATE_BIG_COMPLETE_EVENT_MASK = (1 << 27) -HCI_LE_BIG_SYNC_ESTABLISHED_EVENT_MASK = (1 << 28) -HCI_LE_BIG_SYNC_LOST_EVENT_MASK = (1 << 29) -HCI_LE_REQUEST_PEER_SCA_COMPLETE_EVENT_MASK = (1 << 30) -HCI_LE_PATH_LOSS_THRESHOLD_EVENT_MASK = (1 << 31) -HCI_LE_TRANSMIT_POWER_REPORTING_EVENT_MASK = (1 << 32) -HCI_LE_BIGINFO_ADVERTISING_REPORT_EVENT_MASK = (1 << 33) -HCI_LE_SUBRATE_CHANGE_EVENT_MASK = (1 << 34) - -HCI_LE_EVENT_MASK_NAMES = { - mask: mask_name for (mask_name, mask) in globals().items() - if mask_name.startswith('HCI_LE_') and mask_name.endswith('_EVENT_MASK') -} # ACL HCI_ACL_PB_FIRST_NON_FLUSHABLE = 0 @@ -719,6 +695,19 @@ HCI_LE_PHY_TYPE_TO_BIT = { HCI_LE_CODED_PHY: HCI_LE_CODED_PHY_BIT } + +class Phy(enum.IntEnum): + LE_1M = HCI_LE_1M_PHY + LE_2M = HCI_LE_2M_PHY + LE_CODED = HCI_LE_CODED_PHY + + +class PhyBit(enum.IntFlag): + LE_1M = 1 << HCI_LE_1M_PHY_BIT + LE_2M = 1 << HCI_LE_2M_PHY_BIT + LE_CODED = 1 << HCI_LE_CODED_PHY_BIT + + # Connection Parameters HCI_CONNECTION_INTERVAL_MS_PER_UNIT = 1.25 HCI_CONNECTION_LATENCY_MS_PER_UNIT = 1.25 @@ -801,574 +790,586 @@ HCI_RANDOM_DEVICE_ADDRESS_TYPE = 0x01 HCI_PUBLIC_IDENTITY_ADDRESS_TYPE = 0x02 HCI_RANDOM_IDENTITY_ADDRESS_TYPE = 0x03 -# Supported Commands Flags +# Supported Commands Masks # See Bluetooth spec @ 6.27 SUPPORTED COMMANDS -HCI_SUPPORTED_COMMANDS_FLAGS = ( - # Octet 0 - ( - HCI_INQUIRY_COMMAND, - HCI_INQUIRY_CANCEL_COMMAND, - HCI_PERIODIC_INQUIRY_MODE_COMMAND, - HCI_EXIT_PERIODIC_INQUIRY_MODE_COMMAND, - HCI_CREATE_CONNECTION_COMMAND, - HCI_DISCONNECT_COMMAND, - None, - HCI_CREATE_CONNECTION_CANCEL_COMMAND - ), - # Octet 1 - ( - HCI_ACCEPT_CONNECTION_REQUEST_COMMAND, - HCI_REJECT_CONNECTION_REQUEST_COMMAND, - HCI_LINK_KEY_REQUEST_REPLY_COMMAND, - HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY_COMMAND, - HCI_PIN_CODE_REQUEST_REPLY_COMMAND, - HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY_COMMAND, - HCI_CHANGE_CONNECTION_PACKET_TYPE_COMMAND, - HCI_AUTHENTICATION_REQUESTED_COMMAND - ), - # Octet 2 - ( - HCI_SET_CONNECTION_ENCRYPTION_COMMAND, - HCI_CHANGE_CONNECTION_LINK_KEY_COMMAND, - HCI_LINK_KEY_SELECTION_COMMAND, - HCI_REMOTE_NAME_REQUEST_COMMAND, - HCI_REMOTE_NAME_REQUEST_CANCEL_COMMAND, - HCI_READ_REMOTE_SUPPORTED_FEATURES_COMMAND, - HCI_READ_REMOTE_EXTENDED_FEATURES_COMMAND, - HCI_READ_REMOTE_VERSION_INFORMATION_COMMAND - ), - # Octet 3 - ( - HCI_READ_CLOCK_OFFSET_COMMAND, - HCI_READ_LMP_HANDLE_COMMAND, - None, - None, - None, - None, - None, - None - ), - # Octet 4 - ( - None, - HCI_HOLD_MODE_COMMAND, - HCI_SNIFF_MODE_COMMAND, - HCI_EXIT_SNIFF_MODE_COMMAND, - None, - None, - HCI_QOS_SETUP_COMMAND, - HCI_ROLE_DISCOVERY_COMMAND - ), - # Octet 5 - ( - HCI_SWITCH_ROLE_COMMAND, - HCI_READ_LINK_POLICY_SETTINGS_COMMAND, - HCI_WRITE_LINK_POLICY_SETTINGS_COMMAND, - HCI_READ_DEFAULT_LINK_POLICY_SETTINGS_COMMAND, - HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS_COMMAND, - HCI_FLOW_SPECIFICATION_COMMAND, - HCI_SET_EVENT_MASK_COMMAND, - HCI_RESET_COMMAND - ), - # Octet 6 - ( - HCI_SET_EVENT_FILTER_COMMAND, - HCI_FLUSH_COMMAND, - HCI_READ_PIN_TYPE_COMMAND, - HCI_WRITE_PIN_TYPE_COMMAND, - None, - HCI_READ_STORED_LINK_KEY_COMMAND, - HCI_WRITE_STORED_LINK_KEY_COMMAND, - HCI_DELETE_STORED_LINK_KEY_COMMAND - ), - # Octet 7 - ( - HCI_WRITE_LOCAL_NAME_COMMAND, - HCI_READ_LOCAL_NAME_COMMAND, - HCI_READ_CONNECTION_ACCEPT_TIMEOUT_COMMAND, - HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_COMMAND, - HCI_READ_PAGE_TIMEOUT_COMMAND, - HCI_WRITE_PAGE_TIMEOUT_COMMAND, - HCI_READ_SCAN_ENABLE_COMMAND, - HCI_WRITE_SCAN_ENABLE_COMMAND - ), - # Octet 8 - ( - HCI_READ_PAGE_SCAN_ACTIVITY_COMMAND, - HCI_WRITE_PAGE_SCAN_ACTIVITY_COMMAND, - HCI_READ_INQUIRY_SCAN_ACTIVITY_COMMAND, - HCI_WRITE_INQUIRY_SCAN_ACTIVITY_COMMAND, - HCI_READ_AUTHENTICATION_ENABLE_COMMAND, - HCI_WRITE_AUTHENTICATION_ENABLE_COMMAND, - None, - None - ), - # Octet 9 - ( - HCI_READ_CLASS_OF_DEVICE_COMMAND, - HCI_WRITE_CLASS_OF_DEVICE_COMMAND, - HCI_READ_VOICE_SETTING_COMMAND, - HCI_WRITE_VOICE_SETTING_COMMAND, - HCI_READ_AUTOMATIC_FLUSH_TIMEOUT_COMMAND, - HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT_COMMAND, - HCI_READ_NUM_BROADCAST_RETRANSMISSIONS_COMMAND, - HCI_WRITE_NUM_BROADCAST_RETRANSMISSIONS_COMMAND - ), - # Octet 10 - ( - HCI_READ_HOLD_MODE_ACTIVITY_COMMAND, - HCI_WRITE_HOLD_MODE_ACTIVITY_COMMAND, - HCI_READ_TRANSMIT_POWER_LEVEL_COMMAND, - HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND, - HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND, - HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL_COMMAND, - HCI_HOST_BUFFER_SIZE_COMMAND, - HCI_HOST_NUMBER_OF_COMPLETED_PACKETS_COMMAND - ), - # Octet 11 - ( - HCI_READ_LINK_SUPERVISION_TIMEOUT_COMMAND, - HCI_WRITE_LINK_SUPERVISION_TIMEOUT_COMMAND, - HCI_READ_NUMBER_OF_SUPPORTED_IAC_COMMAND, - HCI_READ_CURRENT_IAC_LAP_COMMAND, - HCI_WRITE_CURRENT_IAC_LAP_COMMAND, - None, - None, - None - ), - # Octet 12 - ( - None, - HCI_SET_AFH_HOST_CHANNEL_CLASSIFICATION_COMMAND, - None, - None, - HCI_READ_INQUIRY_SCAN_TYPE_COMMAND, - HCI_WRITE_INQUIRY_SCAN_TYPE_COMMAND, - HCI_READ_INQUIRY_MODE_COMMAND, - HCI_WRITE_INQUIRY_MODE_COMMAND - ), - # Octet 13 - ( - HCI_READ_PAGE_SCAN_TYPE_COMMAND, - HCI_WRITE_PAGE_SCAN_TYPE_COMMAND, - HCI_READ_AFH_CHANNEL_ASSESSMENT_MODE_COMMAND, - HCI_WRITE_AFH_CHANNEL_ASSESSMENT_MODE_COMMAND, - None, - None, - None, - None, - ), - # Octet 14 - ( - None, - None, - None, - HCI_READ_LOCAL_VERSION_INFORMATION_COMMAND, - None, - HCI_READ_LOCAL_SUPPORTED_FEATURES_COMMAND, - HCI_READ_LOCAL_EXTENDED_FEATURES_COMMAND, - HCI_READ_BUFFER_SIZE_COMMAND - ), - # Octet 15 - ( - None, - HCI_READ_BD_ADDR_COMMAND, - HCI_READ_FAILED_CONTACT_COUNTER_COMMAND, - HCI_RESET_FAILED_CONTACT_COUNTER_COMMAND, - HCI_READ_LINK_QUALITY_COMMAND, - HCI_READ_RSSI_COMMAND, - HCI_READ_AFH_CHANNEL_MAP_COMMAND, - HCI_READ_CLOCK_COMMAND - ), - # Octet 16 - ( - HCI_READ_LOOPBACK_MODE_COMMAND, - HCI_WRITE_LOOPBACK_MODE_COMMAND, - HCI_ENABLE_DEVICE_UNDER_TEST_MODE_COMMAND, - HCI_SETUP_SYNCHRONOUS_CONNECTION_COMMAND, - HCI_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST_COMMAND, - HCI_REJECT_SYNCHRONOUS_CONNECTION_REQUEST_COMMAND, - None, - None, - ), - # Octet 17 - ( - HCI_READ_EXTENDED_INQUIRY_RESPONSE_COMMAND, - HCI_WRITE_EXTENDED_INQUIRY_RESPONSE_COMMAND, - HCI_REFRESH_ENCRYPTION_KEY_COMMAND, - None, - HCI_SNIFF_SUBRATING_COMMAND, - HCI_READ_SIMPLE_PAIRING_MODE_COMMAND, - HCI_WRITE_SIMPLE_PAIRING_MODE_COMMAND, - HCI_READ_LOCAL_OOB_DATA_COMMAND - ), - # Octet 18 - ( - HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL_COMMAND, - HCI_WRITE_INQUIRY_TRANSMIT_POWER_LEVEL_COMMAND, - HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_COMMAND, - HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_COMMAND, - None, - None, - None, - HCI_IO_CAPABILITY_REQUEST_REPLY_COMMAND - ), - # Octet 19 - ( - HCI_USER_CONFIRMATION_REQUEST_REPLY_COMMAND, - HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY_COMMAND, - HCI_USER_PASSKEY_REQUEST_REPLY_COMMAND, - HCI_USER_PASSKEY_REQUEST_NEGATIVE_REPLY_COMMAND, - HCI_REMOTE_OOB_DATA_REQUEST_REPLY_COMMAND, - HCI_WRITE_SIMPLE_PAIRING_DEBUG_MODE_COMMAND, - HCI_ENHANCED_FLUSH_COMMAND, - HCI_REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY_COMMAND - ), - # Octet 20 - ( - None, - None, - HCI_SEND_KEYPRESS_NOTIFICATION_COMMAND, - HCI_IO_CAPABILITY_REQUEST_NEGATIVE_REPLY_COMMAND, - HCI_READ_ENCRYPTION_KEY_SIZE_COMMAND, - None, - None, - None, - ), - # Octet 21 - ( - None, - None, - None, - None, - None, - None, - None, - None, - ), - # Octet 22 - ( - None, - None, - HCI_SET_EVENT_MASK_PAGE_2_COMMAND, - None, - None, - None, - None, - None, - ), - # Octet 23 - ( - HCI_READ_FLOW_CONTROL_MODE_COMMAND, - HCI_WRITE_FLOW_CONTROL_MODE_COMMAND, - HCI_READ_DATA_BLOCK_SIZE_COMMAND, - None, - None, - None, - None, - None, - ), - # Octet 24 - ( - HCI_READ_ENHANCED_TRANSMIT_POWER_LEVEL_COMMAND, - None, - None, - None, - None, - HCI_READ_LE_HOST_SUPPORT_COMMAND, - HCI_WRITE_LE_HOST_SUPPORT_COMMAND, - None, - ), - # Octet 25 - ( - HCI_LE_SET_EVENT_MASK_COMMAND, - HCI_LE_READ_BUFFER_SIZE_COMMAND, - HCI_LE_READ_LOCAL_SUPPORTED_FEATURES_COMMAND, - None, - HCI_LE_SET_RANDOM_ADDRESS_COMMAND, - HCI_LE_SET_ADVERTISING_PARAMETERS_COMMAND, - HCI_LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER_COMMAND, - HCI_LE_SET_ADVERTISING_DATA_COMMAND, - ), - # Octet 26 - ( - HCI_LE_SET_SCAN_RESPONSE_DATA_COMMAND, - HCI_LE_SET_ADVERTISING_ENABLE_COMMAND, - HCI_LE_SET_SCAN_PARAMETERS_COMMAND, - HCI_LE_SET_SCAN_ENABLE_COMMAND, - HCI_LE_CREATE_CONNECTION_COMMAND, - HCI_LE_CREATE_CONNECTION_CANCEL_COMMAND, - HCI_LE_READ_FILTER_ACCEPT_LIST_SIZE_COMMAND, - HCI_LE_CLEAR_FILTER_ACCEPT_LIST_COMMAND - ), - # Octet 27 - ( - HCI_LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST_COMMAND, - HCI_LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST_COMMAND, - HCI_LE_CONNECTION_UPDATE_COMMAND, - HCI_LE_SET_HOST_CHANNEL_CLASSIFICATION_COMMAND, - HCI_LE_READ_CHANNEL_MAP_COMMAND, - HCI_LE_READ_REMOTE_FEATURES_COMMAND, - HCI_LE_ENCRYPT_COMMAND, - HCI_LE_RAND_COMMAND - ), - # Octet 28 - ( - HCI_LE_ENABLE_ENCRYPTION_COMMAND, - HCI_LE_LONG_TERM_KEY_REQUEST_REPLY_COMMAND, - HCI_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY_COMMAND, - HCI_LE_READ_SUPPORTED_STATES_COMMAND, - HCI_LE_RECEIVER_TEST_COMMAND, - HCI_LE_TRANSMITTER_TEST_COMMAND, - HCI_LE_TEST_END_COMMAND, - None, - ), - # Octet 29 - ( - None, - None, - None, - HCI_ENHANCED_SETUP_SYNCHRONOUS_CONNECTION_COMMAND, - HCI_ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST_COMMAND, - HCI_READ_LOCAL_SUPPORTED_CODECS_COMMAND, - HCI_SET_MWS_CHANNEL_PARAMETERS_COMMAND, - HCI_SET_EXTERNAL_FRAME_CONFIGURATION_COMMAND - ), - # Octet 30 - ( - HCI_SET_MWS_SIGNALING_COMMAND, - HCI_SET_MWS_TRANSPORT_LAYER_COMMAND, - HCI_SET_MWS_SCAN_FREQUENCY_TABLE_COMMAND, - HCI_GET_MWS_TRANSPORT_LAYER_CONFIGURATION_COMMAND, - HCI_SET_MWS_PATTERN_CONFIGURATION_COMMAND, - HCI_SET_TRIGGERED_CLOCK_CAPTURE_COMMAND, - HCI_TRUNCATED_PAGE_COMMAND, - HCI_TRUNCATED_PAGE_CANCEL_COMMAND - ), - # Octet 31 - ( - HCI_SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_COMMAND, - HCI_SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE_COMMAND, - HCI_START_SYNCHRONIZATION_TRAIN_COMMAND, - HCI_RECEIVE_SYNCHRONIZATION_TRAIN_COMMAND, - HCI_SET_RESERVED_LT_ADDR_COMMAND, - HCI_DELETE_RESERVED_LT_ADDR_COMMAND, - HCI_SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA_COMMAND, - HCI_READ_SYNCHRONIZATION_TRAIN_PARAMETERS_COMMAND - ), - # Octet 32 - ( - HCI_WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS_COMMAND, - HCI_REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY_COMMAND, - HCI_READ_SECURE_CONNECTIONS_HOST_SUPPORT_COMMAND, - HCI_WRITE_SECURE_CONNECTIONS_HOST_SUPPORT_COMMAND, - HCI_READ_AUTHENTICATED_PAYLOAD_TIMEOUT_COMMAND, - HCI_WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT_COMMAND, - HCI_READ_LOCAL_OOB_EXTENDED_DATA_COMMAND, - HCI_WRITE_SECURE_CONNECTIONS_TEST_MODE_COMMAND - ), - # Octet 33 - ( - HCI_READ_EXTENDED_PAGE_TIMEOUT_COMMAND, - HCI_WRITE_EXTENDED_PAGE_TIMEOUT_COMMAND, - HCI_READ_EXTENDED_INQUIRY_LENGTH_COMMAND, - HCI_WRITE_EXTENDED_INQUIRY_LENGTH_COMMAND, - HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_COMMAND, - HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_COMMAND, - HCI_LE_SET_DATA_LENGTH_COMMAND, - HCI_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND - ), - # Octet 34 - ( - HCI_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND, - HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND, - HCI_LE_GENERATE_DHKEY_COMMAND, - HCI_LE_ADD_DEVICE_TO_RESOLVING_LIST_COMMAND, - HCI_LE_REMOVE_DEVICE_FROM_RESOLVING_LIST_COMMAND, - HCI_LE_CLEAR_RESOLVING_LIST_COMMAND, - HCI_LE_READ_RESOLVING_LIST_SIZE_COMMAND, - HCI_LE_READ_PEER_RESOLVABLE_ADDRESS_COMMAND - ), - # Octet 35 - ( - HCI_LE_READ_LOCAL_RESOLVABLE_ADDRESS_COMMAND, - HCI_LE_SET_ADDRESS_RESOLUTION_ENABLE_COMMAND, - HCI_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_COMMAND, - HCI_LE_READ_MAXIMUM_DATA_LENGTH_COMMAND, - HCI_LE_READ_PHY_COMMAND, - HCI_LE_SET_DEFAULT_PHY_COMMAND, - HCI_LE_SET_PHY_COMMAND, - HCI_LE_RECEIVER_TEST_V2_COMMAND - ), - # Octet 36 - ( - HCI_LE_TRANSMITTER_TEST_V2_COMMAND, - HCI_LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_COMMAND, - HCI_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_COMMAND, - HCI_LE_SET_EXTENDED_ADVERTISING_DATA_COMMAND, - HCI_LE_SET_EXTENDED_SCAN_RESPONSE_DATA_COMMAND, - HCI_LE_SET_EXTENDED_ADVERTISING_ENABLE_COMMAND, - HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_COMMAND, - HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS_COMMAND, - ), - # Octet 37 - ( - HCI_LE_REMOVE_ADVERTISING_SET_COMMAND, - HCI_LE_CLEAR_ADVERTISING_SETS_COMMAND, - HCI_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_COMMAND, - HCI_LE_SET_PERIODIC_ADVERTISING_DATA_COMMAND, - HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE_COMMAND, - HCI_LE_SET_EXTENDED_SCAN_PARAMETERS_COMMAND, - HCI_LE_SET_EXTENDED_SCAN_ENABLE_COMMAND, - HCI_LE_EXTENDED_CREATE_CONNECTION_COMMAND - ), - # Octet 38 - ( - HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_COMMAND, - HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_COMMAND, - HCI_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_COMMAND, - HCI_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_COMMAND, - HCI_LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_COMMAND, - HCI_LE_CLEAR_PERIODIC_ADVERTISER_LIST_COMMAND, - HCI_LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_COMMAND, - HCI_LE_READ_TRANSMIT_POWER_COMMAND - ), - # Octet 39 - ( - HCI_LE_READ_RF_PATH_COMPENSATION_COMMAND, - HCI_LE_WRITE_RF_PATH_COMPENSATION_COMMAND, - HCI_LE_SET_PRIVACY_MODE_COMMAND, - HCI_LE_RECEIVER_TEST_V3_COMMAND, - HCI_LE_TRANSMITTER_TEST_V3_COMMAND, - HCI_LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS_COMMAND, - HCI_LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE_COMMAND, - HCI_LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE_COMMAND, - ), - # Octet 40 - ( - HCI_LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS_COMMAND, - HCI_LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS_COMMAND, - HCI_LE_CONNECTION_CTE_REQUEST_ENABLE_COMMAND, - HCI_LE_CONNECTION_CTE_RESPONSE_ENABLE_COMMAND, - HCI_LE_READ_ANTENNA_INFORMATION_COMMAND, - HCI_LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE_COMMAND, - HCI_LE_PERIODIC_ADVERTISING_SYNC_TRANSFER_COMMAND, - HCI_LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER_COMMAND - ), - # Octet 41 - ( - HCI_LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS_COMMAND, - HCI_LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS_COMMAND, - HCI_LE_GENERATE_DHKEY_V2_COMMAND, - HCI_READ_LOCAL_SIMPLE_PAIRING_OPTIONS_COMMAND, - HCI_LE_MODIFY_SLEEP_CLOCK_ACCURACY_COMMAND, - HCI_LE_READ_BUFFER_SIZE_V2_COMMAND, - HCI_LE_READ_ISO_TX_SYNC_COMMAND, - HCI_LE_SET_CIG_PARAMETERS_COMMAND - ), - # Octet 42 - ( - HCI_LE_SET_CIG_PARAMETERS_TEST_COMMAND, - HCI_LE_CREATE_CIS_COMMAND, - HCI_LE_REMOVE_CIG_COMMAND, - HCI_LE_ACCEPT_CIS_REQUEST_COMMAND, - HCI_LE_REJECT_CIS_REQUEST_COMMAND, - HCI_LE_CREATE_BIG_COMMAND, - HCI_LE_CREATE_BIG_TEST_COMMAND, - HCI_LE_TERMINATE_BIG_COMMAND, - ), - # Octet 43 - ( - HCI_LE_BIG_CREATE_SYNC_COMMAND, - HCI_LE_BIG_TERMINATE_SYNC_COMMAND, - HCI_LE_REQUEST_PEER_SCA_COMMAND, - HCI_LE_SETUP_ISO_DATA_PATH_COMMAND, - HCI_LE_REMOVE_ISO_DATA_PATH_COMMAND, - HCI_LE_ISO_TRANSMIT_TEST_COMMAND, - HCI_LE_ISO_RECEIVE_TEST_COMMAND, - HCI_LE_ISO_READ_TEST_COUNTERS_COMMAND - ), - # Octet 44 - ( - HCI_LE_ISO_TEST_END_COMMAND, - HCI_LE_SET_HOST_FEATURE_COMMAND, - HCI_LE_READ_ISO_LINK_QUALITY_COMMAND, - HCI_LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL_COMMAND, - HCI_LE_READ_REMOTE_TRANSMIT_POWER_LEVEL_COMMAND, - HCI_LE_SET_PATH_LOSS_REPORTING_PARAMETERS_COMMAND, - HCI_LE_SET_PATH_LOSS_REPORTING_ENABLE_COMMAND, - HCI_LE_SET_TRANSMIT_POWER_REPORTING_ENABLE_COMMAND - ), - # Octet 45 - ( - HCI_LE_TRANSMITTER_TEST_V4_COMMAND, - HCI_SET_ECOSYSTEM_BASE_INTERVAL_COMMAND, - HCI_READ_LOCAL_SUPPORTED_CODECS_V2_COMMAND, - HCI_READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES_COMMAND, - HCI_READ_LOCAL_SUPPORTED_CONTROLLER_DELAY_COMMAND, - HCI_CONFIGURE_DATA_PATH_COMMAND, - HCI_LE_SET_DATA_RELATED_ADDRESS_CHANGES_COMMAND, - HCI_SET_MIN_ENCRYPTION_KEY_SIZE_COMMAND - ), - # Octet 46 - ( - HCI_LE_SET_DEFAULT_SUBRATE_COMMAND, - HCI_LE_SUBRATE_REQUEST_COMMAND, - None, - None, - None, - None, - None, - None - ) -) +HCI_SUPPORTED_COMMANDS_MASKS = { + HCI_INQUIRY_COMMAND : 1 << (0*8+0), + HCI_INQUIRY_CANCEL_COMMAND : 1 << (0*8+1), + HCI_PERIODIC_INQUIRY_MODE_COMMAND : 1 << (0*8+2), + HCI_EXIT_PERIODIC_INQUIRY_MODE_COMMAND : 1 << (0*8+3), + HCI_CREATE_CONNECTION_COMMAND : 1 << (0*8+4), + HCI_DISCONNECT_COMMAND : 1 << (0*8+5), + HCI_CREATE_CONNECTION_CANCEL_COMMAND : 1 << (0*8+7), + HCI_ACCEPT_CONNECTION_REQUEST_COMMAND : 1 << (1*8+0), + HCI_REJECT_CONNECTION_REQUEST_COMMAND : 1 << (1*8+1), + HCI_LINK_KEY_REQUEST_REPLY_COMMAND : 1 << (1*8+2), + HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (1*8+3), + HCI_PIN_CODE_REQUEST_REPLY_COMMAND : 1 << (1*8+4), + HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (1*8+5), + HCI_CHANGE_CONNECTION_PACKET_TYPE_COMMAND : 1 << (1*8+6), + HCI_AUTHENTICATION_REQUESTED_COMMAND : 1 << (1*8+7), + HCI_SET_CONNECTION_ENCRYPTION_COMMAND : 1 << (2*8+0), + HCI_CHANGE_CONNECTION_LINK_KEY_COMMAND : 1 << (2*8+1), + HCI_LINK_KEY_SELECTION_COMMAND : 1 << (2*8+2), + HCI_REMOTE_NAME_REQUEST_COMMAND : 1 << (2*8+3), + HCI_REMOTE_NAME_REQUEST_CANCEL_COMMAND : 1 << (2*8+4), + HCI_READ_REMOTE_SUPPORTED_FEATURES_COMMAND : 1 << (2*8+5), + HCI_READ_REMOTE_EXTENDED_FEATURES_COMMAND : 1 << (2*8+6), + HCI_READ_REMOTE_VERSION_INFORMATION_COMMAND : 1 << (2*8+7), + HCI_READ_CLOCK_OFFSET_COMMAND : 1 << (3*8+0), + HCI_READ_LMP_HANDLE_COMMAND : 1 << (3*8+1), + HCI_HOLD_MODE_COMMAND : 1 << (4*8+1), + HCI_SNIFF_MODE_COMMAND : 1 << (4*8+2), + HCI_EXIT_SNIFF_MODE_COMMAND : 1 << (4*8+3), + HCI_QOS_SETUP_COMMAND : 1 << (4*8+6), + HCI_ROLE_DISCOVERY_COMMAND : 1 << (4*8+7), + HCI_SWITCH_ROLE_COMMAND : 1 << (5*8+0), + HCI_READ_LINK_POLICY_SETTINGS_COMMAND : 1 << (5*8+1), + HCI_WRITE_LINK_POLICY_SETTINGS_COMMAND : 1 << (5*8+2), + HCI_READ_DEFAULT_LINK_POLICY_SETTINGS_COMMAND : 1 << (5*8+3), + HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS_COMMAND : 1 << (5*8+4), + HCI_FLOW_SPECIFICATION_COMMAND : 1 << (5*8+5), + HCI_SET_EVENT_MASK_COMMAND : 1 << (5*8+6), + HCI_RESET_COMMAND : 1 << (5*8+7), + HCI_SET_EVENT_FILTER_COMMAND : 1 << (6*8+0), + HCI_FLUSH_COMMAND : 1 << (6*8+1), + HCI_READ_PIN_TYPE_COMMAND : 1 << (6*8+2), + HCI_WRITE_PIN_TYPE_COMMAND : 1 << (6*8+3), + HCI_READ_STORED_LINK_KEY_COMMAND : 1 << (6*8+5), + HCI_WRITE_STORED_LINK_KEY_COMMAND : 1 << (6*8+6), + HCI_DELETE_STORED_LINK_KEY_COMMAND : 1 << (6*8+7), + HCI_WRITE_LOCAL_NAME_COMMAND : 1 << (7*8+0), + HCI_READ_LOCAL_NAME_COMMAND : 1 << (7*8+1), + HCI_READ_CONNECTION_ACCEPT_TIMEOUT_COMMAND : 1 << (7*8+2), + HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_COMMAND : 1 << (7*8+3), + HCI_READ_PAGE_TIMEOUT_COMMAND : 1 << (7*8+4), + HCI_WRITE_PAGE_TIMEOUT_COMMAND : 1 << (7*8+5), + HCI_READ_SCAN_ENABLE_COMMAND : 1 << (7*8+6), + HCI_WRITE_SCAN_ENABLE_COMMAND : 1 << (7*8+7), + HCI_READ_PAGE_SCAN_ACTIVITY_COMMAND : 1 << (8*8+0), + HCI_WRITE_PAGE_SCAN_ACTIVITY_COMMAND : 1 << (8*8+1), + HCI_READ_INQUIRY_SCAN_ACTIVITY_COMMAND : 1 << (8*8+2), + HCI_WRITE_INQUIRY_SCAN_ACTIVITY_COMMAND : 1 << (8*8+3), + HCI_READ_AUTHENTICATION_ENABLE_COMMAND : 1 << (8*8+4), + HCI_WRITE_AUTHENTICATION_ENABLE_COMMAND : 1 << (8*8+5), + HCI_READ_CLASS_OF_DEVICE_COMMAND : 1 << (9*8+0), + HCI_WRITE_CLASS_OF_DEVICE_COMMAND : 1 << (9*8+1), + HCI_READ_VOICE_SETTING_COMMAND : 1 << (9*8+2), + HCI_WRITE_VOICE_SETTING_COMMAND : 1 << (9*8+3), + HCI_READ_AUTOMATIC_FLUSH_TIMEOUT_COMMAND : 1 << (9*8+4), + HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT_COMMAND : 1 << (9*8+5), + HCI_READ_NUM_BROADCAST_RETRANSMISSIONS_COMMAND : 1 << (9*8+6), + HCI_WRITE_NUM_BROADCAST_RETRANSMISSIONS_COMMAND : 1 << (9*8+7), + HCI_READ_HOLD_MODE_ACTIVITY_COMMAND : 1 << (10*8+0), + HCI_WRITE_HOLD_MODE_ACTIVITY_COMMAND : 1 << (10*8+1), + HCI_READ_TRANSMIT_POWER_LEVEL_COMMAND : 1 << (10*8+2), + HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND : 1 << (10*8+3), + HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND : 1 << (10*8+4), + HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL_COMMAND : 1 << (10*8+5), + HCI_HOST_BUFFER_SIZE_COMMAND : 1 << (10*8+6), + HCI_HOST_NUMBER_OF_COMPLETED_PACKETS_COMMAND : 1 << (10*8+7), + HCI_READ_LINK_SUPERVISION_TIMEOUT_COMMAND : 1 << (11*8+0), + HCI_WRITE_LINK_SUPERVISION_TIMEOUT_COMMAND : 1 << (11*8+1), + HCI_READ_NUMBER_OF_SUPPORTED_IAC_COMMAND : 1 << (11*8+2), + HCI_READ_CURRENT_IAC_LAP_COMMAND : 1 << (11*8+3), + HCI_WRITE_CURRENT_IAC_LAP_COMMAND : 1 << (11*8+4), + HCI_SET_AFH_HOST_CHANNEL_CLASSIFICATION_COMMAND : 1 << (12*8+1), + HCI_READ_INQUIRY_SCAN_TYPE_COMMAND : 1 << (12*8+4), + HCI_WRITE_INQUIRY_SCAN_TYPE_COMMAND : 1 << (12*8+5), + HCI_READ_INQUIRY_MODE_COMMAND : 1 << (12*8+6), + HCI_WRITE_INQUIRY_MODE_COMMAND : 1 << (12*8+7), + HCI_READ_PAGE_SCAN_TYPE_COMMAND : 1 << (13*8+0), + HCI_WRITE_PAGE_SCAN_TYPE_COMMAND : 1 << (13*8+1), + HCI_READ_AFH_CHANNEL_ASSESSMENT_MODE_COMMAND : 1 << (13*8+2), + HCI_WRITE_AFH_CHANNEL_ASSESSMENT_MODE_COMMAND : 1 << (13*8+3), + HCI_READ_LOCAL_VERSION_INFORMATION_COMMAND : 1 << (14*8+3), + HCI_READ_LOCAL_SUPPORTED_FEATURES_COMMAND : 1 << (14*8+5), + HCI_READ_LOCAL_EXTENDED_FEATURES_COMMAND : 1 << (14*8+6), + HCI_READ_BUFFER_SIZE_COMMAND : 1 << (14*8+7), + HCI_READ_BD_ADDR_COMMAND : 1 << (15*8+1), + HCI_READ_FAILED_CONTACT_COUNTER_COMMAND : 1 << (15*8+2), + HCI_RESET_FAILED_CONTACT_COUNTER_COMMAND : 1 << (15*8+3), + HCI_READ_LINK_QUALITY_COMMAND : 1 << (15*8+4), + HCI_READ_RSSI_COMMAND : 1 << (15*8+5), + HCI_READ_AFH_CHANNEL_MAP_COMMAND : 1 << (15*8+6), + HCI_READ_CLOCK_COMMAND : 1 << (15*8+7), + HCI_READ_LOOPBACK_MODE_COMMAND : 1 << (16*8+0), + HCI_WRITE_LOOPBACK_MODE_COMMAND : 1 << (16*8+1), + HCI_ENABLE_DEVICE_UNDER_TEST_MODE_COMMAND : 1 << (16*8+2), + HCI_SETUP_SYNCHRONOUS_CONNECTION_COMMAND : 1 << (16*8+3), + HCI_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST_COMMAND : 1 << (16*8+4), + HCI_REJECT_SYNCHRONOUS_CONNECTION_REQUEST_COMMAND : 1 << (16*8+5), + HCI_READ_EXTENDED_INQUIRY_RESPONSE_COMMAND : 1 << (17*8+0), + HCI_WRITE_EXTENDED_INQUIRY_RESPONSE_COMMAND : 1 << (17*8+1), + HCI_REFRESH_ENCRYPTION_KEY_COMMAND : 1 << (17*8+2), + HCI_SNIFF_SUBRATING_COMMAND : 1 << (17*8+4), + HCI_READ_SIMPLE_PAIRING_MODE_COMMAND : 1 << (17*8+5), + HCI_WRITE_SIMPLE_PAIRING_MODE_COMMAND : 1 << (17*8+6), + HCI_READ_LOCAL_OOB_DATA_COMMAND : 1 << (17*8+7), + HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL_COMMAND : 1 << (18*8+0), + HCI_WRITE_INQUIRY_TRANSMIT_POWER_LEVEL_COMMAND : 1 << (18*8+1), + HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_COMMAND : 1 << (18*8+2), + HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_COMMAND : 1 << (18*8+3), + HCI_IO_CAPABILITY_REQUEST_REPLY_COMMAND : 1 << (18*8+7), + HCI_USER_CONFIRMATION_REQUEST_REPLY_COMMAND : 1 << (19*8+0), + HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (19*8+1), + HCI_USER_PASSKEY_REQUEST_REPLY_COMMAND : 1 << (19*8+2), + HCI_USER_PASSKEY_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (19*8+3), + HCI_REMOTE_OOB_DATA_REQUEST_REPLY_COMMAND : 1 << (19*8+4), + HCI_WRITE_SIMPLE_PAIRING_DEBUG_MODE_COMMAND : 1 << (19*8+5), + HCI_ENHANCED_FLUSH_COMMAND : 1 << (19*8+6), + HCI_REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (19*8+7), + HCI_SEND_KEYPRESS_NOTIFICATION_COMMAND : 1 << (20*8+2), + HCI_IO_CAPABILITY_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (20*8+3), + HCI_READ_ENCRYPTION_KEY_SIZE_COMMAND : 1 << (20*8+4), + HCI_SET_EVENT_MASK_PAGE_2_COMMAND : 1 << (22*8+2), + HCI_READ_FLOW_CONTROL_MODE_COMMAND : 1 << (23*8+0), + HCI_WRITE_FLOW_CONTROL_MODE_COMMAND : 1 << (23*8+1), + HCI_READ_DATA_BLOCK_SIZE_COMMAND : 1 << (23*8+2), + HCI_READ_ENHANCED_TRANSMIT_POWER_LEVEL_COMMAND : 1 << (24*8+0), + HCI_READ_LE_HOST_SUPPORT_COMMAND : 1 << (24*8+5), + HCI_WRITE_LE_HOST_SUPPORT_COMMAND : 1 << (24*8+6), + HCI_LE_SET_EVENT_MASK_COMMAND : 1 << (25*8+0), + HCI_LE_READ_BUFFER_SIZE_COMMAND : 1 << (25*8+1), + HCI_LE_READ_LOCAL_SUPPORTED_FEATURES_COMMAND : 1 << (25*8+2), + HCI_LE_SET_RANDOM_ADDRESS_COMMAND : 1 << (25*8+4), + HCI_LE_SET_ADVERTISING_PARAMETERS_COMMAND : 1 << (25*8+5), + HCI_LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER_COMMAND : 1 << (25*8+6), + HCI_LE_SET_ADVERTISING_DATA_COMMAND : 1 << (25*8+7), + HCI_LE_SET_SCAN_RESPONSE_DATA_COMMAND : 1 << (26*8+0), + HCI_LE_SET_ADVERTISING_ENABLE_COMMAND : 1 << (26*8+1), + HCI_LE_SET_SCAN_PARAMETERS_COMMAND : 1 << (26*8+2), + HCI_LE_SET_SCAN_ENABLE_COMMAND : 1 << (26*8+3), + HCI_LE_CREATE_CONNECTION_COMMAND : 1 << (26*8+4), + HCI_LE_CREATE_CONNECTION_CANCEL_COMMAND : 1 << (26*8+5), + HCI_LE_READ_FILTER_ACCEPT_LIST_SIZE_COMMAND : 1 << (26*8+6), + HCI_LE_CLEAR_FILTER_ACCEPT_LIST_COMMAND : 1 << (26*8+7), + HCI_LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST_COMMAND : 1 << (27*8+0), + HCI_LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST_COMMAND : 1 << (27*8+1), + HCI_LE_CONNECTION_UPDATE_COMMAND : 1 << (27*8+2), + HCI_LE_SET_HOST_CHANNEL_CLASSIFICATION_COMMAND : 1 << (27*8+3), + HCI_LE_READ_CHANNEL_MAP_COMMAND : 1 << (27*8+4), + HCI_LE_READ_REMOTE_FEATURES_COMMAND : 1 << (27*8+5), + HCI_LE_ENCRYPT_COMMAND : 1 << (27*8+6), + HCI_LE_RAND_COMMAND : 1 << (27*8+7), + HCI_LE_ENABLE_ENCRYPTION_COMMAND : 1 << (28*8+0), + HCI_LE_LONG_TERM_KEY_REQUEST_REPLY_COMMAND : 1 << (28*8+1), + HCI_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (28*8+2), + HCI_LE_READ_SUPPORTED_STATES_COMMAND : 1 << (28*8+3), + HCI_LE_RECEIVER_TEST_COMMAND : 1 << (28*8+4), + HCI_LE_TRANSMITTER_TEST_COMMAND : 1 << (28*8+5), + HCI_LE_TEST_END_COMMAND : 1 << (28*8+6), + HCI_ENHANCED_SETUP_SYNCHRONOUS_CONNECTION_COMMAND : 1 << (29*8+3), + HCI_ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST_COMMAND : 1 << (29*8+4), + HCI_READ_LOCAL_SUPPORTED_CODECS_COMMAND : 1 << (29*8+5), + HCI_SET_MWS_CHANNEL_PARAMETERS_COMMAND : 1 << (29*8+6), + HCI_SET_EXTERNAL_FRAME_CONFIGURATION_COMMAND : 1 << (29*8+7), + HCI_SET_MWS_SIGNALING_COMMAND : 1 << (30*8+0), + HCI_SET_MWS_TRANSPORT_LAYER_COMMAND : 1 << (30*8+1), + HCI_SET_MWS_SCAN_FREQUENCY_TABLE_COMMAND : 1 << (30*8+2), + HCI_GET_MWS_TRANSPORT_LAYER_CONFIGURATION_COMMAND : 1 << (30*8+3), + HCI_SET_MWS_PATTERN_CONFIGURATION_COMMAND : 1 << (30*8+4), + HCI_SET_TRIGGERED_CLOCK_CAPTURE_COMMAND : 1 << (30*8+5), + HCI_TRUNCATED_PAGE_COMMAND : 1 << (30*8+6), + HCI_TRUNCATED_PAGE_CANCEL_COMMAND : 1 << (30*8+7), + HCI_SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_COMMAND : 1 << (31*8+0), + HCI_SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE_COMMAND : 1 << (31*8+1), + HCI_START_SYNCHRONIZATION_TRAIN_COMMAND : 1 << (31*8+2), + HCI_RECEIVE_SYNCHRONIZATION_TRAIN_COMMAND : 1 << (31*8+3), + HCI_SET_RESERVED_LT_ADDR_COMMAND : 1 << (31*8+4), + HCI_DELETE_RESERVED_LT_ADDR_COMMAND : 1 << (31*8+5), + HCI_SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA_COMMAND : 1 << (31*8+6), + HCI_READ_SYNCHRONIZATION_TRAIN_PARAMETERS_COMMAND : 1 << (31*8+7), + HCI_WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS_COMMAND : 1 << (32*8+0), + HCI_REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY_COMMAND : 1 << (32*8+1), + HCI_READ_SECURE_CONNECTIONS_HOST_SUPPORT_COMMAND : 1 << (32*8+2), + HCI_WRITE_SECURE_CONNECTIONS_HOST_SUPPORT_COMMAND : 1 << (32*8+3), + HCI_READ_AUTHENTICATED_PAYLOAD_TIMEOUT_COMMAND : 1 << (32*8+4), + HCI_WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT_COMMAND : 1 << (32*8+5), + HCI_READ_LOCAL_OOB_EXTENDED_DATA_COMMAND : 1 << (32*8+6), + HCI_WRITE_SECURE_CONNECTIONS_TEST_MODE_COMMAND : 1 << (32*8+7), + HCI_READ_EXTENDED_PAGE_TIMEOUT_COMMAND : 1 << (33*8+0), + HCI_WRITE_EXTENDED_PAGE_TIMEOUT_COMMAND : 1 << (33*8+1), + HCI_READ_EXTENDED_INQUIRY_LENGTH_COMMAND : 1 << (33*8+2), + HCI_WRITE_EXTENDED_INQUIRY_LENGTH_COMMAND : 1 << (33*8+3), + HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_COMMAND : 1 << (33*8+4), + HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_COMMAND : 1 << (33*8+5), + HCI_LE_SET_DATA_LENGTH_COMMAND : 1 << (33*8+6), + HCI_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND : 1 << (33*8+7), + HCI_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND : 1 << (34*8+0), + HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND : 1 << (34*8+1), + HCI_LE_GENERATE_DHKEY_COMMAND : 1 << (34*8+2), + HCI_LE_ADD_DEVICE_TO_RESOLVING_LIST_COMMAND : 1 << (34*8+3), + HCI_LE_REMOVE_DEVICE_FROM_RESOLVING_LIST_COMMAND : 1 << (34*8+4), + HCI_LE_CLEAR_RESOLVING_LIST_COMMAND : 1 << (34*8+5), + HCI_LE_READ_RESOLVING_LIST_SIZE_COMMAND : 1 << (34*8+6), + HCI_LE_READ_PEER_RESOLVABLE_ADDRESS_COMMAND : 1 << (34*8+7), + HCI_LE_READ_LOCAL_RESOLVABLE_ADDRESS_COMMAND : 1 << (35*8+0), + HCI_LE_SET_ADDRESS_RESOLUTION_ENABLE_COMMAND : 1 << (35*8+1), + HCI_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_COMMAND : 1 << (35*8+2), + HCI_LE_READ_MAXIMUM_DATA_LENGTH_COMMAND : 1 << (35*8+3), + HCI_LE_READ_PHY_COMMAND : 1 << (35*8+4), + HCI_LE_SET_DEFAULT_PHY_COMMAND : 1 << (35*8+5), + HCI_LE_SET_PHY_COMMAND : 1 << (35*8+6), + HCI_LE_RECEIVER_TEST_V2_COMMAND : 1 << (35*8+7), + HCI_LE_TRANSMITTER_TEST_V2_COMMAND : 1 << (36*8+0), + HCI_LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_COMMAND : 1 << (36*8+1), + HCI_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_COMMAND : 1 << (36*8+2), + HCI_LE_SET_EXTENDED_ADVERTISING_DATA_COMMAND : 1 << (36*8+3), + HCI_LE_SET_EXTENDED_SCAN_RESPONSE_DATA_COMMAND : 1 << (36*8+4), + HCI_LE_SET_EXTENDED_ADVERTISING_ENABLE_COMMAND : 1 << (36*8+5), + HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_COMMAND : 1 << (36*8+6), + HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS_COMMAND : 1 << (36*8+7), + HCI_LE_REMOVE_ADVERTISING_SET_COMMAND : 1 << (37*8+0), + HCI_LE_CLEAR_ADVERTISING_SETS_COMMAND : 1 << (37*8+1), + HCI_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_COMMAND : 1 << (37*8+2), + HCI_LE_SET_PERIODIC_ADVERTISING_DATA_COMMAND : 1 << (37*8+3), + HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE_COMMAND : 1 << (37*8+4), + HCI_LE_SET_EXTENDED_SCAN_PARAMETERS_COMMAND : 1 << (37*8+5), + HCI_LE_SET_EXTENDED_SCAN_ENABLE_COMMAND : 1 << (37*8+6), + HCI_LE_EXTENDED_CREATE_CONNECTION_COMMAND : 1 << (37*8+7), + HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_COMMAND : 1 << (38*8+0), + HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_COMMAND : 1 << (38*8+1), + HCI_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_COMMAND : 1 << (38*8+2), + HCI_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_COMMAND : 1 << (38*8+3), + HCI_LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_COMMAND : 1 << (38*8+4), + HCI_LE_CLEAR_PERIODIC_ADVERTISER_LIST_COMMAND : 1 << (38*8+5), + HCI_LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_COMMAND : 1 << (38*8+6), + HCI_LE_READ_TRANSMIT_POWER_COMMAND : 1 << (38*8+7), + HCI_LE_READ_RF_PATH_COMPENSATION_COMMAND : 1 << (39*8+0), + HCI_LE_WRITE_RF_PATH_COMPENSATION_COMMAND : 1 << (39*8+1), + HCI_LE_SET_PRIVACY_MODE_COMMAND : 1 << (39*8+2), + HCI_LE_RECEIVER_TEST_V3_COMMAND : 1 << (39*8+3), + HCI_LE_TRANSMITTER_TEST_V3_COMMAND : 1 << (39*8+4), + HCI_LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS_COMMAND : 1 << (39*8+5), + HCI_LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE_COMMAND : 1 << (39*8+6), + HCI_LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE_COMMAND : 1 << (39*8+7), + HCI_LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS_COMMAND : 1 << (40*8+0), + HCI_LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS_COMMAND : 1 << (40*8+1), + HCI_LE_CONNECTION_CTE_REQUEST_ENABLE_COMMAND : 1 << (40*8+2), + HCI_LE_CONNECTION_CTE_RESPONSE_ENABLE_COMMAND : 1 << (40*8+3), + HCI_LE_READ_ANTENNA_INFORMATION_COMMAND : 1 << (40*8+4), + HCI_LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE_COMMAND : 1 << (40*8+5), + HCI_LE_PERIODIC_ADVERTISING_SYNC_TRANSFER_COMMAND : 1 << (40*8+6), + HCI_LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER_COMMAND : 1 << (40*8+7), + HCI_LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS_COMMAND : 1 << (41*8+0), + HCI_LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS_COMMAND : 1 << (41*8+1), + HCI_LE_GENERATE_DHKEY_V2_COMMAND : 1 << (41*8+2), + HCI_READ_LOCAL_SIMPLE_PAIRING_OPTIONS_COMMAND : 1 << (41*8+3), + HCI_LE_MODIFY_SLEEP_CLOCK_ACCURACY_COMMAND : 1 << (41*8+4), + HCI_LE_READ_BUFFER_SIZE_V2_COMMAND : 1 << (41*8+5), + HCI_LE_READ_ISO_TX_SYNC_COMMAND : 1 << (41*8+6), + HCI_LE_SET_CIG_PARAMETERS_COMMAND : 1 << (41*8+7), + HCI_LE_SET_CIG_PARAMETERS_TEST_COMMAND : 1 << (42*8+0), + HCI_LE_CREATE_CIS_COMMAND : 1 << (42*8+1), + HCI_LE_REMOVE_CIG_COMMAND : 1 << (42*8+2), + HCI_LE_ACCEPT_CIS_REQUEST_COMMAND : 1 << (42*8+3), + HCI_LE_REJECT_CIS_REQUEST_COMMAND : 1 << (42*8+4), + HCI_LE_CREATE_BIG_COMMAND : 1 << (42*8+5), + HCI_LE_CREATE_BIG_TEST_COMMAND : 1 << (42*8+6), + HCI_LE_TERMINATE_BIG_COMMAND : 1 << (42*8+7), + HCI_LE_BIG_CREATE_SYNC_COMMAND : 1 << (43*8+0), + HCI_LE_BIG_TERMINATE_SYNC_COMMAND : 1 << (43*8+1), + HCI_LE_REQUEST_PEER_SCA_COMMAND : 1 << (43*8+2), + HCI_LE_SETUP_ISO_DATA_PATH_COMMAND : 1 << (43*8+3), + HCI_LE_REMOVE_ISO_DATA_PATH_COMMAND : 1 << (43*8+4), + HCI_LE_ISO_TRANSMIT_TEST_COMMAND : 1 << (43*8+5), + HCI_LE_ISO_RECEIVE_TEST_COMMAND : 1 << (43*8+6), + HCI_LE_ISO_READ_TEST_COUNTERS_COMMAND : 1 << (43*8+7), + HCI_LE_ISO_TEST_END_COMMAND : 1 << (44*8+0), + HCI_LE_SET_HOST_FEATURE_COMMAND : 1 << (44*8+1), + HCI_LE_READ_ISO_LINK_QUALITY_COMMAND : 1 << (44*8+2), + HCI_LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL_COMMAND : 1 << (44*8+3), + HCI_LE_READ_REMOTE_TRANSMIT_POWER_LEVEL_COMMAND : 1 << (44*8+4), + HCI_LE_SET_PATH_LOSS_REPORTING_PARAMETERS_COMMAND : 1 << (44*8+5), + HCI_LE_SET_PATH_LOSS_REPORTING_ENABLE_COMMAND : 1 << (44*8+6), + HCI_LE_SET_TRANSMIT_POWER_REPORTING_ENABLE_COMMAND : 1 << (44*8+7), + HCI_LE_TRANSMITTER_TEST_V4_COMMAND : 1 << (45*8+0), + HCI_SET_ECOSYSTEM_BASE_INTERVAL_COMMAND : 1 << (45*8+1), + HCI_READ_LOCAL_SUPPORTED_CODECS_V2_COMMAND : 1 << (45*8+2), + HCI_READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES_COMMAND : 1 << (45*8+3), + HCI_READ_LOCAL_SUPPORTED_CONTROLLER_DELAY_COMMAND : 1 << (45*8+4), + HCI_CONFIGURE_DATA_PATH_COMMAND : 1 << (45*8+5), + HCI_LE_SET_DATA_RELATED_ADDRESS_CHANGES_COMMAND : 1 << (45*8+6), + HCI_SET_MIN_ENCRYPTION_KEY_SIZE_COMMAND : 1 << (45*8+7), + HCI_LE_SET_DEFAULT_SUBRATE_COMMAND : 1 << (46*8+0), + HCI_LE_SUBRATE_REQUEST_COMMAND : 1 << (46*8+1), + HCI_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2_COMMAND : 1 << (46*8+2), + HCI_LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA_COMMAND : 1 << (46*8+5), + HCI_LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA_COMMAND : 1 << (46*8+6), + HCI_LE_SET_PERIODIC_SYNC_SUBEVENT_COMMAND : 1 << (46*8+7), + HCI_LE_EXTENDED_CREATE_CONNECTION_V2_COMMAND : 1 << (47*8+0), + HCI_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2_COMMAND : 1 << (47*8+1), +} # LE Supported Features -HCI_LE_ENCRYPTION_LE_SUPPORTED_FEATURE = 0 -HCI_CONNECTION_PARAMETERS_REQUEST_PROCEDURE_LE_SUPPORTED_FEATURE = 1 -HCI_EXTENDED_REJECT_INDICATION_LE_SUPPORTED_FEATURE = 2 -HCI_PERIPHERAL_INITIATED_FEATURE_EXCHANGE_LE_SUPPORTED_FEATURE = 3 -HCI_LE_PING_LE_SUPPORTED_FEATURE = 4 -HCI_LE_DATA_PACKET_LENGTH_EXTENSION_LE_SUPPORTED_FEATURE = 5 -HCI_LL_PRIVACY_LE_SUPPORTED_FEATURE = 6 -HCI_EXTENDED_SCANNER_FILTER_POLICIES_LE_SUPPORTED_FEATURE = 7 -HCI_LE_2M_PHY_LE_SUPPORTED_FEATURE = 8 -HCI_STABLE_MODULATION_INDEX_TRANSMITTER_LE_SUPPORTED_FEATURE = 9 -HCI_STABLE_MODULATION_INDEX_RECEIVER_LE_SUPPORTED_FEATURE = 10 -HCI_LE_CODED_PHY_LE_SUPPORTED_FEATURE = 11 -HCI_LE_EXTENDED_ADVERTISING_LE_SUPPORTED_FEATURE = 12 -HCI_LE_PERIODIC_ADVERTISING_LE_SUPPORTED_FEATURE = 13 -HCI_CHANNEL_SELECTION_ALGORITHM_2_LE_SUPPORTED_FEATURE = 14 -HCI_LE_POWER_CLASS_1_LE_SUPPORTED_FEATURE = 15 -HCI_MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE_LE_SUPPORTED_FEATURE = 16 -HCI_CONNECTION_CTE_REQUEST_LE_SUPPORTED_FEATURE = 17 -HCI_CONNECTION_CTE_RESPONSE_LE_SUPPORTED_FEATURE = 18 -HCI_CONNECTIONLESS_CTE_TRANSMITTER_LE_SUPPORTED_FEATURE = 19 -HCI_CONNECTIONLESS_CTR_RECEIVER_LE_SUPPORTED_FEATURE = 20 -HCI_ANTENNA_SWITCHING_DURING_CTE_TRANSMISSION_LE_SUPPORTED_FEATURE = 21 -HCI_ANTENNA_SWITCHING_DURING_CTE_RECEPTION_LE_SUPPORTED_FEATURE = 22 -HCI_RECEIVING_CONSTANT_TONE_EXTENSIONS_LE_SUPPORTED_FEATURE = 23 -HCI_PERIODIC_ADVERTISING_SYNC_TRANSFER_SENDER_LE_SUPPORTED_FEATURE = 24 -HCI_PERIODIC_ADVERTISING_SYNC_TRANSFER_RECIPIENT_LE_SUPPORTED_FEATURE = 25 -HCI_SLEEP_CLOCK_ACCURACY_UPDATES_LE_SUPPORTED_FEATURE = 26 -HCI_REMOTE_PUBLIC_KEY_VALIDATION_LE_SUPPORTED_FEATURE = 27 -HCI_CONNECTED_ISOCHRONOUS_STREAM_CENTRAL_LE_SUPPORTED_FEATURE = 28 -HCI_CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL_LE_SUPPORTED_FEATURE = 29 -HCI_ISOCHRONOUS_BROADCASTER_LE_SUPPORTED_FEATURE = 30 -HCI_SYNCHRONIZED_RECEIVER_LE_SUPPORTED_FEATURE = 31 -HCI_CONNECTED_ISOCHRONOUS_STREAM_LE_SUPPORTED_FEATURE = 32 -HCI_LE_POWER_CONTROL_REQUEST_LE_SUPPORTED_FEATURE = 33 -HCI_LE_POWER_CONTROL_REQUEST_DUP_LE_SUPPORTED_FEATURE = 34 -HCI_LE_PATH_LOSS_MONITORING_LE_SUPPORTED_FEATURE = 35 -HCI_PERIODIC_ADVERTISING_ADI_SUPPORT_LE_SUPPORTED_FEATURE = 36 -HCI_CONNECTION_SUBRATING_LE_SUPPORTED_FEATURE = 37 -HCI_CONNECTION_SUBRATING_HOST_SUPPORT_LE_SUPPORTED_FEATURE = 38 -HCI_CHANNEL_CLASSIFICATION_LE_SUPPORTED_FEATURE = 39 - -HCI_LE_SUPPORTED_FEATURES_NAMES = { - flag: feature_name for (feature_name, flag) in globals().items() - if feature_name.startswith('HCI_') and feature_name.endswith('_LE_SUPPORTED_FEATURE') -} +# See Bluetooth spec @ Vol 6, Part B, 4.6 FEATURE SUPPORT +class LeFeature(enum.IntEnum): + LE_ENCRYPTION = 0 + CONNECTION_PARAMETERS_REQUEST_PROCEDURE = 1 + EXTENDED_REJECT_INDICATION = 2 + PERIPHERAL_INITIATED_FEATURE_EXCHANGE = 3 + LE_PING = 4 + LE_DATA_PACKET_LENGTH_EXTENSION = 5 + LL_PRIVACY = 6 + EXTENDED_SCANNER_FILTER_POLICIES = 7 + LE_2M_PHY = 8 + STABLE_MODULATION_INDEX_TRANSMITTER = 9 + STABLE_MODULATION_INDEX_RECEIVER = 10 + LE_CODED_PHY = 11 + LE_EXTENDED_ADVERTISING = 12 + LE_PERIODIC_ADVERTISING = 13 + CHANNEL_SELECTION_ALGORITHM_2 = 14 + LE_POWER_CLASS_1 = 15 + MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE = 16 + CONNECTION_CTE_REQUEST = 17 + CONNECTION_CTE_RESPONSE = 18 + CONNECTIONLESS_CTE_TRANSMITTER = 19 + CONNECTIONLESS_CTR_RECEIVER = 20 + ANTENNA_SWITCHING_DURING_CTE_TRANSMISSION = 21 + ANTENNA_SWITCHING_DURING_CTE_RECEPTION = 22 + RECEIVING_CONSTANT_TONE_EXTENSIONS = 23 + PERIODIC_ADVERTISING_SYNC_TRANSFER_SENDER = 24 + PERIODIC_ADVERTISING_SYNC_TRANSFER_RECIPIENT = 25 + SLEEP_CLOCK_ACCURACY_UPDATES = 26 + REMOTE_PUBLIC_KEY_VALIDATION = 27 + CONNECTED_ISOCHRONOUS_STREAM_CENTRAL = 28 + CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL = 29 + ISOCHRONOUS_BROADCASTER = 30 + SYNCHRONIZED_RECEIVER = 31 + CONNECTED_ISOCHRONOUS_STREAM = 32 + LE_POWER_CONTROL_REQUEST = 33 + LE_POWER_CONTROL_REQUEST_DUP = 34 + LE_PATH_LOSS_MONITORING = 35 + PERIODIC_ADVERTISING_ADI_SUPPORT = 36 + CONNECTION_SUBRATING = 37 + CONNECTION_SUBRATING_HOST_SUPPORT = 38 + CHANNEL_CLASSIFICATION = 39 + ADVERTISING_CODING_SELECTION = 40 + ADVERTISING_CODING_SELECTION_HOST_SUPPORT = 41 + PERIODIC_ADVERTISING_WITH_RESPONSES_ADVERTISER = 43 + PERIODIC_ADVERTISING_WITH_RESPONSES_SCANNER = 44 + +class LeFeatureMask(enum.IntFlag): + LE_ENCRYPTION = 1 << LeFeature.LE_ENCRYPTION + CONNECTION_PARAMETERS_REQUEST_PROCEDURE = 1 << LeFeature.CONNECTION_PARAMETERS_REQUEST_PROCEDURE + EXTENDED_REJECT_INDICATION = 1 << LeFeature.EXTENDED_REJECT_INDICATION + PERIPHERAL_INITIATED_FEATURE_EXCHANGE = 1 << LeFeature.PERIPHERAL_INITIATED_FEATURE_EXCHANGE + LE_PING = 1 << LeFeature.LE_PING + LE_DATA_PACKET_LENGTH_EXTENSION = 1 << LeFeature.LE_DATA_PACKET_LENGTH_EXTENSION + LL_PRIVACY = 1 << LeFeature.LL_PRIVACY + EXTENDED_SCANNER_FILTER_POLICIES = 1 << LeFeature.EXTENDED_SCANNER_FILTER_POLICIES + LE_2M_PHY = 1 << LeFeature.LE_2M_PHY + STABLE_MODULATION_INDEX_TRANSMITTER = 1 << LeFeature.STABLE_MODULATION_INDEX_TRANSMITTER + STABLE_MODULATION_INDEX_RECEIVER = 1 << LeFeature.STABLE_MODULATION_INDEX_RECEIVER + LE_CODED_PHY = 1 << LeFeature.LE_CODED_PHY + LE_EXTENDED_ADVERTISING = 1 << LeFeature.LE_EXTENDED_ADVERTISING + LE_PERIODIC_ADVERTISING = 1 << LeFeature.LE_PERIODIC_ADVERTISING + CHANNEL_SELECTION_ALGORITHM_2 = 1 << LeFeature.CHANNEL_SELECTION_ALGORITHM_2 + LE_POWER_CLASS_1 = 1 << LeFeature.LE_POWER_CLASS_1 + MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE = 1 << LeFeature.MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE + CONNECTION_CTE_REQUEST = 1 << LeFeature.CONNECTION_CTE_REQUEST + CONNECTION_CTE_RESPONSE = 1 << LeFeature.CONNECTION_CTE_RESPONSE + CONNECTIONLESS_CTE_TRANSMITTER = 1 << LeFeature.CONNECTIONLESS_CTE_TRANSMITTER + CONNECTIONLESS_CTR_RECEIVER = 1 << LeFeature.CONNECTIONLESS_CTR_RECEIVER + ANTENNA_SWITCHING_DURING_CTE_TRANSMISSION = 1 << LeFeature.ANTENNA_SWITCHING_DURING_CTE_TRANSMISSION + ANTENNA_SWITCHING_DURING_CTE_RECEPTION = 1 << LeFeature.ANTENNA_SWITCHING_DURING_CTE_RECEPTION + RECEIVING_CONSTANT_TONE_EXTENSIONS = 1 << LeFeature.RECEIVING_CONSTANT_TONE_EXTENSIONS + PERIODIC_ADVERTISING_SYNC_TRANSFER_SENDER = 1 << LeFeature.PERIODIC_ADVERTISING_SYNC_TRANSFER_SENDER + PERIODIC_ADVERTISING_SYNC_TRANSFER_RECIPIENT = 1 << LeFeature.PERIODIC_ADVERTISING_SYNC_TRANSFER_RECIPIENT + SLEEP_CLOCK_ACCURACY_UPDATES = 1 << LeFeature.SLEEP_CLOCK_ACCURACY_UPDATES + REMOTE_PUBLIC_KEY_VALIDATION = 1 << LeFeature.REMOTE_PUBLIC_KEY_VALIDATION + CONNECTED_ISOCHRONOUS_STREAM_CENTRAL = 1 << LeFeature.CONNECTED_ISOCHRONOUS_STREAM_CENTRAL + CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL = 1 << LeFeature.CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL + ISOCHRONOUS_BROADCASTER = 1 << LeFeature.ISOCHRONOUS_BROADCASTER + SYNCHRONIZED_RECEIVER = 1 << LeFeature.SYNCHRONIZED_RECEIVER + CONNECTED_ISOCHRONOUS_STREAM = 1 << LeFeature.CONNECTED_ISOCHRONOUS_STREAM + LE_POWER_CONTROL_REQUEST = 1 << LeFeature.LE_POWER_CONTROL_REQUEST + LE_POWER_CONTROL_REQUEST_DUP = 1 << LeFeature.LE_POWER_CONTROL_REQUEST_DUP + LE_PATH_LOSS_MONITORING = 1 << LeFeature.LE_PATH_LOSS_MONITORING + PERIODIC_ADVERTISING_ADI_SUPPORT = 1 << LeFeature.PERIODIC_ADVERTISING_ADI_SUPPORT + CONNECTION_SUBRATING = 1 << LeFeature.CONNECTION_SUBRATING + CONNECTION_SUBRATING_HOST_SUPPORT = 1 << LeFeature.CONNECTION_SUBRATING_HOST_SUPPORT + CHANNEL_CLASSIFICATION = 1 << LeFeature.CHANNEL_CLASSIFICATION + ADVERTISING_CODING_SELECTION = 1 << LeFeature.ADVERTISING_CODING_SELECTION + ADVERTISING_CODING_SELECTION_HOST_SUPPORT = 1 << LeFeature.ADVERTISING_CODING_SELECTION_HOST_SUPPORT + PERIODIC_ADVERTISING_WITH_RESPONSES_ADVERTISER = 1 << LeFeature.PERIODIC_ADVERTISING_WITH_RESPONSES_ADVERTISER + PERIODIC_ADVERTISING_WITH_RESPONSES_SCANNER = 1 << LeFeature.PERIODIC_ADVERTISING_WITH_RESPONSES_SCANNER + +class LmpFeature(enum.IntEnum): + # Page 0 (Legacy LMP features) + LMP_3_SLOT_PACKETS = 0 + LMP_5_SLOT_PACKETS = 1 + ENCRYPTION = 2 + SLOT_OFFSET = 3 + TIMING_ACCURACY = 4 + ROLE_SWITCH = 5 + HOLD_MODE = 6 + SNIFF_MODE = 7 + # PREVIOUSLY_USED = 8 + POWER_CONTROL_REQUESTS = 9 + CHANNEL_QUALITY_DRIVEN_DATA_RATE_CQDDR = 10 + SCO_LINK = 11 + HV2_PACKETS = 12 + HV3_PACKETS = 13 + U_LAW_LOG_SYNCHRONOUS_DATA = 14 + A_LAW_LOG_SYNCHRONOUS_DATA = 15 + CVSD_SYNCHRONOUS_DATA = 16 + PAGING_PARAMETER_NEGOTIATION = 17 + POWER_CONTROL = 18 + TRANSPARENT_SYNCHRONOUS_DATA = 19 + FLOW_CONTROL_LAG_LEAST_SIGNIFICANT_BIT = 20 + FLOW_CONTROL_LAG_MIDDLE_BIT = 21 + FLOW_CONTROL_LAG_MOST_SIGNIFICANT_BIT = 22 + BROADCAST_ENCRYPTION = 23 + # RESERVED_FOR_FUTURE_USE = 24 + ENHANCED_DATA_RATE_ACL_2_MBPS_MODE = 25 + ENHANCED_DATA_RATE_ACL_3_MBPS_MODE = 26 + ENHANCED_INQUIRY_SCAN = 27 + INTERLACED_INQUIRY_SCAN = 28 + INTERLACED_PAGE_SCAN = 29 + RSSI_WITH_INQUIRY_RESULTS = 30 + EXTENDED_SCO_LINK_EV3_PACKETS = 31 + EV4_PACKETS = 32 + EV5_PACKETS = 33 + # RESERVED_FOR_FUTURE_USE = 34 + AFH_CAPABLE_PERIPHERAL = 35 + AFH_CLASSIFICATION_PERIPHERAL = 36 + BR_EDR_NOT_SUPPORTED = 37 + LE_SUPPORTED_CONTROLLER = 38 + LMP_3_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS = 39 + LMP_5_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS = 40 + SNIFF_SUBRATING = 41 + PAUSE_ENCRYPTION = 42 + AFH_CAPABLE_CENTRAL = 43 + AFH_CLASSIFICATION_CENTRAL = 44 + ENHANCED_DATA_RATE_ESCO_2_MBPS_MODE = 45 + ENHANCED_DATA_RATE_ESCO_3_MBPS_MODE = 46 + LMP_3_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS = 47 + EXTENDED_INQUIRY_RESPONSE = 48 + SIMULTANEOUS_LE_AND_BR_EDR_TO_SAME_DEVICE_CAPABLE_CONTROLLER = 49 + # RESERVED_FOR_FUTURE_USE = 50 + SECURE_SIMPLE_PAIRING_CONTROLLER_SUPPORT = 51 + ENCAPSULATED_PDU = 52 + ERRONEOUS_DATA_REPORTING = 53 + NON_FLUSHABLE_PACKET_BOUNDARY_FLAG = 54 + # RESERVED_FOR_FUTURE_USE = 55 + HCI_LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT = 56 + VARIABLE_INQUIRY_TX_POWER_LEVEL = 57 + ENHANCED_POWER_CONTROL = 58 + # RESERVED_FOR_FUTURE_USE = 59 + # RESERVED_FOR_FUTURE_USE = 60 + # RESERVED_FOR_FUTURE_USE = 61 + # RESERVED_FOR_FUTURE_USE = 62 + EXTENDED_FEATURES = 63 + + # Page 1 + SECURE_SIMPLE_PAIRING_HOST_SUPPORT = 64 + LE_SUPPORTED_HOST = 65 + # PREVIOUSLY_USED = 66 + SECURE_CONNECTIONS_HOST_SUPPORT = 67 + + # Page 2 + CONNECTIONLESS_PERIPHERAL_BROADCAST_TRANSMITTER_OPERATION = 128 + CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVER_OPERATION = 129 + SYNCHRONIZATION_TRAIN = 130 + SYNCHRONIZATION_SCAN = 131 + HCI_INQUIRY_RESPONSE_NOTIFICATION_EVENT = 132 + GENERALIZED_INTERLACED_SCAN = 133 + COARSE_CLOCK_ADJUSTMENT = 134 + RESERVED_FOR_FUTURE_USE = 135 + SECURE_CONNECTIONS_CONTROLLER_SUPPORT = 136 + PING = 137 + SLOT_AVAILABILITY_MASK = 138 + TRAIN_NUDGING = 139 + +class LmpFeatureMask(enum.IntFlag): + # Page 0 (Legacy LMP features) + LMP_3_SLOT_PACKETS = (1 << LmpFeature.LMP_3_SLOT_PACKETS) + LMP_5_SLOT_PACKETS = (1 << LmpFeature.LMP_5_SLOT_PACKETS) + ENCRYPTION = (1 << LmpFeature.ENCRYPTION) + SLOT_OFFSET = (1 << LmpFeature.SLOT_OFFSET) + TIMING_ACCURACY = (1 << LmpFeature.TIMING_ACCURACY) + ROLE_SWITCH = (1 << LmpFeature.ROLE_SWITCH) + HOLD_MODE = (1 << LmpFeature.HOLD_MODE) + SNIFF_MODE = (1 << LmpFeature.SNIFF_MODE) + # PREVIOUSLY_USED = (1 << LmpFeature.PREVIOUSLY_USED) + POWER_CONTROL_REQUESTS = (1 << LmpFeature.POWER_CONTROL_REQUESTS) + CHANNEL_QUALITY_DRIVEN_DATA_RATE_CQDDR = (1 << LmpFeature.CHANNEL_QUALITY_DRIVEN_DATA_RATE_CQDDR) + SCO_LINK = (1 << LmpFeature.SCO_LINK) + HV2_PACKETS = (1 << LmpFeature.HV2_PACKETS) + HV3_PACKETS = (1 << LmpFeature.HV3_PACKETS) + U_LAW_LOG_SYNCHRONOUS_DATA = (1 << LmpFeature.U_LAW_LOG_SYNCHRONOUS_DATA) + A_LAW_LOG_SYNCHRONOUS_DATA = (1 << LmpFeature.A_LAW_LOG_SYNCHRONOUS_DATA) + CVSD_SYNCHRONOUS_DATA = (1 << LmpFeature.CVSD_SYNCHRONOUS_DATA) + PAGING_PARAMETER_NEGOTIATION = (1 << LmpFeature.PAGING_PARAMETER_NEGOTIATION) + POWER_CONTROL = (1 << LmpFeature.POWER_CONTROL) + TRANSPARENT_SYNCHRONOUS_DATA = (1 << LmpFeature.TRANSPARENT_SYNCHRONOUS_DATA) + FLOW_CONTROL_LAG_LEAST_SIGNIFICANT_BIT = (1 << LmpFeature.FLOW_CONTROL_LAG_LEAST_SIGNIFICANT_BIT) + FLOW_CONTROL_LAG_MIDDLE_BIT = (1 << LmpFeature.FLOW_CONTROL_LAG_MIDDLE_BIT) + FLOW_CONTROL_LAG_MOST_SIGNIFICANT_BIT = (1 << LmpFeature.FLOW_CONTROL_LAG_MOST_SIGNIFICANT_BIT) + BROADCAST_ENCRYPTION = (1 << LmpFeature.BROADCAST_ENCRYPTION) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + ENHANCED_DATA_RATE_ACL_2_MBPS_MODE = (1 << LmpFeature.ENHANCED_DATA_RATE_ACL_2_MBPS_MODE) + ENHANCED_DATA_RATE_ACL_3_MBPS_MODE = (1 << LmpFeature.ENHANCED_DATA_RATE_ACL_3_MBPS_MODE) + ENHANCED_INQUIRY_SCAN = (1 << LmpFeature.ENHANCED_INQUIRY_SCAN) + INTERLACED_INQUIRY_SCAN = (1 << LmpFeature.INTERLACED_INQUIRY_SCAN) + INTERLACED_PAGE_SCAN = (1 << LmpFeature.INTERLACED_PAGE_SCAN) + RSSI_WITH_INQUIRY_RESULTS = (1 << LmpFeature.RSSI_WITH_INQUIRY_RESULTS) + EXTENDED_SCO_LINK_EV3_PACKETS = (1 << LmpFeature.EXTENDED_SCO_LINK_EV3_PACKETS) + EV4_PACKETS = (1 << LmpFeature.EV4_PACKETS) + EV5_PACKETS = (1 << LmpFeature.EV5_PACKETS) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + AFH_CAPABLE_PERIPHERAL = (1 << LmpFeature.AFH_CAPABLE_PERIPHERAL) + AFH_CLASSIFICATION_PERIPHERAL = (1 << LmpFeature.AFH_CLASSIFICATION_PERIPHERAL) + BR_EDR_NOT_SUPPORTED = (1 << LmpFeature.BR_EDR_NOT_SUPPORTED) + LE_SUPPORTED_CONTROLLER = (1 << LmpFeature.LE_SUPPORTED_CONTROLLER) + LMP_3_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS = (1 << LmpFeature.LMP_3_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) + LMP_5_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS = (1 << LmpFeature.LMP_5_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) + SNIFF_SUBRATING = (1 << LmpFeature.SNIFF_SUBRATING) + PAUSE_ENCRYPTION = (1 << LmpFeature.PAUSE_ENCRYPTION) + AFH_CAPABLE_CENTRAL = (1 << LmpFeature.AFH_CAPABLE_CENTRAL) + AFH_CLASSIFICATION_CENTRAL = (1 << LmpFeature.AFH_CLASSIFICATION_CENTRAL) + ENHANCED_DATA_RATE_ESCO_2_MBPS_MODE = (1 << LmpFeature.ENHANCED_DATA_RATE_ESCO_2_MBPS_MODE) + ENHANCED_DATA_RATE_ESCO_3_MBPS_MODE = (1 << LmpFeature.ENHANCED_DATA_RATE_ESCO_3_MBPS_MODE) + LMP_3_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS = (1 << LmpFeature.LMP_3_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS) + EXTENDED_INQUIRY_RESPONSE = (1 << LmpFeature.EXTENDED_INQUIRY_RESPONSE) + SIMULTANEOUS_LE_AND_BR_EDR_TO_SAME_DEVICE_CAPABLE_CONTROLLER = (1 << LmpFeature.SIMULTANEOUS_LE_AND_BR_EDR_TO_SAME_DEVICE_CAPABLE_CONTROLLER) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + SECURE_SIMPLE_PAIRING_CONTROLLER_SUPPORT = (1 << LmpFeature.SECURE_SIMPLE_PAIRING_CONTROLLER_SUPPORT) + ENCAPSULATED_PDU = (1 << LmpFeature.ENCAPSULATED_PDU) + ERRONEOUS_DATA_REPORTING = (1 << LmpFeature.ERRONEOUS_DATA_REPORTING) + NON_FLUSHABLE_PACKET_BOUNDARY_FLAG = (1 << LmpFeature.NON_FLUSHABLE_PACKET_BOUNDARY_FLAG) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + HCI_LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT = (1 << LmpFeature.HCI_LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT) + VARIABLE_INQUIRY_TX_POWER_LEVEL = (1 << LmpFeature.VARIABLE_INQUIRY_TX_POWER_LEVEL) + ENHANCED_POWER_CONTROL = (1 << LmpFeature.ENHANCED_POWER_CONTROL) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + # RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + EXTENDED_FEATURES = (1 << LmpFeature.EXTENDED_FEATURES) + + # Page 1 + SECURE_SIMPLE_PAIRING_HOST_SUPPORT = (1 << LmpFeature.SECURE_SIMPLE_PAIRING_HOST_SUPPORT) + LE_SUPPORTED_HOST = (1 << LmpFeature.LE_SUPPORTED_HOST) + # PREVIOUSLY_USED = (1 << LmpFeature.PREVIOUSLY_USED) + SECURE_CONNECTIONS_HOST_SUPPORT = (1 << LmpFeature.SECURE_CONNECTIONS_HOST_SUPPORT) + + # Page 2 + CONNECTIONLESS_PERIPHERAL_BROADCAST_TRANSMITTER_OPERATION = (1 << LmpFeature.CONNECTIONLESS_PERIPHERAL_BROADCAST_TRANSMITTER_OPERATION) + CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVER_OPERATION = (1 << LmpFeature.CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVER_OPERATION) + SYNCHRONIZATION_TRAIN = (1 << LmpFeature.SYNCHRONIZATION_TRAIN) + SYNCHRONIZATION_SCAN = (1 << LmpFeature.SYNCHRONIZATION_SCAN) + HCI_INQUIRY_RESPONSE_NOTIFICATION_EVENT = (1 << LmpFeature.HCI_INQUIRY_RESPONSE_NOTIFICATION_EVENT) + GENERALIZED_INTERLACED_SCAN = (1 << LmpFeature.GENERALIZED_INTERLACED_SCAN) + COARSE_CLOCK_ADJUSTMENT = (1 << LmpFeature.COARSE_CLOCK_ADJUSTMENT) + RESERVED_FOR_FUTURE_USE = (1 << LmpFeature.RESERVED_FOR_FUTURE_USE) + SECURE_CONNECTIONS_CONTROLLER_SUPPORT = (1 << LmpFeature.SECURE_CONNECTIONS_CONTROLLER_SUPPORT) + PING = (1 << LmpFeature.PING) + SLOT_AVAILABILITY_MASK = (1 << LmpFeature.SLOT_AVAILABILITY_MASK) + TRAIN_NUDGING = (1 << LmpFeature.TRAIN_NUDGING) + # fmt: on # pylint: enable=line-too-long @@ -1379,6 +1380,45 @@ HCI_LE_SUPPORTED_FEATURES_NAMES = { STATUS_SPEC = {'size': 1, 'mapper': lambda x: HCI_Constant.status_name(x)} +class CodecID(enum.IntEnum): + # fmt: off + U_LOG = 0x00 + A_LOG = 0x01 + CVSD = 0x02 + TRANSPARENT = 0x03 + LINEAR_PCM = 0x04 + MSBC = 0x05 + LC3 = 0x06 + G729A = 0x07 + VENDOR_SPECIFIC = 0xFF + + +@dataclasses.dataclass(frozen=True) +class CodingFormat: + codec_id: CodecID + company_id: int = 0 + vendor_specific_codec_id: int = 0 + + @classmethod + def parse_from_bytes(cls, data: bytes, offset: int): + (codec_id, company_id, vendor_specific_codec_id) = struct.unpack_from( + '<BHH', data, offset + ) + return offset + 5, cls( + codec_id=CodecID(codec_id), + company_id=company_id, + vendor_specific_codec_id=vendor_specific_codec_id, + ) + + def to_bytes(self) -> bytes: + return struct.pack( + '<BHH', self.codec_id, self.company_id, self.vendor_specific_codec_id + ) + + def __bytes__(self) -> bytes: + return self.to_bytes() + + # ----------------------------------------------------------------------------- class HCI_Constant: @staticmethod @@ -1474,6 +1514,12 @@ class HCI_Object: # The rest of the bytes field_value = data[offset:] return (field_value, len(field_value)) + if field_type == 'v': + # Variable-length bytes field, with 1-byte length at the beginning + field_length = data[offset] + offset += 1 + field_value = data[offset : offset + field_length] + return (field_value, field_length + 1) if field_type == 1: # 8-bit unsigned return (data[offset], 1) @@ -1578,6 +1624,11 @@ class HCI_Object: raise ValueError('value too large for *-typed field') else: field_bytes = bytes(field_value) + elif field_type == 'v': + # Variable-length bytes field, with 1-byte length at the beginning + field_bytes = bytes(field_value) + field_length = len(field_bytes) + field_bytes = bytes([field_length]) + field_bytes elif isinstance(field_value, (bytes, bytearray)) or hasattr( field_value, 'to_bytes' ): @@ -1792,6 +1843,43 @@ class Address: address_type = data[offset - 1] return Address.parse_address_with_type(data, offset, address_type) + @classmethod + def generate_static_address(cls) -> Address: + '''Generates Random Static Address, with the 2 most significant bits of 0b11. + + See Bluetooth spec, Vol 6, Part B - Table 1.2. + ''' + address_bytes = secrets.token_bytes(6) + address_bytes = address_bytes[:5] + bytes([address_bytes[5] | 0b11000000]) + return Address( + address=address_bytes, address_type=Address.RANDOM_DEVICE_ADDRESS + ) + + @classmethod + def generate_private_address(cls, irk: bytes = b'') -> Address: + '''Generates Random Private MAC Address. + + If IRK is present, a Resolvable Private Address, with the 2 most significant + bits of 0b01 will be generated. Otherwise, a Non-resolvable Private Address, + with the 2 most significant bits of 0b00 will be generated. + + See Bluetooth spec, Vol 6, Part B - Table 1.2. + + Args: + irk: Local Identity Resolving Key(IRK), in little-endian. If not set, a + non-resolvable address will be generated. + ''' + if irk: + prand = crypto.generate_prand() + address_bytes = crypto.ah(irk, prand) + prand + else: + address_bytes = secrets.token_bytes(6) + address_bytes = address_bytes[:5] + bytes([address_bytes[5] & 0b00111111]) + + return Address( + address=address_bytes, address_type=Address.RANDOM_DEVICE_ADDRESS + ) + def __init__( self, address: Union[bytes, str], address_type: int = RANDOM_DEVICE_ADDRESS ): @@ -1885,26 +1973,28 @@ Address.NIL = Address(b"\xff\xff\xff\xff\xff\xff", Address.PUBLIC_DEVICE_ADDRESS Address.ANY = Address(b"\x00\x00\x00\x00\x00\x00", Address.PUBLIC_DEVICE_ADDRESS) Address.ANY_RANDOM = Address(b"\x00\x00\x00\x00\x00\x00", Address.RANDOM_DEVICE_ADDRESS) + # ----------------------------------------------------------------------------- -class OwnAddressType: +class OwnAddressType(enum.IntEnum): PUBLIC = 0 RANDOM = 1 RESOLVABLE_OR_PUBLIC = 2 RESOLVABLE_OR_RANDOM = 3 - TYPE_NAMES = { - PUBLIC: 'PUBLIC', - RANDOM: 'RANDOM', - RESOLVABLE_OR_PUBLIC: 'RESOLVABLE_OR_PUBLIC', - RESOLVABLE_OR_RANDOM: 'RESOLVABLE_OR_RANDOM', - } + @classmethod + def type_spec(cls): + return {'size': 1, 'mapper': lambda x: OwnAddressType(x).name} - @staticmethod - def type_name(type_id): - return name_or_number(OwnAddressType.TYPE_NAMES, type_id) - # pylint: disable-next=unnecessary-lambda - TYPE_SPEC = {'size': 1, 'mapper': lambda x: OwnAddressType.type_name(x)} +# ----------------------------------------------------------------------------- +class LoopbackMode(enum.IntEnum): + DISABLED = 0 + LOCAL = 1 + REMOTE = 2 + + @classmethod + def type_spec(cls): + return {'size': 1, 'mapper': lambda x: LoopbackMode(x).name} # ----------------------------------------------------------------------------- @@ -1925,9 +2015,15 @@ class HCI_Packet: if packet_type == HCI_ACL_DATA_PACKET: return HCI_AclDataPacket.from_bytes(packet) + if packet_type == HCI_SYNCHRONOUS_DATA_PACKET: + return HCI_SynchronousDataPacket.from_bytes(packet) + if packet_type == HCI_EVENT_PACKET: return HCI_Event.from_bytes(packet) + if packet_type == HCI_ISO_DATA_PACKET: + return HCI_IsoDataPacket.from_bytes(packet) + return HCI_CustomPacket(packet) def __init__(self, name): @@ -1960,6 +2056,7 @@ class HCI_Command(HCI_Packet): hci_packet_type = HCI_COMMAND_PACKET command_names: Dict[int, str] = {} command_classes: Dict[int, Type[HCI_Command]] = {} + op_code: int @staticmethod def command(fields=(), return_parameters_fields=()): @@ -2045,7 +2142,11 @@ class HCI_Command(HCI_Packet): return_parameters.fields = cls.return_parameters_fields return return_parameters - def __init__(self, op_code, parameters=None, **kwargs): + def __init__(self, op_code=-1, parameters=None, **kwargs): + # Since the legacy implementation relies on an __init__ injector, typing always + # complains that positional argument op_code is not passed, so here sets a + # default value to allow building derived HCI_Command without op_code. + assert op_code != -1 super().__init__(HCI_Command.command_name(op_code)) if (fields := getattr(self, 'fields', None)) and kwargs: HCI_Object.init_from_fields(self, fields, kwargs) @@ -2297,6 +2398,19 @@ class HCI_Read_Clock_Offset_Command(HCI_Command): @HCI_Command.command( fields=[ ('bd_addr', Address.parse_address), + ('reason', {'size': 1, 'mapper': HCI_Constant.error_name}), + ], +) +class HCI_Reject_Synchronous_Connection_Request_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.1.28 Reject Synchronous Connection Request Command + ''' + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + ('bd_addr', Address.parse_address), ('io_capability', {'size': 1, 'mapper': HCI_Constant.io_capability_name}), ('oob_data_present', 1), ( @@ -2426,14 +2540,14 @@ class HCI_IO_Capability_Request_Negative_Reply_Command(HCI_Command): ('connection_handle', 2), ('transmit_bandwidth', 4), ('receive_bandwidth', 4), - ('transmit_coding_format', 5), - ('receive_coding_format', 5), + ('transmit_coding_format', CodingFormat.parse_from_bytes), + ('receive_coding_format', CodingFormat.parse_from_bytes), ('transmit_codec_frame_size', 2), ('receive_codec_frame_size', 2), ('input_bandwidth', 4), ('output_bandwidth', 4), - ('input_coding_format', 5), - ('output_coding_format', 5), + ('input_coding_format', CodingFormat.parse_from_bytes), + ('output_coding_format', CodingFormat.parse_from_bytes), ('input_coded_data_size', 2), ('output_coded_data_size', 2), ('input_pcm_data_format', 1), @@ -2454,6 +2568,35 @@ class HCI_Enhanced_Setup_Synchronous_Connection_Command(HCI_Command): See Bluetooth spec @ 7.1.45 Enhanced Setup Synchronous Connection Command ''' + class PcmDataFormat(enum.IntEnum): + NA = 0x00 + ONES_COMPLEMENT = 0x01 + TWOS_COMPLEMENT = 0x02 + SIGN_MAGNITUDE = 0x03 + UNSIGNED = 0x04 + + class DataPath(enum.IntEnum): + HCI = 0x00 + PCM = 0x01 + + class RetransmissionEffort(enum.IntEnum): + NO_RETRANSMISSION = 0x00 + OPTIMIZE_FOR_POWER = 0x01 + OPTIMIZE_FOR_QUALITY = 0x02 + DONT_CARE = 0xFF + + class PacketType(enum.IntFlag): + HV1 = 0x0001 + HV2 = 0x0002 + HV3 = 0x0004 + EV3 = 0x0008 + EV4 = 0x0010 + EV5 = 0x0020 + NO_2_EV3 = 0x0040 + NO_3_EV3 = 0x0080 + NO_2_EV5 = 0x0100 + NO_3_EV5 = 0x0200 + # ----------------------------------------------------------------------------- @HCI_Command.command( @@ -2461,14 +2604,14 @@ class HCI_Enhanced_Setup_Synchronous_Connection_Command(HCI_Command): ('bd_addr', Address.parse_address), ('transmit_bandwidth', 4), ('receive_bandwidth', 4), - ('transmit_coding_format', 5), - ('receive_coding_format', 5), + ('transmit_coding_format', CodingFormat.parse_from_bytes), + ('receive_coding_format', CodingFormat.parse_from_bytes), ('transmit_codec_frame_size', 2), ('receive_codec_frame_size', 2), ('input_bandwidth', 4), ('output_bandwidth', 4), - ('input_coding_format', 5), - ('output_coding_format', 5), + ('input_coding_format', CodingFormat.parse_from_bytes), + ('output_coding_format', CodingFormat.parse_from_bytes), ('input_coded_data_size', 2), ('output_coded_data_size', 2), ('input_pcm_data_format', 1), @@ -2685,6 +2828,20 @@ class HCI_Set_Event_Mask_Command(HCI_Command): See Bluetooth spec @ 7.3.1 Set Event Mask Command ''' + @staticmethod + def mask(event_codes: Iterable[int]) -> bytes: + ''' + Compute the event mask value for a list of events. + ''' + # NOTE: this implementation takes advantage of the fact that as of version 5.4 + # of the core specification, the bit number for each event code is equal to one + # less than the event code. + # If future versions of the specification deviate from that, a different + # implementation would be needed. + return sum((1 << event_code - 1) for event_code in event_codes).to_bytes( + 8, 'little' + ) + # ----------------------------------------------------------------------------- @HCI_Command.command() @@ -3094,7 +3251,12 @@ class HCI_Read_Local_Supported_Commands_Command(HCI_Command): # ----------------------------------------------------------------------------- -@HCI_Command.command() +@HCI_Command.command( + return_parameters_fields=[ + ('status', STATUS_SPEC), + ('lmp_features', 8), + ] +) class HCI_Read_Local_Supported_Features_Command(HCI_Command): ''' See Bluetooth spec @ 7.4.3 Read Local Supported Features Command @@ -3181,12 +3343,47 @@ class HCI_Read_Encryption_Key_Size_Command(HCI_Command): # ----------------------------------------------------------------------------- +@HCI_Command.command( + return_parameters_fields=[ + ('status', STATUS_SPEC), + ('loopback_mode', LoopbackMode.type_spec()), + ], +) +class HCI_Read_Loopback_Mode_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.6.1 Read Loopback Mode Command + ''' + + +# ----------------------------------------------------------------------------- +@HCI_Command.command([('loopback_mode', 1)]) +class HCI_Write_Loopback_Mode_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.6.2 Write Loopback Mode Command + ''' + + +# ----------------------------------------------------------------------------- @HCI_Command.command([('le_event_mask', 8)]) class HCI_LE_Set_Event_Mask_Command(HCI_Command): ''' See Bluetooth spec @ 7.8.1 LE Set Event Mask Command ''' + @staticmethod + def mask(event_codes: Iterable[int]) -> bytes: + ''' + Compute the event mask value for a list of events. + ''' + # NOTE: this implementation takes advantage of the fact that as of version 5.4 + # of the core specification, the bit number for each event code is equal to one + # less than the event code. + # If future versions of the specification deviate from that, a different + # implementation would be needed. + return sum((1 << event_code - 1) for event_code in event_codes).to_bytes( + 8, 'little' + ) + # ----------------------------------------------------------------------------- @HCI_Command.command( @@ -3244,7 +3441,7 @@ class HCI_LE_Set_Random_Address_Command(HCI_Command): ), }, ), - ('own_address_type', OwnAddressType.TYPE_SPEC), + ('own_address_type', OwnAddressType.type_spec()), ('peer_address_type', Address.ADDRESS_TYPE_SPEC), ('peer_address', Address.parse_address_preceded_by_type), ('advertising_channel_map', 1), @@ -3337,7 +3534,7 @@ class HCI_LE_Set_Advertising_Enable_Command(HCI_Command): ('le_scan_type', 1), ('le_scan_interval', 2), ('le_scan_window', 2), - ('own_address_type', OwnAddressType.TYPE_SPEC), + ('own_address_type', OwnAddressType.type_spec()), ('scanning_filter_policy', 1), ] ) @@ -3376,7 +3573,7 @@ class HCI_LE_Set_Scan_Enable_Command(HCI_Command): ('initiator_filter_policy', 1), ('peer_address_type', Address.ADDRESS_TYPE_SPEC), ('peer_address', Address.parse_address_preceded_by_type), - ('own_address_type', OwnAddressType.TYPE_SPEC), + ('own_address_type', OwnAddressType.type_spec()), ('connection_interval_min', 2), ('connection_interval_max', 2), ('max_latency', 2), @@ -3765,8 +3962,10 @@ class HCI_LE_Set_Advertising_Set_Random_Address_Command(HCI_Command): 'advertising_event_properties', { 'size': 2, - 'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Parameters_Command.advertising_properties_string( - x + 'mapper': lambda x: str( + HCI_LE_Set_Extended_Advertising_Parameters_Command.AdvertisingProperties( + x + ) ), }, ), @@ -3776,12 +3975,12 @@ class HCI_LE_Set_Advertising_Set_Random_Address_Command(HCI_Command): 'primary_advertising_channel_map', { 'size': 1, - 'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Parameters_Command.channel_map_string( - x + 'mapper': lambda x: str( + HCI_LE_Set_Extended_Advertising_Parameters_Command.ChannelMap(x) ), }, ), - ('own_address_type', OwnAddressType.TYPE_SPEC), + ('own_address_type', OwnAddressType.type_spec()), ('peer_address_type', Address.ADDRESS_TYPE_SPEC), ('peer_address', Address.parse_address_preceded_by_type), ('advertising_filter_policy', 1), @@ -3792,45 +3991,43 @@ class HCI_LE_Set_Advertising_Set_Random_Address_Command(HCI_Command): ('advertising_sid', 1), ('scan_request_notification_enable', 1), ], - return_parameters_fields=[('status', STATUS_SPEC), ('selected_tx__power', 1)], + return_parameters_fields=[('status', STATUS_SPEC), ('selected_tx_power', 1)], ) class HCI_LE_Set_Extended_Advertising_Parameters_Command(HCI_Command): ''' See Bluetooth spec @ 7.8.53 LE Set Extended Advertising Parameters Command ''' - CONNECTABLE_ADVERTISING = 0 - SCANNABLE_ADVERTISING = 1 - DIRECTED_ADVERTISING = 2 - HIGH_DUTY_CYCLE_DIRECTED_CONNECTABLE_ADVERTISING = 3 - USE_LEGACY_ADVERTISING_PDUS = 4 - ANONYMOUS_ADVERTISING = 5 - INCLUDE_TX_POWER = 6 - - ADVERTISING_PROPERTIES_NAMES = ( - 'CONNECTABLE_ADVERTISING', - 'SCANNABLE_ADVERTISING', - 'DIRECTED_ADVERTISING', - 'HIGH_DUTY_CYCLE_DIRECTED_CONNECTABLE_ADVERTISING', - 'USE_LEGACY_ADVERTISING_PDUS', - 'ANONYMOUS_ADVERTISING', - 'INCLUDE_TX_POWER', - ) + TX_POWER_NO_PREFERENCE = 0x7F + SHOULD_NOT_FRAGMENT = 0x01 - CHANNEL_37 = 0 - CHANNEL_38 = 1 - CHANNEL_39 = 2 + class AdvertisingProperties(enum.IntFlag): + CONNECTABLE_ADVERTISING = 1 << 0 + SCANNABLE_ADVERTISING = 1 << 1 + DIRECTED_ADVERTISING = 1 << 2 + HIGH_DUTY_CYCLE_DIRECTED_CONNECTABLE_ADVERTISING = 1 << 3 + USE_LEGACY_ADVERTISING_PDUS = 1 << 4 + ANONYMOUS_ADVERTISING = 1 << 5 + INCLUDE_TX_POWER = 1 << 6 - CHANNEL_NAMES = ('37', '38', '39') + def __str__(self) -> str: + return '|'.join( + flag.name + for flag in HCI_LE_Set_Extended_Advertising_Parameters_Command.AdvertisingProperties + if self.value & flag.value and flag.name is not None + ) - @classmethod - def advertising_properties_string(cls, properties): - # pylint: disable=line-too-long - return f'[{",".join(bit_flags_to_strings(properties, cls.ADVERTISING_PROPERTIES_NAMES))}]' + class ChannelMap(enum.IntFlag): + CHANNEL_37 = 1 << 0 + CHANNEL_38 = 1 << 1 + CHANNEL_39 = 1 << 2 - @classmethod - def channel_map_string(cls, channel_map): - return f'[{",".join(bit_flags_to_strings(channel_map, cls.CHANNEL_NAMES))}]' + def __str__(self) -> str: + return '|'.join( + flag.name + for flag in HCI_LE_Set_Extended_Advertising_Parameters_Command.ChannelMap + if self.value & flag.value and flag.name is not None + ) # ----------------------------------------------------------------------------- @@ -3842,9 +4039,9 @@ class HCI_LE_Set_Extended_Advertising_Parameters_Command(HCI_Command): 'operation', { 'size': 1, - 'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.operation_name( + 'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.Operation( x - ), + ).name, }, ), ('fragment_preference', 1), @@ -3862,23 +4059,12 @@ class HCI_LE_Set_Extended_Advertising_Data_Command(HCI_Command): See Bluetooth spec @ 7.8.54 LE Set Extended Advertising Data Command ''' - INTERMEDIATE_FRAGMENT = 0x00 - FIRST_FRAGMENT = 0x01 - LAST_FRAGMENT = 0x02 - COMPLETE_DATA = 0x03 - UNCHANGED_DATA = 0x04 - - OPERATION_NAMES = { - INTERMEDIATE_FRAGMENT: 'INTERMEDIATE_FRAGMENT', - FIRST_FRAGMENT: 'FIRST_FRAGMENT', - LAST_FRAGMENT: 'LAST_FRAGMENT', - COMPLETE_DATA: 'COMPLETE_DATA', - UNCHANGED_DATA: 'UNCHANGED_DATA', - } - - @classmethod - def operation_name(cls, operation): - return name_or_number(cls.OPERATION_NAMES, operation) + class Operation(enum.IntEnum): + INTERMEDIATE_FRAGMENT = 0x00 + FIRST_FRAGMENT = 0x01 + LAST_FRAGMENT = 0x02 + COMPLETE_DATA = 0x03 + UNCHANGED_DATA = 0x04 # ----------------------------------------------------------------------------- @@ -3890,9 +4076,9 @@ class HCI_LE_Set_Extended_Advertising_Data_Command(HCI_Command): 'operation', { 'size': 1, - 'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.operation_name( + 'mapper': lambda x: HCI_LE_Set_Extended_Advertising_Data_Command.Operation( x - ), + ).name, }, ), ('fragment_preference', 1), @@ -3910,22 +4096,6 @@ class HCI_LE_Set_Extended_Scan_Response_Data_Command(HCI_Command): See Bluetooth spec @ 7.8.55 LE Set Extended Scan Response Data Command ''' - INTERMEDIATE_FRAGMENT = 0x00 - FIRST_FRAGMENT = 0x01 - LAST_FRAGMENT = 0x02 - COMPLETE_DATA = 0x03 - - OPERATION_NAMES = { - INTERMEDIATE_FRAGMENT: 'INTERMEDIATE_FRAGMENT', - FIRST_FRAGMENT: 'FIRST_FRAGMENT', - LAST_FRAGMENT: 'LAST_FRAGMENT', - COMPLETE_DATA: 'COMPLETE_DATA', - } - - @classmethod - def operation_name(cls, operation): - return name_or_number(cls.OPERATION_NAMES, operation) - # ----------------------------------------------------------------------------- @HCI_Command.command( @@ -4075,7 +4245,7 @@ class HCI_LE_Set_Extended_Scan_Parameters_Command(HCI_Command): ('scanning_filter_policy:', self.scanning_filter_policy), ('scanning_phys: ', ','.join(scanning_phys_strs)), ] - for (i, scanning_phy_str) in enumerate(scanning_phys_strs): + for i, scanning_phy_str in enumerate(scanning_phys_strs): fields.append( ( f'{scanning_phy_str}.scan_type: ', @@ -4209,7 +4379,7 @@ class HCI_LE_Extended_Create_Connection_Command(HCI_Command): ('initiator_filter_policy:', self.initiator_filter_policy), ( 'own_address_type: ', - OwnAddressType.type_name(self.own_address_type), + OwnAddressType(self.own_address_type).name, ), ( 'peer_address_type: ', @@ -4218,7 +4388,7 @@ class HCI_LE_Extended_Create_Connection_Command(HCI_Command): ('peer_address: ', str(self.peer_address)), ('initiating_phys: ', ','.join(initiating_phys_strs)), ] - for (i, initiating_phys_str) in enumerate(initiating_phys_strs): + for i, initiating_phys_str in enumerate(initiating_phys_strs): fields.append( ( f'{initiating_phys_str}.scan_interval: ', @@ -4324,6 +4494,166 @@ class HCI_LE_Set_Host_Feature_Command(HCI_Command): # ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + ('cig_id', 1), + ('sdu_interval_c_to_p', 3), + ('sdu_interval_p_to_c', 3), + ('worst_case_sca', 1), + ('packing', 1), + ('framing', 1), + ('max_transport_latency_c_to_p', 2), + ('max_transport_latency_p_to_c', 2), + [ + ('cis_id', 1), + ('max_sdu_c_to_p', 2), + ('max_sdu_p_to_c', 2), + ('phy_c_to_p', 1), + ('phy_p_to_c', 1), + ('rtn_c_to_p', 1), + ('rtn_p_to_c', 1), + ], + ], + return_parameters_fields=[ + ('status', STATUS_SPEC), + ('cig_id', 1), + [('connection_handle', 2)], + ], +) +class HCI_LE_Set_CIG_Parameters_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.97 LE Set CIG Parameters Command + ''' + + cig_id: int + sdu_interval_c_to_p: int + sdu_interval_p_to_c: int + worst_case_sca: int + packing: int + framing: int + max_transport_latency_c_to_p: int + max_transport_latency_p_to_c: int + cis_id: List[int] + max_sdu_c_to_p: List[int] + max_sdu_p_to_c: List[int] + phy_c_to_p: List[int] + phy_p_to_c: List[int] + rtn_c_to_p: List[int] + rtn_p_to_c: List[int] + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + [ + ('cis_connection_handle', 2), + ('acl_connection_handle', 2), + ], + ], +) +class HCI_LE_Create_CIS_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.99 LE Create CIS command + ''' + + cis_connection_handle: List[int] + acl_connection_handle: List[int] + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[('cig_id', 1)], + return_parameters_fields=[('status', STATUS_SPEC), ('cig_id', 1)], +) +class HCI_LE_Remove_CIG_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.100 LE Remove CIG command + ''' + + cig_id: int + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[('connection_handle', 2)], +) +class HCI_LE_Accept_CIS_Request_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.101 LE Accept CIS Request command + ''' + + connection_handle: int + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + ('connection_handle', 2), + ('reason', {'size': 1, 'mapper': HCI_Constant.error_name}), + ], +) +class HCI_LE_Reject_CIS_Request_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.102 LE Reject CIS Request command + ''' + + connection_handle: int + reason: int + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + ('connection_handle', 2), + ('data_path_direction', 1), + ('data_path_id', 1), + ('codec_id', CodingFormat.parse_from_bytes), + ('controller_delay', 3), + ('codec_configuration', 'v'), + ], + return_parameters_fields=[ + ('status', STATUS_SPEC), + ('connection_handle', 2), + ], +) +class HCI_LE_Setup_ISO_Data_Path_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.109 LE Setup ISO Data Path command + ''' + + class Direction(enum.IntEnum): + HOST_TO_CONTROLLER = 0x00 + CONTROLLER_TO_HOST = 0x01 + + connection_handle: int + data_path_direction: int + data_path_id: int + codec_id: CodingFormat + controller_delay: int + codec_configuration: bytes + + +# ----------------------------------------------------------------------------- +@HCI_Command.command( + fields=[ + ('connection_handle', 2), + ('data_path_direction', 1), + ], + return_parameters_fields=[ + ('status', STATUS_SPEC), + ('connection_handle', 2), + ], +) +class HCI_LE_Remove_ISO_Data_Path_Command(HCI_Command): + ''' + See Bluetooth spec @ 7.8.110 LE Remove ISO Data Path command + ''' + + connection_handle: int + data_path_direction: int + + +# ----------------------------------------------------------------------------- # HCI Events # ----------------------------------------------------------------------------- class HCI_Event(HCI_Packet): @@ -4431,7 +4761,11 @@ class HCI_Event(HCI_Packet): HCI_Object.init_from_bytes(self, parameters, 0, fields) return self - def __init__(self, event_code, parameters=None, **kwargs): + def __init__(self, event_code=-1, parameters=None, **kwargs): + # Since the legacy implementation relies on an __init__ injector, typing always + # complains that positional argument event_code is not passed, so here sets a + # default value to allow building derived HCI_Event without event_code. + assert event_code != -1 super().__init__(HCI_Event.event_name(event_code)) if (fields := getattr(self, 'fields', None)) and kwargs: HCI_Object.init_from_fields(self, fields, kwargs) @@ -4525,7 +4859,8 @@ class HCI_Extended_Event(HCI_Event): HCI_Object.init_from_bytes(self, parameters, 1, fields) return self - def __init__(self, subevent_code, parameters, **kwargs): + def __init__(self, subevent_code=None, parameters=None, **kwargs): + assert subevent_code is not None self.subevent_code = subevent_code if parameters is None and (fields := getattr(self, 'fields', None)) and kwargs: parameters = bytes([subevent_code]) + HCI_Object.dict_to_bytes( @@ -4935,6 +5270,21 @@ HCI_LE_Meta_Event.subevent_classes[ # ----------------------------------------------------------------------------- +@HCI_LE_Meta_Event.event( + [ + ('status', 1), + ('advertising_handle', 1), + ('connection_handle', 2), + ('num_completed_extended_advertising_events', 1), + ] +) +class HCI_LE_Advertising_Set_Terminated_Event(HCI_LE_Meta_Event): + ''' + See Bluetooth spec @ 7.7.65.18 LE Advertising Set Terminated Event + ''' + + +# ----------------------------------------------------------------------------- @HCI_LE_Meta_Event.event([('connection_handle', 2), ('channel_selection_algorithm', 1)]) class HCI_LE_Channel_Selection_Algorithm_Event(HCI_LE_Meta_Event): ''' @@ -4943,6 +5293,48 @@ class HCI_LE_Channel_Selection_Algorithm_Event(HCI_LE_Meta_Event): # ----------------------------------------------------------------------------- +@HCI_LE_Meta_Event.event( + [ + ('status', STATUS_SPEC), + ('connection_handle', 2), + ('cig_sync_delay', 3), + ('cis_sync_delay', 3), + ('transport_latency_c_to_p', 3), + ('transport_latency_p_to_c', 3), + ('phy_c_to_p', 1), + ('phy_p_to_c', 1), + ('nse', 1), + ('bn_c_to_p', 1), + ('bn_p_to_c', 1), + ('ft_c_to_p', 1), + ('ft_p_to_c', 1), + ('max_pdu_c_to_p', 2), + ('max_pdu_p_to_c', 2), + ('iso_interval', 2), + ] +) +class HCI_LE_CIS_Established_Event(HCI_LE_Meta_Event): + ''' + See Bluetooth spec @ 7.7.65.25 LE CIS Established Event + ''' + + +# ----------------------------------------------------------------------------- +@HCI_LE_Meta_Event.event( + [ + ('acl_connection_handle', 2), + ('cis_connection_handle', 2), + ('cig_id', 1), + ('cis_id', 1), + ] +) +class HCI_LE_CIS_Request_Event(HCI_LE_Meta_Event): + ''' + See Bluetooth spec @ 7.7.65.26 LE CIS Request Event + ''' + + +# ----------------------------------------------------------------------------- @HCI_Event.event([('status', STATUS_SPEC)]) class HCI_Inquiry_Complete_Event(HCI_Event): ''' @@ -5068,6 +5460,10 @@ class HCI_Disconnection_Complete_Event(HCI_Event): See Bluetooth spec @ 7.7.5 Disconnection Complete Event ''' + status: int + connection_handle: int + reason: int + # ----------------------------------------------------------------------------- @HCI_Event.event([('status', STATUS_SPEC), ('connection_handle', 2)]) @@ -5739,6 +6135,168 @@ class HCI_AclDataPacket(HCI_Packet): # ----------------------------------------------------------------------------- +class HCI_SynchronousDataPacket(HCI_Packet): + ''' + See Bluetooth spec @ 5.4.3 HCI SCO Data Packets + ''' + + hci_packet_type = HCI_SYNCHRONOUS_DATA_PACKET + + @staticmethod + def from_bytes(packet: bytes) -> HCI_SynchronousDataPacket: + # Read the header + h, data_total_length = struct.unpack_from('<HB', packet, 1) + connection_handle = h & 0xFFF + packet_status = (h >> 12) & 0b11 + data = packet[4:] + if len(data) != data_total_length: + raise ValueError( + f'invalid packet length {len(data)} != {data_total_length}' + ) + return HCI_SynchronousDataPacket( + connection_handle, packet_status, data_total_length, data + ) + + def to_bytes(self) -> bytes: + h = (self.packet_status << 12) | self.connection_handle + return ( + struct.pack('<BHB', HCI_SYNCHRONOUS_DATA_PACKET, h, self.data_total_length) + + self.data + ) + + def __init__( + self, + connection_handle: int, + packet_status: int, + data_total_length: int, + data: bytes, + ) -> None: + self.connection_handle = connection_handle + self.packet_status = packet_status + self.data_total_length = data_total_length + self.data = data + + def __bytes__(self) -> bytes: + return self.to_bytes() + + def __str__(self) -> str: + return ( + f'{color("SCO", "blue")}: ' + f'handle=0x{self.connection_handle:04x}, ' + f'ps={self.packet_status}, ' + f'data_total_length={self.data_total_length}, ' + f'data={self.data.hex()}' + ) + + +# ----------------------------------------------------------------------------- +class HCI_IsoDataPacket(HCI_Packet): + ''' + See Bluetooth spec @ 5.4.5 HCI ISO Data Packets + ''' + + hci_packet_type = HCI_ISO_DATA_PACKET + + @staticmethod + def from_bytes(packet: bytes) -> HCI_IsoDataPacket: + time_stamp: Optional[int] = None + packet_sequence_number: Optional[int] = None + iso_sdu_length: Optional[int] = None + packet_status_flag: Optional[int] = None + + pos = 1 + pdu_info, data_total_length = struct.unpack_from('<HH', packet, pos) + connection_handle = pdu_info & 0xFFF + pb_flag = (pdu_info >> 12) & 0b11 + ts_flag = (pdu_info >> 14) & 0b01 + pos += 4 + + # pb_flag in (0b00, 0b10) but faster + should_include_sdu_info = not (pb_flag & 0b01) + + if ts_flag: + if not should_include_sdu_info: + logger.warning(f'Timestamp included when pb_flag={bin(pb_flag)}') + time_stamp, *_ = struct.unpack_from('<I', packet, pos) + pos += 4 + + if should_include_sdu_info: + packet_sequence_number, sdu_info = struct.unpack_from('<HH', packet, pos) + iso_sdu_length = sdu_info & 0xFFF + packet_status_flag = sdu_info >> 14 + pos += 4 + + iso_sdu_fragment = packet[pos:] + return HCI_IsoDataPacket( + connection_handle=connection_handle, + pb_flag=pb_flag, + ts_flag=ts_flag, + data_total_length=data_total_length, + time_stamp=time_stamp, + packet_sequence_number=packet_sequence_number, + iso_sdu_length=iso_sdu_length, + packet_status_flag=packet_status_flag, + iso_sdu_fragment=iso_sdu_fragment, + ) + + def __init__( + self, + connection_handle: int, + pb_flag: int, + ts_flag: int, + data_total_length: int, + time_stamp: Optional[int], + packet_sequence_number: Optional[int], + iso_sdu_length: Optional[int], + packet_status_flag: Optional[int], + iso_sdu_fragment: bytes, + ) -> None: + self.connection_handle = connection_handle + self.pb_flag = pb_flag + self.ts_flag = ts_flag + self.data_total_length = data_total_length + self.time_stamp = time_stamp + self.packet_sequence_number = packet_sequence_number + self.iso_sdu_length = iso_sdu_length + self.packet_status_flag = packet_status_flag + self.iso_sdu_fragment = iso_sdu_fragment + + def __bytes__(self) -> bytes: + return self.to_bytes() + + def to_bytes(self) -> bytes: + fmt = '<BHH' + args = [ + HCI_ISO_DATA_PACKET, + self.ts_flag << 14 | self.pb_flag << 12 | self.connection_handle, + self.data_total_length, + ] + if self.time_stamp is not None: + fmt += 'I' + args.append(self.time_stamp) + if ( + self.packet_sequence_number is not None + and self.iso_sdu_length is not None + and self.packet_status_flag is not None + ): + fmt += 'HH' + args += [ + self.packet_sequence_number, + self.iso_sdu_length | self.packet_status_flag << 14, + ] + return struct.pack(fmt, *args) + self.iso_sdu_fragment + + def __str__(self) -> str: + return ( + f'{color("ISO", "blue")}: ' + f'handle=0x{self.connection_handle:04x}, ' + f'ps={self.packet_status_flag}, ' + f'data_total_length={self.data_total_length}, ' + f'sdu={self.iso_sdu_fragment.hex()}' + ) + + +# ----------------------------------------------------------------------------- class HCI_AclDataPacketAssembler: current_data: Optional[bytes] @@ -5771,7 +6329,7 @@ class HCI_AclDataPacketAssembler: self.current_data = None self.l2cap_pdu_length = 0 else: - # Sanity check + # Compliance check if len(self.current_data) > self.l2cap_pdu_length + 4: logger.warning('!!! ACL data exceeds L2CAP PDU') self.current_data = None |