Source code for max_ble_hci.packet_codes

#! /usr/bin/env python3
###############################################################################
#
#
# Copyright (C) 2023 Maxim Integrated Products, Inc., All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
# OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of Maxim Integrated
# Products, Inc. shall not be used except as stated in the Maxim Integrated
# Products, Inc. Branding Policy.
#
# The mere transfer of this software does not imply any licenses
# of trade secrets, proprietary technology, copyrights, patents,
# trademarks, maskwork rights, or any other form of intellectual
# property whatsoever. Maxim Integrated Products, Inc. retains all
# ownership rights.
#
##############################################################################
#
# Copyright 2023 Analog Devices, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
"""Contains definitions for BLE standard codes utilized in HCI packet creation/parsing."""
from __future__ import annotations

from enum import Enum, Flag
from typing import List, Union


[docs]class EventCode(Enum): """Supported HCI Event Codes""" DICON_COMPLETE = 0x05 """Disconnection complete event.""" ENC_CHANGE = 0x08 """Encryption change event.""" READ_REMOTE_VERSION_INFO_COMPLETE = 0x0C """Read remote version information complete event.""" COMMAND_COMPLETE = 0x0E """Command complete event.""" COMMAND_STATUS = 0x0F """Command status event.""" HARDWARE_ERROR = 0x10 """Hardware error event.""" NUM_COMPLETED_PACKETS = 0x13 """Number of completed packets event.""" DATA_BUFF_OVERFLOW = 0x1A """Data buffer overflow event.""" ENC_KEY_REFRESH_COMPLETE = 0x30 """Encryption key refresh complete event.""" LE_META = 0x3E """LE meta event.""" AUTH_PAYLOAD_TIMEOUT_EXPIRED = 0x57 """Authenticated payload timeout expired event.""" VENDOR_SPEC = 0xFF """Vendor specific event."""
def _get_full_mask(mask_type: Union[EventMask, EventMaskLE]): full_mask = None for flag in mask_type: if full_mask is None: full_mask = flag full_mask |= flag return full_mask
[docs]class EventMask(Flag): """Controller Event Mask""" INQUIRY_COMPLETE = 1 << 0 INQUIRY_RESULT = 1 << 1 CONNECTION_COMPLETE = 1 << 2 CONNECTION_REQUEST = 1 << 3 DISCONNECTION_COMPLETE = 1 << 4 AUTHENTICATION_COMPLETE = 1 << 5 REMOTE_NAME_REQUEST_COMPLETE = 1 << 6 ENCRYPTION_CHANGE = 1 << 7 CHANGE_CONNECTION_LINK_KEY_COMPLETE = 1 << 8 LINK_KEY_TYPE_CHANGED = 1 << 9 READ_REMOTE_SUPPORTED_FEATURES_COMPLETE = 1 << 10 READ_REMOTE_VERSION_INFORMATION_COMPLETE = 1 << 11 QOS_SETUP_COMPLETE = 1 << 12 HARDWARE_ERROR = 1 << 15 FLUSH_OCCURRED = 1 << 16 ROLE_CHANGE = 1 << 17 MODE_CHANGE = 1 << 19 RETURN_LINK_KEYS = 1 << 20 PIN_CODE_REQUEST = 1 << 21 LINK_KEY_REQUEST = 1 << 22 LINK_KEY_NOTIFICATION = 1 << 23 LOOPBACK_COMMAND = 1 << 24 DATA_BUFFER_OVERFLOW = 1 << 25 MAX_SLOTS_CHANGE = 1 << 26 READ_CLOCK_OFFSET_COMPLETE = 1 << 27 CONNECTION_PACKET_TYPE_CHANGED = 1 << 28 QOS_VIOLATION = 1 << 29 PREVIOUSLY_USED = 1 << 30 PAGE_SCAN_REPETITION_MODE_CHANGE = 1 << 31 FLOW_SPECIFICATION_COMPLETE = 1 << 32 INQUIRY_RESULT_WITH_RSSI = 1 << 33 READ_REMOTE_EXTENDED_FEATURES_COMPLETE = 1 << 34 SYNCHRONOUS_CONNECTION_COMPLETE = 1 << 43 SYNCHRONOUS_CONNECTION_CHANGED = 1 << 44 SNIFF_SUBRATING = 1 << 45 EXTENDED_INQUIRY_RESULT = 1 << 46 ENCRYPTION_KEY_REFRESH_COMPLETE = 1 << 47 IO_CAPABILITY_REQUEST = 1 << 48 IO_CAPABILITY_RESPONSE = 1 << 49 USER_CONFIRMATION_REQUEST = 1 << 50 USER_PASSKEY_REQUEST = 1 << 51 REMOTE_OOB_DATA_REQUEST = 1 << 52 SIMPLE_PAIRING_COMPLETE = 1 << 53 LINK_SUPERVISION_TIMEOUT_CHANGED = 1 << 55 ENHANCED_FLUSH_COMPLETE = 1 << 56 USER_PASSKEY_NOTIFICATION = 1 << 58 KEYPRESS_NOTIFICATION = 1 << 59 REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION = 1 << 60 LE_META = 1 << 61
[docs] @staticmethod def get_full_mask(): """Get full event mask Returns ------- EventMask All events in event mask """ return _get_full_mask(EventMask)
[docs] @staticmethod def from_int(mask: int) -> EventMask: """From integer mask to EventMask class Parameters ---------- mask : int Interger mask. Returns ------- EventMask EventMask class """ clear_mask = EventMask.get_full_mask() return EventMask(mask & clear_mask.value)
[docs] def as_str_list(self) -> List[str]: """Get list of event mask strings Returns ------- List[str] List of event mask strings """ flags = [flag.name for flag in EventMask if flag in self] return flags
[docs]class EventMaskPage2(Flag): """Controller Event Mask""" NUM_CMPLT_DAT_BLOCKS = 1 << 8 TRIG_CLK_CAPTURE = 1 << 14 SYNC_TRAIN_CMPLT = 1 << 15 SYNC_TRAIN_RECEIVED = 1 << 16 CONNECTIONLESS_PERIPH_BROADCAST = 1 << 17 CONNECTIONLESS_PERIPH_TIMEOUT = 1 << 18 TRUNCATED_PAGE_CMPLT = 1 << 19 PERIPH_PAGE_RESP_TIMEOUT = 1 << 20 CONNECTIONLESS_PERIPH_BROADCAST_CH_MAP_CHANGE = 1 << 21 INQUIRY_RESP_NOTIF = 1 << 22 AUTH_PAYLOAD_TIMEOUT_EXPIRED = 1 << 23 SAM_STATUS_CHANGED = 1 << 24 ENC_CHANGED = 1 << 25
[docs] @staticmethod def get_full_mask() -> EventMaskPage2: """Get full event mask page 2 Returns ------- EventMaskPage2 Full event mask page 2 """ return _get_full_mask(EventMaskPage2)
[docs] @staticmethod def from_int(mask: int) -> EventMaskPage2: """From integer mask to EventMask class Parameters ---------- mask : int Interger mask. Returns ------- EventMask EventMask class """ clear_mask = EventMask.get_full_mask() return EventMask(mask & clear_mask.value)
[docs] def as_str_list(self) -> List[str]: """Get list of event mask strings Returns ------- List[str] List of event mask strings """ flags = [flag.name for flag in EventMaskPage2 if flag in self] return flags
[docs]class EventMaskLE(Flag): """LE Event Mask""" CONNECTION_COMPLETE = 1 << 0 ADV_REPORT = 1 << 1 CONN_UPDATE_COMPLETE = 1 << 2 READ_REMOTE_FEAT_CMPLT = 1 << 3 LTK_REQUEST = 1 << 4 REMOTE_CONN_PARAM_REQ = 1 << 5 DATA_LEN_CHANGE = 1 << 6 READ_LOCAL_P256_PUB_KEY_CMPLT = 1 << 7 GEN_DHKEY_CMPLT = 1 << 8 ENHANCED_CONNECTION_COMPLETE = 1 << 9 DIRECTED_ADV_REPORT = 1 << 10 PHY_UPDATE_COMPLETE = 1 << 11 EXTENDED_ADVERTISING_REPORT = 1 << 12 PERIODIC_ADV_SYNC_EST = 1 << 13 PERIODIC_ADV_REPORT = 1 << 14 PERIODIC_ADV_SYNC_LOST = 1 << 15 SCAN_TIMEOUT = 1 << 16 ADVERTISING_SET_TERMINATED = 1 << 17 SCAN_REQUEST_RECEIVED = 1 << 18 CHANNEL_SELECTION_ALGORITHM = 1 << 19 CONNECTIONLESS_IQ_REPORT = 1 << 20 CONNECTION_IQ_REPORT = 1 << 21 CTE_REQUEST_FAILED = 1 << 22 PERIODIC_ADV_SYNC_XFER_LOST = 1 << 23 CIS_ESTABLISHED = 1 << 24 CIS_REQUEST = 1 << 25 CREATE_BIG_COMPLETE = 1 << 26 TERMINATE_BIG_COMPLETE = 1 << 27 BIG_SYNC_ESTABLISHED = 1 << 28 BIG_SYNC_LOST = 1 << 29 REQUEST_PEER_SCA_COMPLETE = 1 << 30 PATH_LOSS_THRESHOLD = 1 << 31 TX_POWER_REPORTING = 1 << 32 BIG_INFO_ADV_REPORT = 1 << 33 SUBRATE_CHANGE = 1 << 34
[docs] @staticmethod def get_full_mask() -> EventMaskLE: """Get full LE Event mask Returns ------- EventMaskLE Event mask with all events """ return _get_full_mask(EventMaskLE)
[docs] def as_str_list(self) -> List[str]: """List of flags as strings Returns ------- List[str] List of flags as string """ flags = [flag.name for flag in EventMaskLE if flag in self] return flags
[docs] @staticmethod def from_int(mask: int) -> EventMaskLE: """From int to EventMaskLE class Parameters ---------- mask : int Integer mask Returns ------- EventMaskLE EventMaskLE class """ clear_mask = EventMaskLE.get_full_mask() return EventMaskLE(mask & clear_mask.value)
[docs]class EventSubcode(Enum): """Supported LE Meta event subcodes.""" CONNECTION_CMPLT = 0x1 """Connection complete event.""" ADVERTISING_REPORT = 0x2 """Advertising report event.""" CONNECTION_UPDATE = 0x3 """Connection update complete event.""" READ_REMOTE_FEATURES_COMPLETE = 0x4 """Read remote feature complete event.""" LTK_REQUEST = 0x5 """Long term key request event.""" REMOTE_CONNECTION_PARAMETER_REQ = 0x6 """Remote connection parameter request event.""" DATA_LENGTH_CHANGE = 0x7 """Data length change event.""" READ_LOCAL_P256_PUB_KEY_CMPLT = 0x8 """Read local P-256 public key complete event.""" GENERATE_DHKEY_CMPLT = 0x9 """Generate DHKey complete event.""" ENHANCED_CONNECTION_CMPLT = 0xA """Enhanced connection complete event.""" DIRECTED_ADVERTISIING_REPORT = 0xB """Directed advertising report event.""" PHY_UPDATE_CMPLT = 0xC """PHY update complete event.""" EXTENDED_ADVERTISING_REPORT = 0xD """Extended advertising report event.""" PERIODIC_ADVERTISING_SYNC_ESTABLISHED = 0xE """Periodic advertising sync established event.""" PERIODIC_ADVERTISING_REPORT = 0xF """Periodic advertising report event.""" PERIODIC_ADVERTISING_SYNC_LOST = 0x10 """Periodic advertising sync lost event.""" SCAN_TIMEOUT = 0x11 """Scan timeout event.""" ADVERTISING_SET_TERMINATED = 0x12 """Advertising set terminated event.""" SCAN_REQUEST_RECEIVED = 0x13 """Scan request received event.""" CHANNEL_SELECTION_ALGORITHM = 0x14 """Channel selection algorithm event.""" CONNECTIONLESS_IQ_REPORT = 0x15 """Connectionless IQ report event.""" CONNECTION_IQ_REPORT = 0x16 """Connection IQ report event.""" CTE_REQUEST_FAILED = 0x17 """CTE request failed event.""" PERIODIC_ADVERTISING_SYNC_TRANSER_RECEIVED = 0x18 """Periodic advertising sync transfer received event.""" CIS_ESTABLISHED = 0x19 """CIS established event.""" CIS_REQUEST = 0x1A """CIS request event.""" CREATE_BIG_CMPLT = 0x1B """Create BIG complete event.""" TERMINATE_BIG_CMPLT = 0x1C """Terminate BIG complete event.""" BIG_SYNC_EST = 0x1D """BIG sync established event.""" BIG_SYNC_LOST = 0x1E """BIG sync list event.""" REQUEST_PEER_SCA_CMPLT = 0x1F """Request peeer SCA complete event.""" PATH_LOSS_THRESHOLD = 0x20 """Path loss threshold event.""" TRANSMIT_POWER_REPORTING = 0x21 """Transmit power reporting event.""" BIGINFO_ADVERTISING_REPORT = 0x22 """BIGInfo advertising report event."""
[docs]class StatusCode(Enum): """BLE-defined status codes.""" SUCCESS = 0x00 """Success.""" ERROR_CODE_UNKNOWN_HCI_CMD = 0x01 """Unknown HCI command error.""" ERROR_CODE_UNKNOWN_CONN_ID = 0x2 """Unknown connection identifier.""" ERROR_CODE_HW_FAILURE = 0x03 """Hardware failure.""" ERROR_CODE_PAGE_TIMEOUT = 0x04 """Page timeout.""" ERROR_CODE_AUTH_FAILURE = 0x05 """Authentication failure.""" ERROR_CODE_PIN_KEY_MISSING = 0x06 """PIN or key missing.""" ERROR_CODE_MEM_CAP_EXCEEDED = 0x07 """Memory capacity exceeded.""" ERROR_CODE_CONN_TIMEOUT = 0x08 """Connection timeout.""" ERROR_CODE_CONN_LIMIT_EXCEEDED = 0x09 """Connection limit exceeded.""" ERROR_CODE_SYNCH_CONN_LIMIT_EXCEEDED = 0x0A """Synchronous connection limit to a device exceeded.""" ERROR_CODE_ACL_CONN_ALREADY_EXISTS = 0x0B """Connection already exists.""" ERROR_CODE_CMD_DISALLOWED = 0x0C """Command disallowed.""" ERROR_CODE_CONN_REJ_LIMITED_RESOURCES = 0x0D """connection rejection due to limited resources.""" ERROR_CODE_CONN_REJECTED_SECURITY_REASONS = 0x0E """Connection rejected due to security reasons.""" ERROR_CODE_CONN_REJECTED_UNACCEPTABLE_BDADDR = 0x0F """Connection rejected dur to unacceptable BD address.""" ERROR_CODE_CONN_ACCEPT_TIMEOUT_EXCEEDED = 0x10 """Connection accept timeout exceeded.""" ERROR_CODE_UNSUPPORTED_FEATURE_PARAM_VALUE = 0x11 """Unsupported feature or parameter value.""" ERROR_CODE_INVALID_HCI_CMD_PARAMS = 0x12 """Invalid HCI command parameters.""" ERROR_CODE_REMOTE_USER_TERM_CONN = 0x13 """Remote user terminated connection.""" ERROR_CODE_REMOTE_DEVICE_TERM_CONN_LOW_RESOURCES = 0x14 """Remote device terminated connection due to low resources.""" ERROR_CODE_REMOTE_DEVICE_TERM_CONN_POWER_OFF = 0x15 """Remote device terminated connection due to power off.""" ERROR_CODE_CONN_TERM_BY_LOCAL_HOST = 0x16 """Connection terminated by local host.""" ERROR_CODE_REPEATED_ATTEMPTS = 0x17 """Repeated attempts.""" ERROR_CODE_PAIRING_NOT_ALLOWED = 0x18 """Pairing not allowed.""" ERROR_CODE_UNKNOWN_LMP_PDU = 0x19 """Unknown LMP PDU.""" ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE = 0x1A """Unsupported remote feature.""" ERROR_CODE_SCO_OFFSET_REJ = 0x1B """SCO offset rejected.""" ERROR_CODE_SCO_INTERVAL_REJ = 0x1C """SCO interval rejected.""" ERROR_CODE_SCO_AIR_MODE_REJ = 0x1D """SCO air mode rejected.""" ERROR_CODE_INVALID_LMP_PARAMS = 0x1E """Invalid LMP parameters / Invalid LL parameters.""" ERROR_CODE_UNSPECIFIED_ERROR = 0x1F """Unspecified error.""" ERROR_CODE_UNSUPPORTED_LMP_PARAM_VAL = 0x20 """Unsupported LMP parameter value / Unsupported LL parameter value.""" ERROR_CODE_ROLE_CHANGE_NOT_ALLOWED = 0x21 """Role change not allowed.""" ERROR_CODE_LMP_LL_RESP_TIMEOUT = 0x22 """LMP response timeout / LL response timeout.""" ERROR_CODE_LMP_ERR_TRANSACTION_COLLISION = 0x23 """LMP error transaction collision / LL procedure collision.""" ERROR_CODE_LMP_PDU_NOT_ALLOWED = 0x24 """LMP PDU not allowed.""" ERROR_CODE_ENCRYPT_MODE_NOT_ACCEPTABLE = 0x25 """Encryption mode not acceptable.""" ERROR_CODE_LINK_KEY_CAN_NOT_BE_CHANGED = 0x26 """Link key cannot be changed.""" ERROR_CODE_REQ_QOS_NOT_SUPPORTED = 0x27 """Requested QoS not supported.""" ERROR_CODE_INSTANT_PASSED = 0x28 """Instance passed.""" ERROR_CODE_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED = 0x29 """Pairing with unit key not supported.""" ERROR_CODE_DIFFERENT_TRANSACTION_COLLISION = 0x2A """Different transaction collision.""" ERROR_CODE_RESERVED1 = 0x2B """Reserved for future use.""" ERROR_CODE_QOS_UNACCEPTABLE_PARAM = 0x2C """QoS unacceptable parameter.""" ERROR_CODE_QOS_REJ = 0x2D """QoS rejected.""" ERROR_CODE_CHAN_ASSESSMENT_NOT_SUPPORTED = 0x2E """Channel classification not supported error.""" ERROR_CODE_INSUFFICIENT_SECURITY = 0x2F """Insufficient security.""" ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE = 0x30 """Parameter out of mandatory range.""" ERROR_CODE_RESERVED2 = 0x31 """Reserved for future use.""" ERROR_CODE_ROLE_SWITCH_PENDING = 0x32 """Role switch pending.""" ERROR_CODE_RESERVED3 = 0x33 """Reserved for future use.""" ERROR_CODE_RESERVED_SLOT_VIOLATION = 0x34 """Reserved slot violation.""" ERROR_CODE_ROLE_SWITCH_FAILED = 0x35 """Role switch failed.""" ERROR_CODE_EXTENDED_INQUIRY_RESP_TOO_LARGE = 0x36 """Extended inquiry response too large.""" ERROR_CODE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST = 0x37 """Secure simple pairing not supported by host.""" ERROR_CODE_HOST_BUSY_PAIRING = 0x38 """Host busy - pairing.""" ERROR_CODE_CONN_REJ_NO_SUITABLE_CHAN_FOUND = 0x39 """Connection rejected dur to no suitable channel found.""" ERROR_CODE_CONTROLLER_BUSY = 0x3A """Controller busy.""" ERROR_CODE_UNACCEPTABLE_CONN_INTERVAL = 0x3B """Unacceptable connection parameters.""" ERROR_CODE_ADV_TIMEOUT = 0x3C """Advertising timeout.""" ERROR_CODE_CONN_TERM_MIC_FAILURE = 0x3D """Connection terminated due to MIC failure.""" ERROR_CODE_CONN_FAILED_TO_ESTABLISH = 0x3E """Connection failed to be established / Synchronization timeout.""" ERROR_CODE_MAC_CONN_FAILED = 0x3F """MAC connection failed [previously used].""" ERROR_CODE_COARSE_CLK_ADJ_REJ = 0x40 """ Coarse cloack adjustment rejected but will try to adjust clock using clock dragging. """ ERROR_CODE_TYPE0_SUBMAP_NOT_DEF = 0x41 """Type0 submap noot defined.""" ERROR_CODE_UNKNOWN_ADV_ID = 0x42 """Unknown advertising identifier.""" ERROR_CODE_LIMIT_REACHED = 0x43 """Limit reached.""" ERROR_CODE_OP_CANCELLED_BY_HOST = 0x44 """Operation cancelled by host.""" ERROR_CODE_PKT_TOO_LONG = 0x45 """Packet too long.""" DECODE_FAILURE = 0xFF """ADI vendor specific, returns when the status is not properly set."""