• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2021-2022 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15# -----------------------------------------------------------------------------
16# Imports
17# -----------------------------------------------------------------------------
18import struct
19import collections
20import logging
21import functools
22from colors import color
23
24from .core import *
25
26# -----------------------------------------------------------------------------
27# Logging
28# -----------------------------------------------------------------------------
29logger = logging.getLogger(__name__)
30
31
32# -----------------------------------------------------------------------------
33# Utils
34# -----------------------------------------------------------------------------
35def hci_command_op_code(ogf, ocf):
36    return (ogf << 10 | ocf)
37
38
39def key_with_value(dictionary, target_value):
40    for key, value in dictionary.items():
41        if value == target_value:
42            return key
43    return None
44
45
46def indent_lines(str):
47    return '\n'.join(['  ' + line for line in str.split('\n')])
48
49
50def map_null_terminated_utf8_string(utf8_bytes):
51    try:
52        terminator = utf8_bytes.find(0)
53        if terminator < 0:
54            return utf8_bytes
55        return utf8_bytes[0:terminator].decode('utf8')
56    except UnicodeDecodeError:
57        return utf8_bytes
58
59
60def map_class_of_device(class_of_device):
61    service_classes, major_device_class, minor_device_class = DeviceClass.split_class_of_device(class_of_device)
62    return f'[{class_of_device:06X}] Services({",".join(DeviceClass.service_class_labels(service_classes))}),Class({DeviceClass.major_device_class_name(major_device_class)}|{DeviceClass.minor_device_class_name(major_device_class, minor_device_class)})'
63
64
65# -----------------------------------------------------------------------------
66# Constants
67# -----------------------------------------------------------------------------
68
69# HCI Version
70HCI_VERSION_BLUETOOTH_CORE_1_0B    = 0
71HCI_VERSION_BLUETOOTH_CORE_1_1     = 1
72HCI_VERSION_BLUETOOTH_CORE_1_2     = 2
73HCI_VERSION_BLUETOOTH_CORE_2_0_EDR = 3
74HCI_VERSION_BLUETOOTH_CORE_2_1_EDR = 4
75HCI_VERSION_BLUETOOTH_CORE_3_0_HS  = 5
76HCI_VERSION_BLUETOOTH_CORE_4_0     = 6
77HCI_VERSION_BLUETOOTH_CORE_4_1     = 7
78HCI_VERSION_BLUETOOTH_CORE_4_2     = 8
79HCI_VERSION_BLUETOOTH_CORE_5_0     = 9
80HCI_VERSION_BLUETOOTH_CORE_5_1     = 10
81HCI_VERSION_BLUETOOTH_CORE_5_2     = 11
82HCI_VERSION_BLUETOOTH_CORE_5_3     = 12
83
84# HCI Packet types
85HCI_COMMAND_PACKET          = 0x01
86HCI_ACL_DATA_PACKET         = 0x02
87HCI_SYNCHRONOUS_DATA_PACKET = 0x03
88HCI_EVENT_PACKET            = 0x04
89
90# HCI Event Codes
91HCI_INQUIRY_COMPLETE_EVENT                            = 0x01
92HCI_INQUIRY_RESULT_EVENT                              = 0x02
93HCI_CONNECTION_COMPLETE_EVENT                         = 0x03
94HCI_CONNECTION_REQUEST_EVENT                          = 0x04
95HCI_DISCONNECTION_COMPLETE_EVENT                      = 0x05
96HCI_AUTHENTICATION_COMPLETE_EVENT                     = 0x06
97HCI_REMOTE_NAME_REQUEST_COMPLETE_EVENT                = 0x07
98HCI_ENCRYPTION_CHANGE_EVENT                           = 0x08
99HCI_CHANGE_CONNECTION_LINK_KEY_COMPLETE_EVENT         = 0x09
100HCI_LINK_KEY_TYPE_CHANGED_EVENT                       = 0x0A
101HCI_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE_EVENT     = 0x0B
102HCI_READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT    = 0x0C
103HCI_QOS_SETUP_COMPLETE_EVENT                          = 0x0D
104HCI_COMMAND_COMPLETE_EVENT                            = 0x0E
105HCI_COMMAND_STATUS_EVENT                              = 0x0F
106HCI_HARDWARE_ERROR_EVENT                              = 0x10
107HCI_FLUSH_OCCURRED_EVENT                              = 0x11
108HCI_ROLE_CHANGE_EVENT                                 = 0x12
109HCI_NUMBER_OF_COMPLETED_PACKETS_EVENT                 = 0x13
110HCI_MODE_CHANGE_EVENT                                 = 0x14
111HCI_RETURN_LINK_KEYS_EVENT                            = 0x15
112HCI_PIN_CODE_REQUEST_EVENT                            = 0x16
113HCI_LINK_KEY_REQUEST_EVENT                            = 0x17
114HCI_LINK_KEY_NOTIFICATION_EVENT                       = 0x18
115HCI_LOOPBACK_COMMAND_EVENT                            = 0x19
116HCI_DATA_BUFFER_OVERFLOW_EVENT                        = 0x1A
117HCI_MAX_SLOTS_CHANGE_EVENT                            = 0x1B
118HCI_READ_CLOCK_OFFSET_COMPLETE_EVENT                  = 0x1C
119HCI_CONNECTION_PACKET_TYPE_CHANGED_EVENT              = 0x1D
120HCI_QOS_VIOLATION_EVENT                               = 0x1E
121HCI_PAGE_SCAN_REPETITION_MODE_CHANGE_EVENT            = 0x20
122HCI_FLOW_SPECIFICATION_COMPLETE_EVENT                 = 0x21
123HCI_INQUIRY_RESULT_WITH_RSSI_EVENT                    = 0x22
124HCI_READ_REMOTE_EXTENDED_FEATURES_COMPLETE_EVENT      = 0x23
125HCI_SYNCHRONOUS_CONNECTION_COMPLETE_EVENT             = 0x2C
126HCI_SYNCHRONOUS_CONNECTION_CHANGED_EVENT              = 0x2D
127HCI_SNIFF_SUBRATING_EVENT                             = 0x2E
128HCI_EXTENDED_INQUIRY_RESULT_EVENT                     = 0x2F
129HCI_ENCRYPTION_KEY_REFRESH_COMPLETE_EVENT             = 0x30
130HCI_IO_CAPABILITY_REQUEST_EVENT                       = 0x31
131HCI_IO_CAPABILITY_RESPONSE_EVENT                      = 0x32
132HCI_USER_CONFIRMATION_REQUEST_EVENT                   = 0x33
133HCI_USER_PASSKEY_REQUEST_EVENT                        = 0x34
134HCI_REMOTE_OOB_DATA_REQUEST                           = 0x35
135HCI_SIMPLE_PAIRING_COMPLETE_EVENT                     = 0x36
136HCI_LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT            = 0x38
137HCI_ENHANCED_FLUSH_COMPLETE_EVENT                     = 0x39
138HCI_USER_PASSKEY_NOTIFICATION_EVENT                   = 0x3B
139HCI_KEYPRESS_NOTIFICATION_EVENT                       = 0x3C
140HCI_REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION_EVENT = 0x3D
141HCI_LE_META_EVENT                                     = 0x3E
142HCI_NUMBER_OF_COMPLETED_DATA_BLOCKS_EVENT             = 0x48
143
144HCI_EVENT_NAMES = {
145    HCI_INQUIRY_COMPLETE_EVENT:                            'HCI_INQUIRY_COMPLETE_EVENT',
146    HCI_INQUIRY_RESULT_EVENT:                              'HCI_INQUIRY_RESULT_EVENT',
147    HCI_CONNECTION_COMPLETE_EVENT:                         'HCI_CONNECTION_COMPLETE_EVENT',
148    HCI_CONNECTION_REQUEST_EVENT:                          'HCI_CONNECTION_REQUEST_EVENT',
149    HCI_DISCONNECTION_COMPLETE_EVENT:                      'HCI_DISCONNECTION_COMPLETE_EVENT',
150    HCI_AUTHENTICATION_COMPLETE_EVENT:                     'HCI_AUTHENTICATION_COMPLETE_EVENT',
151    HCI_REMOTE_NAME_REQUEST_COMPLETE_EVENT:                'HCI_REMOTE_NAME_REQUEST_COMPLETE_EVENT',
152    HCI_ENCRYPTION_CHANGE_EVENT:                           'HCI_ENCRYPTION_CHANGE_EVENT',
153    HCI_CHANGE_CONNECTION_LINK_KEY_COMPLETE_EVENT:         'HCI_CHANGE_CONNECTION_LINK_KEY_COMPLETE_EVENT',
154    HCI_LINK_KEY_TYPE_CHANGED_EVENT:                       'HCI_LINK_KEY_TYPE_CHANGED_EVENT',
155    HCI_INQUIRY_RESULT_WITH_RSSI_EVENT:                    'HCI_INQUIRY_RESULT_WITH_RSSI_EVENT',
156    HCI_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE_EVENT:     'HCI_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE_EVENT',
157    HCI_READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT:    'HCI_READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT',
158    HCI_QOS_SETUP_COMPLETE_EVENT:                          'HCI_QOS_SETUP_COMPLETE_EVENT',
159    HCI_SYNCHRONOUS_CONNECTION_COMPLETE_EVENT:             'HCI_SYNCHRONOUS_CONNECTION_COMPLETE_EVENT',
160    HCI_SYNCHRONOUS_CONNECTION_CHANGED_EVENT:              'HCI_SYNCHRONOUS_CONNECTION_CHANGED_EVENT',
161    HCI_SNIFF_SUBRATING_EVENT:                             'HCI_SNIFF_SUBRATING_EVENT',
162    HCI_COMMAND_COMPLETE_EVENT:                            'HCI_COMMAND_COMPLETE_EVENT',
163    HCI_COMMAND_STATUS_EVENT:                              'HCI_COMMAND_STATUS_EVENT',
164    HCI_HARDWARE_ERROR_EVENT:                              'HCI_HARDWARE_ERROR_EVENT',
165    HCI_FLUSH_OCCURRED_EVENT:                              'HCI_FLUSH_OCCURRED_EVENT',
166    HCI_ROLE_CHANGE_EVENT:                                 'HCI_ROLE_CHANGE_EVENT',
167    HCI_NUMBER_OF_COMPLETED_PACKETS_EVENT:                 'HCI_NUMBER_OF_COMPLETED_PACKETS_EVENT',
168    HCI_MODE_CHANGE_EVENT:                                 'HCI_MODE_CHANGE_EVENT',
169    HCI_RETURN_LINK_KEYS_EVENT:                            'HCI_RETURN_LINK_KEYS_EVENT',
170    HCI_PIN_CODE_REQUEST_EVENT:                            'HCI_PIN_CODE_REQUEST_EVENT',
171    HCI_LINK_KEY_REQUEST_EVENT:                            'HCI_LINK_KEY_REQUEST_EVENT',
172    HCI_LINK_KEY_NOTIFICATION_EVENT:                       'HCI_LINK_KEY_NOTIFICATION_EVENT',
173    HCI_LOOPBACK_COMMAND_EVENT:                            'HCI_LOOPBACK_COMMAND_EVENT',
174    HCI_DATA_BUFFER_OVERFLOW_EVENT:                        'HCI_DATA_BUFFER_OVERFLOW_EVENT',
175    HCI_MAX_SLOTS_CHANGE_EVENT:                            'HCI_MAX_SLOTS_CHANGE_EVENT',
176    HCI_READ_CLOCK_OFFSET_COMPLETE_EVENT:                  'HCI_READ_CLOCK_OFFSET_COMPLETE_EVENT',
177    HCI_CONNECTION_PACKET_TYPE_CHANGED_EVENT:              'HCI_CONNECTION_PACKET_TYPE_CHANGED_EVENT',
178    HCI_QOS_VIOLATION_EVENT:                               'HCI_QOS_VIOLATION_EVENT',
179    HCI_PAGE_SCAN_REPETITION_MODE_CHANGE_EVENT:            'HCI_PAGE_SCAN_REPETITION_MODE_CHANGE_EVENT',
180    HCI_FLOW_SPECIFICATION_COMPLETE_EVENT:                 'HCI_FLOW_SPECIFICATION_COMPLETE_EVENT',
181    HCI_READ_REMOTE_EXTENDED_FEATURES_COMPLETE_EVENT:      'HCI_READ_REMOTE_EXTENDED_FEATURES_COMPLETE_EVENT',
182    HCI_EXTENDED_INQUIRY_RESULT_EVENT:                     'HCI_EXTENDED_INQUIRY_RESULT_EVENT',
183    HCI_ENCRYPTION_KEY_REFRESH_COMPLETE_EVENT:             'HCI_ENCRYPTION_KEY_REFRESH_COMPLETE_EVENT',
184    HCI_IO_CAPABILITY_REQUEST_EVENT:                       'HCI_IO_CAPABILITY_REQUEST_EVENT',
185    HCI_IO_CAPABILITY_RESPONSE_EVENT:                      'HCI_IO_CAPABILITY_RESPONSE_EVENT',
186    HCI_USER_CONFIRMATION_REQUEST_EVENT:                   'HCI_USER_CONFIRMATION_REQUEST_EVENT',
187    HCI_USER_PASSKEY_REQUEST_EVENT:                        'HCI_USER_PASSKEY_REQUEST_EVENT',
188    HCI_REMOTE_OOB_DATA_REQUEST:                           'HCI_REMOTE_OOB_DATA_REQUEST',
189    HCI_SIMPLE_PAIRING_COMPLETE_EVENT:                     'HCI_SIMPLE_PAIRING_COMPLETE_EVENT',
190    HCI_LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT:            'HCI_LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT',
191    HCI_ENHANCED_FLUSH_COMPLETE_EVENT:                     'HCI_ENHANCED_FLUSH_COMPLETE_EVENT',
192    HCI_USER_PASSKEY_NOTIFICATION_EVENT:                   'HCI_USER_PASSKEY_NOTIFICATION_EVENT',
193    HCI_KEYPRESS_NOTIFICATION_EVENT:                       'HCI_KEYPRESS_NOTIFICATION_EVENT',
194    HCI_REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION_EVENT: 'HCI_REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION_EVENT',
195    HCI_LE_META_EVENT:                                     'HCI_LE_META_EVENT'
196}
197
198# HCI Subevent Codes
199HCI_LE_CONNECTION_COMPLETE_EVENT                   = 0x01
200HCI_LE_ADVERTISING_REPORT_EVENT                    = 0x02
201HCI_LE_CONNECTION_UPDATE_COMPLETE_EVENT            = 0x03
202HCI_LE_READ_REMOTE_FEATURES_COMPLETE_EVENT         = 0x04
203HCI_LE_LONG_TERM_KEY_REQUEST_EVENT                 = 0x05
204HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_EVENT   = 0x06
205HCI_LE_DATA_LENGTH_CHANGE_EVENT                    = 0x07
206HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT  = 0x08
207HCI_LE_GENERATE_DHKEY_COMPLETE_EVENT               = 0x09
208HCI_LE_ENHANCED_CONNECTION_COMPLETE_EVENT          = 0x0A
209HCI_LE_DIRECTED_ADVERTISING_REPORT_EVENT           = 0x0B
210HCI_LE_PHY_UPDATE_COMPLETE_EVENT                   = 0x0C
211HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT           = 0x0D
212HCI_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_EVENT = 0x0E
213HCI_LE_PERIODIC_ADVERTISING_REPORT_EVENT           = 0x0F
214HCI_LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT        = 0x10
215HCI_LE_SCAN_TIMEOUT_EVENT                          = 0x11
216HCI_LE_ADVERTISING_SET_TERMINATED_EVENT            = 0x12
217HCI_LE_SCAN_REQUEST_RECEIVED_EVENT                 = 0x13
218HCI_LE_CHANNEL_SELECTION_ALGORITHM_EVENT           = 0x14
219
220HCI_SUBEVENT_NAMES = {
221    HCI_LE_CONNECTION_COMPLETE_EVENT:                   'HCI_LE_CONNECTION_COMPLETE_EVENT',
222    HCI_LE_ADVERTISING_REPORT_EVENT:                    'HCI_LE_ADVERTISING_REPORT_EVENT',
223    HCI_LE_CONNECTION_UPDATE_COMPLETE_EVENT:            'HCI_LE_CONNECTION_UPDATE_COMPLETE_EVENT',
224    HCI_LE_READ_REMOTE_FEATURES_COMPLETE_EVENT:         'HCI_LE_READ_REMOTE_FEATURES_COMPLETE_EVENT',
225    HCI_LE_LONG_TERM_KEY_REQUEST_EVENT:                 'HCI_LE_LONG_TERM_KEY_REQUEST_EVENT',
226    HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_EVENT:   'HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_EVENT',
227    HCI_LE_DATA_LENGTH_CHANGE_EVENT:                    'HCI_LE_DATA_LENGTH_CHANGE_EVENT',
228    HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT:  'HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT',
229    HCI_LE_GENERATE_DHKEY_COMPLETE_EVENT:               'HCI_LE_GENERATE_DHKEY_COMPLETE_EVENT',
230    HCI_LE_ENHANCED_CONNECTION_COMPLETE_EVENT:          'HCI_LE_ENHANCED_CONNECTION_COMPLETE_EVENT',
231    HCI_LE_DIRECTED_ADVERTISING_REPORT_EVENT:           'HCI_LE_DIRECTED_ADVERTISING_REPORT_EVENT',
232    HCI_LE_PHY_UPDATE_COMPLETE_EVENT:                   'HCI_LE_PHY_UPDATE_COMPLETE_EVENT',
233    HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT:           'HCI_LE_EXTENDED_ADVERTISING_REPORT_EVENT',
234    HCI_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_EVENT: 'HCI_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_EVENT',
235    HCI_LE_PERIODIC_ADVERTISING_REPORT_EVENT:           'HCI_LE_PERIODIC_ADVERTISING_REPORT_EVENT',
236    HCI_LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT:        'HCI_LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT',
237    HCI_LE_SCAN_TIMEOUT_EVENT:                          'HCI_LE_SCAN_TIMEOUT_EVENT',
238    HCI_LE_ADVERTISING_SET_TERMINATED_EVENT:            'HCI_LE_ADVERTISING_SET_TERMINATED_EVENT',
239    HCI_LE_SCAN_REQUEST_RECEIVED_EVENT:                 'HCI_LE_SCAN_REQUEST_RECEIVED_EVENT',
240    HCI_LE_CHANNEL_SELECTION_ALGORITHM_EVENT:           'HCI_LE_CHANNEL_SELECTION_ALGORITHM_EVENT'
241}
242
243# HCI Command
244HCI_INQUIRY_COMMAND                                               = hci_command_op_code(0x01, 0x0001)
245HCI_INQUIRY_CANCEL_COMMAND                                        = hci_command_op_code(0x01, 0x0002)
246HCI_CREATE_CONNECTION_COMMAND                                     = hci_command_op_code(0x01, 0x0005)
247HCI_DISCONNECT_COMMAND                                            = hci_command_op_code(0x01, 0x0006)
248HCI_ACCEPT_CONNECTION_REQUEST_COMMAND                             = hci_command_op_code(0x01, 0x0009)
249HCI_LINK_KEY_REQUEST_REPLY_COMMAND                                = hci_command_op_code(0x01, 0x000B)
250HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY_COMMAND                       = hci_command_op_code(0x01, 0x000C)
251HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY_COMMAND                       = hci_command_op_code(0x01, 0x000E)
252HCI_CHANGE_CONNECTION_PACKET_TYPE_COMMAND                         = hci_command_op_code(0x01, 0x000F)
253HCI_AUTHENTICATION_REQUESTED_COMMAND                              = hci_command_op_code(0x01, 0x0011)
254HCI_SET_CONNECTION_ENCRYPTION_COMMAND                             = hci_command_op_code(0x01, 0x0013)
255HCI_REMOTE_NAME_REQUEST_COMMAND                                   = hci_command_op_code(0x01, 0x0019)
256HCI_READ_REMOTE_SUPPORTED_FEATURES_COMMAND                        = hci_command_op_code(0x01, 0x001B)
257HCI_READ_REMOTE_EXTENDED_FEATURES_COMMAND                         = hci_command_op_code(0x01, 0x001C)
258HCI_READ_REMOTE_VERSION_INFORMATION_COMMAND                       = hci_command_op_code(0x01, 0x001D)
259HCI_READ_CLOCK_OFFSET_COMMAND                                     = hci_command_op_code(0x01, 0x001F)
260HCI_IO_CAPABILITY_REQUEST_REPLY_COMMAND                           = hci_command_op_code(0x01, 0x002B)
261HCI_USER_CONFIRMATION_REQUEST_REPLY_COMMAND                       = hci_command_op_code(0x01, 0x002C)
262HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY_COMMAND              = hci_command_op_code(0x01, 0x002D)
263HCI_USER_PASSKEY_REQUEST_REPLY_COMMAND                            = hci_command_op_code(0x01, 0x002E)
264HCI_USER_PASSKEY_REQUEST_NEGATIVE_REPLY_COMMAND                   = hci_command_op_code(0x01, 0x002F)
265HCI_ENHANCED_SETUP_SYNCHRONOUS_CONNECTION_COMMAND                 = hci_command_op_code(0x01, 0x003D)
266HCI_SNIFF_MODE_COMMAND                                            = hci_command_op_code(0x02, 0x0003)
267HCI_EXIT_SNIFF_MODE_COMMAND                                       = hci_command_op_code(0x02, 0x0004)
268HCI_SWITCH_ROLE_COMMAND                                           = hci_command_op_code(0x02, 0x000B)
269HCI_WRITE_LINK_POLICY_SETTINGS_COMMAND                            = hci_command_op_code(0x02, 0x000D)
270HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS_COMMAND                    = hci_command_op_code(0x02, 0x000F)
271HCI_SNIFF_SUBRATING_COMMAND                                       = hci_command_op_code(0x02, 0x0011)
272HCI_SET_EVENT_MASK_COMMAND                                        = hci_command_op_code(0x03, 0x0001)
273HCI_RESET_COMMAND                                                 = hci_command_op_code(0x03, 0x0003)
274HCI_SET_EVENT_FILTER_COMMAND                                      = hci_command_op_code(0x03, 0x0005)
275HCI_READ_STORED_LINK_KEY_COMMAND                                  = hci_command_op_code(0x03, 0x000D)
276HCI_DELETE_STORED_LINK_KEY_COMMAND                                = hci_command_op_code(0x03, 0x0012)
277HCI_WRITE_LOCAL_NAME_COMMAND                                      = hci_command_op_code(0x03, 0x0013)
278HCI_READ_LOCAL_NAME_COMMAND                                       = hci_command_op_code(0x03, 0x0014)
279HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_COMMAND                       = hci_command_op_code(0x03, 0x0016)
280HCI_WRITE_PAGE_TIMEOUT_COMMAND                                    = hci_command_op_code(0x03, 0x0018)
281HCI_WRITE_SCAN_ENABLE_COMMAND                                     = hci_command_op_code(0x03, 0x001A)
282HCI_READ_PAGE_SCAN_ACTIVITY_COMMAND                               = hci_command_op_code(0x03, 0x001B)
283HCI_WRITE_PAGE_SCAN_ACTIVITY_COMMAND                              = hci_command_op_code(0x03, 0x001C)
284HCI_WRITE_INQUIRY_SCAN_ACTIVITY_COMMAND                           = hci_command_op_code(0x03, 0x001E)
285HCI_READ_CLASS_OF_DEVICE_COMMAND                                  = hci_command_op_code(0x03, 0x0023)
286HCI_WRITE_CLASS_OF_DEVICE_COMMAND                                 = hci_command_op_code(0x03, 0x0024)
287HCI_READ_VOICE_SETTING_COMMAND                                    = hci_command_op_code(0x03, 0x0025)
288HCI_WRITE_VOICE_SETTING_COMMAND                                   = hci_command_op_code(0x03, 0x0026)
289HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND                  = hci_command_op_code(0x03, 0x002E)
290HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND                 = hci_command_op_code(0x03, 0x002F)
291HCI_HOST_BUFFER_SIZE_COMMAND                                      = hci_command_op_code(0x03, 0x0033)
292HCI_WRITE_LINK_SUPERVISION_TIMEOUT_COMMAND                        = hci_command_op_code(0x03, 0x0037)
293HCI_READ_NUMBER_OF_SUPPORTED_IAC_COMMAND                          = hci_command_op_code(0x03, 0x0038)
294HCI_READ_CURRENT_IAC_LAP_COMMAND                                  = hci_command_op_code(0x03, 0x0039)
295HCI_WRITE_INQUIRY_SCAN_TYPE_COMMAND                               = hci_command_op_code(0x03, 0x0043)
296HCI_WRITE_INQUIRY_MODE_COMMAND                                    = hci_command_op_code(0x03, 0x0045)
297HCI_READ_PAGE_SCAN_TYPE_COMMAND                                   = hci_command_op_code(0x03, 0x0046)
298HCI_WRITE_PAGE_SCAN_TYPE_COMMAND                                  = hci_command_op_code(0x03, 0x0047)
299HCI_WRITE_EXTENDED_INQUIRY_RESPONSE_COMMAND                       = hci_command_op_code(0x03, 0x0052)
300HCI_WRITE_SIMPLE_PAIRING_MODE_COMMAND                             = hci_command_op_code(0x03, 0x0056)
301HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL_COMMAND            = hci_command_op_code(0x03, 0x0058)
302HCI_SET_EVENT_MASK_PAGE_2_COMMAND                                 = hci_command_op_code(0x03, 0x0063)
303HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_COMMAND                 = hci_command_op_code(0x03, 0x005A)
304HCI_READ_LE_HOST_SUPPORT_COMMAND                                  = hci_command_op_code(0x03, 0x006C)
305HCI_WRITE_LE_HOST_SUPPORT_COMMAND                                 = hci_command_op_code(0x03, 0x006D)
306HCI_WRITE_SECURE_CONNECTIONS_HOST_SUPPORT_COMMAND                 = hci_command_op_code(0x03, 0x007A)
307HCI_WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT_COMMAND                   = hci_command_op_code(0x03, 0x007C)
308HCI_READ_LOCAL_VERSION_INFORMATION_COMMAND                        = hci_command_op_code(0x04, 0x0001)
309HCI_READ_LOCAL_SUPPORTED_COMMANDS_COMMAND                         = hci_command_op_code(0x04, 0x0002)
310HCI_READ_LOCAL_SUPPORTED_FEATURES_COMMAND                         = hci_command_op_code(0x04, 0x0003)
311HCI_READ_LOCAL_EXTENDED_FEATURES_COMMAND                          = hci_command_op_code(0x04, 0x0004)
312HCI_READ_BUFFER_SIZE_COMMAND                                      = hci_command_op_code(0x04, 0x0005)
313HCI_READ_BD_ADDR_COMMAND                                          = hci_command_op_code(0x04, 0x0009)
314HCI_READ_LOCAL_SUPPORTED_CODECS_COMMAND                           = hci_command_op_code(0x04, 0x000B)
315HCI_READ_ENCRYPTION_KEY_SIZE_COMMAND                              = hci_command_op_code(0x05, 0x0008)
316HCI_LE_SET_EVENT_MASK_COMMAND                                     = hci_command_op_code(0x08, 0x0001)
317HCI_LE_READ_BUFFER_SIZE_COMMAND                                   = hci_command_op_code(0x08, 0x0002)
318HCI_LE_READ_LOCAL_SUPPORTED_FEATURES_COMMAND                      = hci_command_op_code(0x08, 0x0003)
319HCI_LE_SET_RANDOM_ADDRESS_COMMAND                                 = hci_command_op_code(0x08, 0x0005)
320HCI_LE_SET_ADVERTISING_PARAMETERS_COMMAND                         = hci_command_op_code(0x08, 0x0006)
321HCI_LE_READ_ADVERTISING_CHANNEL_TX_POWER_COMMAND                  = hci_command_op_code(0x08, 0x0007)
322HCI_LE_SET_ADVERTISING_DATA_COMMAND                               = hci_command_op_code(0x08, 0x0008)
323HCI_LE_SET_SCAN_RESPONSE_DATA_COMMAND                             = hci_command_op_code(0x08, 0x0009)
324HCI_LE_SET_ADVERTISING_ENABLE_COMMAND                             = hci_command_op_code(0x08, 0x000A)
325HCI_LE_SET_SCAN_PARAMETERS_COMMAND                                = hci_command_op_code(0x08, 0x000B)
326HCI_LE_SET_SCAN_ENABLE_COMMAND                                    = hci_command_op_code(0x08, 0x000C)
327HCI_LE_CREATE_CONNECTION_COMMAND                                  = hci_command_op_code(0x08, 0x000D)
328HCI_LE_CREATE_CONNECTION_CANCEL_COMMAND                           = hci_command_op_code(0x08, 0x000E)
329HCI_LE_READ_WHITE_LIST_SIZE_COMMAND                               = hci_command_op_code(0x08, 0x000F)
330HCI_LE_CLEAR_WHITE_LIST_COMMAND                                   = hci_command_op_code(0x08, 0x0010)
331HCI_LE_ADD_DEVICE_TO_WHITE_LIST_COMMAND                           = hci_command_op_code(0x08, 0x0011)
332HCI_LE_REMOVE_DEVICE_FROM_WHITE_LIST_COMMAND                      = hci_command_op_code(0x08, 0x0012)
333HCI_LE_CONNECTION_UPDATE_COMMAND                                  = hci_command_op_code(0x08, 0x0013)
334HCI_LE_SET_HOST_CHANNEL_CLASSIFICATION_COMMAND                    = hci_command_op_code(0x08, 0x0014)
335HCI_LE_READ_CHANNEL_MAP_COMMAND                                   = hci_command_op_code(0x08, 0x0015)
336HCI_LE_READ_REMOTE_FEATURES_COMMAND                               = hci_command_op_code(0x08, 0x0016)
337HCI_LE_ENCRYPT_COMMAND                                            = hci_command_op_code(0x08, 0x0017)
338HCI_LE_RAND_COMMAND                                               = hci_command_op_code(0x08, 0x0018)
339HCI_LE_START_ENCRYPTION_COMMAND                                   = hci_command_op_code(0x08, 0x0019)
340HCI_LE_LONG_TERM_KEY_REQUEST_REPLY_COMMAND                        = hci_command_op_code(0x08, 0x001A)
341HCI_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY_COMMAND               = hci_command_op_code(0x08, 0x001B)
342HCI_LE_READ_SUPPORTED_STATES_COMMAND                              = hci_command_op_code(0x08, 0x001C)
343HCI_LE_RECEIVER_TEST_COMMAND                                      = hci_command_op_code(0x08, 0x001D)
344HCI_LE_TRANSMITTER_TEST_COMMAND                                   = hci_command_op_code(0x08, 0x001E)
345HCI_LE_TEST_END_COMMAND                                           = hci_command_op_code(0x08, 0x001F)
346HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_COMMAND          = hci_command_op_code(0x08, 0x0020)
347HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_COMMAND = hci_command_op_code(0x08, 0x0021)
348HCI_LE_SET_DATA_LENGTH_COMMAND                                    = hci_command_op_code(0x08, 0x0022)
349HCI_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND                 = hci_command_op_code(0x08, 0x0023)
350HCI_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND                = hci_command_op_code(0x08, 0x0024)
351HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND                        = hci_command_op_code(0x08, 0x0025)
352HCI_LE_GENERATE_DHKEY_COMMAND                                     = hci_command_op_code(0x08, 0x0026)
353HCI_LE_ADD_DEVICE_TO_RESOLVING_LIST_COMMAND                       = hci_command_op_code(0x08, 0x0027)
354HCI_LE_REMOVE_DEVICE_FROM_RESOLVING_LIST_COMMAND                  = hci_command_op_code(0x08, 0x0028)
355HCI_LE_CLEAR_RESOLVING_LIST_COMMAND                               = hci_command_op_code(0x08, 0x0029)
356HCI_LE_READ_RESOLVING_LIST_SIZE_COMMAND                           = hci_command_op_code(0x08, 0x002A)
357HCI_LE_READ_PEER_RESOLVABLE_ADDRESS_COMMAND                       = hci_command_op_code(0x08, 0x002B)
358HCI_LE_READ_LOCAL_RESOLVABLE_ADDRESS_COMMAND                      = hci_command_op_code(0x08, 0x002C)
359HCI_LE_SET_ADDRESS_RESOLUTION_ENABLE_COMMAND                      = hci_command_op_code(0x08, 0x002D)
360HCI_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_COMMAND             = hci_command_op_code(0x08, 0x002E)
361HCI_LE_READ_MAXIMUM_DATA_LENGTH_COMMAND                           = hci_command_op_code(0x08, 0x002F)
362HCI_LE_READ_PHY_COMMAND                                           = hci_command_op_code(0x08, 0x0030)
363HCI_LE_SET_DEFAULT_PHY_COMMAND                                    = hci_command_op_code(0x08, 0x0031)
364HCI_LE_SET_PHY_COMMAND                                            = hci_command_op_code(0x08, 0x0032)
365HCI_LE_ENHANCED_RECEIVER_TEST_COMMAND                             = hci_command_op_code(0x08, 0x0033)
366HCI_LE_ENHANCED_TRANSMITTER_TEST_COMMAND                          = hci_command_op_code(0x08, 0x0034)
367HCI_LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_COMMAND                 = hci_command_op_code(0x08, 0x0035)
368HCI_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_COMMAND                = hci_command_op_code(0x08, 0x0036)
369HCI_LE_SET_EXTENDED_ADVERTISING_DATA_COMMAND                      = hci_command_op_code(0x08, 0x0037)
370HCI_LE_SET_EXTENDED_SCAN_RESPONSE_DATA_COMMAND                    = hci_command_op_code(0x08, 0x0038)
371HCI_LE_SET_EXTENDED_ADVERTISING_ENABLE_COMMAND                    = hci_command_op_code(0x08, 0x0039)
372HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_COMMAND               = hci_command_op_code(0x08, 0x003A)
373HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERETISING_SETS_COMMAND         = hci_command_op_code(0x08, 0x003B)
374HCI_LE_REMOVE_ADVERTISING_SET_COMMAND                             = hci_command_op_code(0x08, 0x003C)
375HCI_LE_CLEAR_ADVERTISING_SETS_COMMAND                             = hci_command_op_code(0x08, 0x003D)
376HCI_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_COMMAND                = hci_command_op_code(0x08, 0x003E)
377HCI_LE_SET_PERIODIC_ADVERTISING_DATA_COMMAND                      = hci_command_op_code(0x08, 0x003F)
378HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE_COMMAND                    = hci_command_op_code(0x08, 0x0040)
379HCI_LE_SET_EXTENDED_SCAN_PARAMETERS_COMMAND                       = hci_command_op_code(0x08, 0x0041)
380HCI_LE_SET_EXTENDED_SCAN_ENABLE_COMMAND                           = hci_command_op_code(0x08, 0x0042)
381HCI_LE_SET_EXTENDED_CREATE_CONNECTION_COMMAND                     = hci_command_op_code(0x08, 0x0043)
382HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_COMMAND                   = hci_command_op_code(0x08, 0x0044)
383HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_COMMAND            = hci_command_op_code(0x08, 0x0045)
384HCI_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_COMMAND                = hci_command_op_code(0x08, 0x0046)
385HCI_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_COMMAND             = hci_command_op_code(0x08, 0x0047)
386HCI_LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_COMMAND        = hci_command_op_code(0x08, 0x0048)
387HCI_LE_CLEAR_PERIODIC_ADVERTISER_LIST_COMMAND                     = hci_command_op_code(0x08, 0x0049)
388HCI_LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_COMMAND                 = hci_command_op_code(0x08, 0x004A)
389HCI_LE_READ_TRANSMIT_POWER_COMMAND                                = hci_command_op_code(0x08, 0x004B)
390HCI_LE_READ_RF_PATH_COMPENSATION_COMMAND                          = hci_command_op_code(0x08, 0x004C)
391HCI_LE_WRITE_RF_PATH_COMPENSATION_COMMAND                         = hci_command_op_code(0x08, 0x004D)
392HCI_LE_SET_PRIVACY_MODE_COMMAND                                   = hci_command_op_code(0x08, 0x004E)
393
394
395HCI_COMMAND_NAMES = {
396    HCI_INQUIRY_COMMAND:                                               'HCI_INQUIRY_COMMAND',
397    HCI_INQUIRY_CANCEL_COMMAND:                                        'HCI_INQUIRY_CANCEL_COMMAND',
398    HCI_CREATE_CONNECTION_COMMAND:                                     'HCI_CREATE_CONNECTION_COMMAND',
399    HCI_DISCONNECT_COMMAND:                                            'HCI_DISCONNECT_COMMAND',
400    HCI_ACCEPT_CONNECTION_REQUEST_COMMAND:                             'HCI_ACCEPT_CONNECTION_REQUEST_COMMAND',
401    HCI_LINK_KEY_REQUEST_REPLY_COMMAND:                                'HCI_LINK_KEY_REQUEST_REPLY_COMMAND',
402    HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY_COMMAND:                       'HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY_COMMAND',
403    HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY_COMMAND:                       'HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY_COMMAND',
404    HCI_CHANGE_CONNECTION_PACKET_TYPE_COMMAND:                         'HCI_CHANGE_CONNECTION_PACKET_TYPE_COMMAND',
405    HCI_AUTHENTICATION_REQUESTED_COMMAND:                              'HCI_AUTHENTICATION_REQUESTED_COMMAND',
406    HCI_SET_CONNECTION_ENCRYPTION_COMMAND:                             'HCI_SET_CONNECTION_ENCRYPTION_COMMAND',
407    HCI_REMOTE_NAME_REQUEST_COMMAND:                                   'HCI_REMOTE_NAME_REQUEST_COMMAND',
408    HCI_READ_REMOTE_SUPPORTED_FEATURES_COMMAND:                        'HCI_READ_REMOTE_SUPPORTED_FEATURES_COMMAND',
409    HCI_READ_REMOTE_EXTENDED_FEATURES_COMMAND:                         'HCI_READ_REMOTE_EXTENDED_FEATURES_COMMAND',
410    HCI_READ_REMOTE_VERSION_INFORMATION_COMMAND:                       'HCI_READ_REMOTE_VERSION_INFORMATION_COMMAND',
411    HCI_READ_CLOCK_OFFSET_COMMAND:                                     'HCI_READ_CLOCK_OFFSET_COMMAND',
412    HCI_IO_CAPABILITY_REQUEST_REPLY_COMMAND:                           'HCI_IO_CAPABILITY_REQUEST_REPLY_COMMAND',
413    HCI_USER_CONFIRMATION_REQUEST_REPLY_COMMAND:                       'HCI_USER_CONFIRMATION_REQUEST_REPLY_COMMAND',
414    HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY_COMMAND:              'HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY_COMMAND',
415    HCI_USER_PASSKEY_REQUEST_REPLY_COMMAND:                            'HCI_USER_PASSKEY_REQUEST_REPLY_COMMAND',
416    HCI_USER_PASSKEY_REQUEST_NEGATIVE_REPLY_COMMAND:                   'HCI_USER_PASSKEY_REQUEST_NEGATIVE_REPLY_COMMAND',
417    HCI_ENHANCED_SETUP_SYNCHRONOUS_CONNECTION_COMMAND:                 'HCI_ENHANCED_SETUP_SYNCHRONOUS_CONNECTION_COMMAND',
418    HCI_SNIFF_MODE_COMMAND:                                            'HCI_SNIFF_MODE_COMMAND',
419    HCI_EXIT_SNIFF_MODE_COMMAND:                                       'HCI_EXIT_SNIFF_MODE_COMMAND',
420    HCI_SWITCH_ROLE_COMMAND:                                           'HCI_SWITCH_ROLE_COMMAND',
421    HCI_WRITE_LINK_POLICY_SETTINGS_COMMAND:                            'HCI_WRITE_LINK_POLICY_SETTINGS_COMMAND',
422    HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS_COMMAND:                    'HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS_COMMAND',
423    HCI_SNIFF_SUBRATING_COMMAND:                                       'HCI_SNIFF_SUBRATING_COMMAND',
424    HCI_SET_EVENT_MASK_COMMAND:                                        'HCI_SET_EVENT_MASK_COMMAND',
425    HCI_RESET_COMMAND:                                                 'HCI_RESET_COMMAND',
426    HCI_SET_EVENT_FILTER_COMMAND:                                      'HCI_SET_EVENT_FILTER_COMMAND',
427    HCI_READ_STORED_LINK_KEY_COMMAND:                                  'HCI_READ_STORED_LINK_KEY_COMMAND',
428    HCI_DELETE_STORED_LINK_KEY_COMMAND:                                'HCI_DELETE_STORED_LINK_KEY_COMMAND',
429    HCI_WRITE_LOCAL_NAME_COMMAND:                                      'HCI_WRITE_LOCAL_NAME_COMMAND',
430    HCI_READ_LOCAL_NAME_COMMAND:                                       'HCI_READ_LOCAL_NAME_COMMAND',
431    HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_COMMAND:                       'HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_COMMAND',
432    HCI_WRITE_PAGE_TIMEOUT_COMMAND:                                    'HCI_WRITE_PAGE_TIMEOUT_COMMAND',
433    HCI_WRITE_SCAN_ENABLE_COMMAND:                                     'HCI_WRITE_SCAN_ENABLE_COMMAND',
434    HCI_READ_PAGE_SCAN_ACTIVITY_COMMAND:                               'HCI_READ_PAGE_SCAN_ACTIVITY_COMMAND',
435    HCI_WRITE_PAGE_SCAN_ACTIVITY_COMMAND:                              'HCI_WRITE_PAGE_SCAN_ACTIVITY_COMMAND',
436    HCI_WRITE_INQUIRY_SCAN_ACTIVITY_COMMAND:                           'HCI_WRITE_INQUIRY_SCAN_ACTIVITY_COMMAND',
437    HCI_READ_CLASS_OF_DEVICE_COMMAND:                                  'HCI_READ_CLASS_OF_DEVICE_COMMAND',
438    HCI_WRITE_CLASS_OF_DEVICE_COMMAND:                                 'HCI_WRITE_CLASS_OF_DEVICE_COMMAND',
439    HCI_READ_VOICE_SETTING_COMMAND:                                    'HCI_READ_VOICE_SETTING_COMMAND',
440    HCI_WRITE_VOICE_SETTING_COMMAND:                                   'HCI_WRITE_VOICE_SETTING_COMMAND',
441    HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND:                  'HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND',
442    HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND:                 'HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE_COMMAND',
443    HCI_HOST_BUFFER_SIZE_COMMAND:                                      'HCI_HOST_BUFFER_SIZE_COMMAND',
444    HCI_WRITE_LINK_SUPERVISION_TIMEOUT_COMMAND:                        'HCI_WRITE_LINK_SUPERVISION_TIMEOUT_COMMAND',
445    HCI_READ_NUMBER_OF_SUPPORTED_IAC_COMMAND:                          'HCI_READ_NUMBER_OF_SUPPORTED_IAC_COMMAND',
446    HCI_READ_CURRENT_IAC_LAP_COMMAND:                                  'HCI_READ_CURRENT_IAC_LAP_COMMAND',
447    HCI_WRITE_INQUIRY_SCAN_TYPE_COMMAND:                               'HCI_WRITE_INQUIRY_SCAN_TYPE_COMMAND',
448    HCI_WRITE_INQUIRY_MODE_COMMAND:                                    'HCI_WRITE_INQUIRY_MODE_COMMAND',
449    HCI_READ_PAGE_SCAN_TYPE_COMMAND:                                   'HCI_READ_PAGE_SCAN_TYPE_COMMAND',
450    HCI_WRITE_PAGE_SCAN_TYPE_COMMAND:                                  'HCI_WRITE_PAGE_SCAN_TYPE_COMMAND',
451    HCI_WRITE_EXTENDED_INQUIRY_RESPONSE_COMMAND:                       'HCI_WRITE_EXTENDED_INQUIRY_RESPONSE_COMMAND',
452    HCI_WRITE_SIMPLE_PAIRING_MODE_COMMAND:                             'HCI_WRITE_SIMPLE_PAIRING_MODE_COMMAND',
453    HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL_COMMAND:            'HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL_COMMAND',
454    HCI_SET_EVENT_MASK_PAGE_2_COMMAND:                                 'HCI_SET_EVENT_MASK_PAGE_2_COMMAND',
455    HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_COMMAND:                 'HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_COMMAND',
456    HCI_READ_LOCAL_VERSION_INFORMATION_COMMAND:                        'HCI_READ_LOCAL_VERSION_INFORMATION_COMMAND',
457    HCI_READ_LOCAL_SUPPORTED_COMMANDS_COMMAND:                         'HCI_READ_LOCAL_SUPPORTED_COMMANDS_COMMAND',
458    HCI_READ_LOCAL_SUPPORTED_FEATURES_COMMAND:                         'HCI_READ_LOCAL_SUPPORTED_FEATURES_COMMAND',
459    HCI_READ_LOCAL_EXTENDED_FEATURES_COMMAND:                          'HCI_READ_LOCAL_EXTENDED_FEATURES_COMMAND',
460    HCI_READ_BUFFER_SIZE_COMMAND:                                      'HCI_READ_BUFFER_SIZE_COMMAND',
461    HCI_READ_LE_HOST_SUPPORT_COMMAND:                                  'HCI_READ_LE_HOST_SUPPORT_COMMAND',
462    HCI_WRITE_LE_HOST_SUPPORT_COMMAND:                                 'HCI_WRITE_LE_HOST_SUPPORT_COMMAND',
463    HCI_WRITE_SECURE_CONNECTIONS_HOST_SUPPORT_COMMAND:                 'HCI_WRITE_SECURE_CONNECTIONS_HOST_SUPPORT_COMMAND',
464    HCI_WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT_COMMAND:                   'HCI_WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT_COMMAND',
465    HCI_READ_BD_ADDR_COMMAND:                                          'HCI_READ_BD_ADDR_COMMAND',
466    HCI_READ_LOCAL_SUPPORTED_CODECS_COMMAND:                           'HCI_READ_LOCAL_SUPPORTED_CODECS_COMMAND',
467    HCI_READ_ENCRYPTION_KEY_SIZE_COMMAND:                              'HCI_READ_ENCRYPTION_KEY_SIZE_COMMAND',
468    HCI_LE_SET_EVENT_MASK_COMMAND:                                     'HCI_LE_SET_EVENT_MASK_COMMAND',
469    HCI_LE_READ_BUFFER_SIZE_COMMAND:                                   'HCI_LE_READ_BUFFER_SIZE_COMMAND',
470    HCI_LE_READ_LOCAL_SUPPORTED_FEATURES_COMMAND:                      'HCI_LE_READ_LOCAL_SUPPORTED_FEATURES_COMMAND',
471    HCI_LE_SET_RANDOM_ADDRESS_COMMAND:                                 'HCI_LE_SET_RANDOM_ADDRESS_COMMAND',
472    HCI_LE_SET_ADVERTISING_PARAMETERS_COMMAND:                         'HCI_LE_SET_ADVERTISING_PARAMETERS_COMMAND',
473    HCI_LE_READ_ADVERTISING_CHANNEL_TX_POWER_COMMAND:                  'HCI_LE_READ_ADVERTISING_CHANNEL_TX_POWER_COMMAND',
474    HCI_LE_SET_ADVERTISING_DATA_COMMAND:                               'HCI_LE_SET_ADVERTISING_DATA_COMMAND',
475    HCI_LE_SET_SCAN_RESPONSE_DATA_COMMAND:                             'HCI_LE_SET_SCAN_RESPONSE_DATA_COMMAND',
476    HCI_LE_SET_ADVERTISING_ENABLE_COMMAND:                             'HCI_LE_SET_ADVERTISING_ENABLE_COMMAND',
477    HCI_LE_SET_SCAN_PARAMETERS_COMMAND:                                'HCI_LE_SET_SCAN_PARAMETERS_COMMAND',
478    HCI_LE_SET_SCAN_ENABLE_COMMAND:                                    'HCI_LE_SET_SCAN_ENABLE_COMMAND',
479    HCI_LE_CREATE_CONNECTION_COMMAND:                                  'HCI_LE_CREATE_CONNECTION_COMMAND',
480    HCI_LE_CREATE_CONNECTION_CANCEL_COMMAND:                           'HCI_LE_CREATE_CONNECTION_CANCEL_COMMAND',
481    HCI_LE_READ_WHITE_LIST_SIZE_COMMAND:                               'HCI_LE_READ_WHITE_LIST_SIZE_COMMAND',
482    HCI_LE_CLEAR_WHITE_LIST_COMMAND:                                   'HCI_LE_CLEAR_WHITE_LIST_COMMAND',
483    HCI_LE_ADD_DEVICE_TO_WHITE_LIST_COMMAND:                           'HCI_LE_ADD_DEVICE_TO_WHITE_LIST_COMMAND',
484    HCI_LE_REMOVE_DEVICE_FROM_WHITE_LIST_COMMAND:                      'HCI_LE_REMOVE_DEVICE_FROM_WHITE_LIST_COMMAND',
485    HCI_LE_CONNECTION_UPDATE_COMMAND:                                  'HCI_LE_CONNECTION_UPDATE_COMMAND',
486    HCI_LE_SET_HOST_CHANNEL_CLASSIFICATION_COMMAND:                    'HCI_LE_SET_HOST_CHANNEL_CLASSIFICATION_COMMAND',
487    HCI_LE_READ_CHANNEL_MAP_COMMAND:                                   'HCI_LE_READ_CHANNEL_MAP_COMMAND',
488    HCI_LE_READ_REMOTE_FEATURES_COMMAND:                               'HCI_LE_READ_REMOTE_FEATURES_COMMAND',
489    HCI_LE_ENCRYPT_COMMAND:                                            'HCI_LE_ENCRYPT_COMMAND',
490    HCI_LE_RAND_COMMAND:                                               'HCI_LE_RAND_COMMAND',
491    HCI_LE_START_ENCRYPTION_COMMAND:                                   'HCI_LE_START_ENCRYPTION_COMMAND',
492    HCI_LE_LONG_TERM_KEY_REQUEST_REPLY_COMMAND:                        'HCI_LE_LONG_TERM_KEY_REQUEST_REPLY_COMMAND',
493    HCI_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY_COMMAND:               'HCI_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY_COMMAND',
494    HCI_LE_READ_SUPPORTED_STATES_COMMAND:                              'HCI_LE_READ_SUPPORTED_STATES_COMMAND',
495    HCI_LE_RECEIVER_TEST_COMMAND:                                      'HCI_LE_RECEIVER_TEST_COMMAND',
496    HCI_LE_TRANSMITTER_TEST_COMMAND:                                   'HCI_LE_TRANSMITTER_TEST_COMMAND',
497    HCI_LE_TEST_END_COMMAND:                                           'HCI_LE_TEST_END_COMMAND',
498    HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_COMMAND:          'HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_COMMAND',
499    HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_COMMAND: 'HCI_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_COMMAND',
500    HCI_LE_SET_DATA_LENGTH_COMMAND:                                    'HCI_LE_SET_DATA_LENGTH_COMMAND',
501    HCI_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND:                 'HCI_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND',
502    HCI_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND:                'HCI_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_COMMAND',
503    HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND:                        'HCI_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND',
504    HCI_LE_GENERATE_DHKEY_COMMAND:                                     'HCI_LE_GENERATE_DHKEY_COMMAND',
505    HCI_LE_ADD_DEVICE_TO_RESOLVING_LIST_COMMAND:                       'HCI_LE_ADD_DEVICE_TO_RESOLVING_LIST_COMMAND',
506    HCI_LE_REMOVE_DEVICE_FROM_RESOLVING_LIST_COMMAND:                  'HCI_LE_REMOVE_DEVICE_FROM_RESOLVING_LIST_COMMAND',
507    HCI_LE_CLEAR_RESOLVING_LIST_COMMAND:                               'HCI_LE_CLEAR_RESOLVING_LIST_COMMAND',
508    HCI_LE_READ_RESOLVING_LIST_SIZE_COMMAND:                           'HCI_LE_READ_RESOLVING_LIST_SIZE_COMMAND',
509    HCI_LE_READ_PEER_RESOLVABLE_ADDRESS_COMMAND:                       'HCI_LE_READ_PEER_RESOLVABLE_ADDRESS_COMMAND',
510    HCI_LE_READ_LOCAL_RESOLVABLE_ADDRESS_COMMAND:                      'HCI_LE_READ_LOCAL_RESOLVABLE_ADDRESS_COMMAND',
511    HCI_LE_SET_ADDRESS_RESOLUTION_ENABLE_COMMAND:                      'HCI_LE_SET_ADDRESS_RESOLUTION_ENABLE_COMMAND',
512    HCI_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_COMMAND:             'HCI_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_COMMAND',
513    HCI_LE_READ_MAXIMUM_DATA_LENGTH_COMMAND:                           'HCI_LE_READ_MAXIMUM_DATA_LENGTH_COMMAND',
514    HCI_LE_READ_PHY_COMMAND:                                           'HCI_LE_READ_PHY_COMMAND',
515    HCI_LE_SET_DEFAULT_PHY_COMMAND:                                    'HCI_LE_SET_DEFAULT_PHY_COMMAND',
516    HCI_LE_SET_PHY_COMMAND:                                            'HCI_LE_SET_PHY_COMMAND',
517    HCI_LE_ENHANCED_RECEIVER_TEST_COMMAND:                             'HCI_LE_ENHANCED_RECEIVER_TEST_COMMAND',
518    HCI_LE_ENHANCED_TRANSMITTER_TEST_COMMAND:                          'HCI_LE_ENHANCED_TRANSMITTER_TEST_COMMAND',
519    HCI_LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_COMMAND:                 'HCI_LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_COMMAND',
520    HCI_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_COMMAND:                'HCI_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_COMMAND',
521    HCI_LE_SET_EXTENDED_ADVERTISING_DATA_COMMAND:                      'HCI_LE_SET_EXTENDED_ADVERTISING_DATA_COMMAND',
522    HCI_LE_SET_EXTENDED_SCAN_RESPONSE_DATA_COMMAND:                    'HCI_LE_SET_EXTENDED_SCAN_RESPONSE_DATA_COMMAND',
523    HCI_LE_SET_EXTENDED_ADVERTISING_ENABLE_COMMAND:                    'HCI_LE_SET_EXTENDED_ADVERTISING_ENABLE_COMMAND',
524    HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_COMMAND:               'HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_COMMAND',
525    HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERETISING_SETS_COMMAND:         'HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERETISING_SETS_COMMAND',
526    HCI_LE_REMOVE_ADVERTISING_SET_COMMAND:                             'HCI_LE_REMOVE_ADVERTISING_SET_COMMAND',
527    HCI_LE_CLEAR_ADVERTISING_SETS_COMMAND:                             'HCI_LE_CLEAR_ADVERTISING_SETS_COMMAND',
528    HCI_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_COMMAND:                'HCI_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_COMMAND',
529    HCI_LE_SET_PERIODIC_ADVERTISING_DATA_COMMAND:                      'HCI_LE_SET_PERIODIC_ADVERTISING_DATA_COMMAND',
530    HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE_COMMAND:                    'HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE_COMMAND',
531    HCI_LE_SET_EXTENDED_SCAN_PARAMETERS_COMMAND:                       'HCI_LE_SET_EXTENDED_SCAN_PARAMETERS_COMMAND',
532    HCI_LE_SET_EXTENDED_SCAN_ENABLE_COMMAND:                           'HCI_LE_SET_EXTENDED_SCAN_ENABLE_COMMAND',
533    HCI_LE_SET_EXTENDED_CREATE_CONNECTION_COMMAND:                     'HCI_LE_SET_EXTENDED_CREATE_CONNECTION_COMMAND',
534    HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_COMMAND:                   'HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_COMMAND',
535    HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_COMMAND:            'HCI_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_COMMAND',
536    HCI_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_COMMAND:                'HCI_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_COMMAND',
537    HCI_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_COMMAND:             'HCI_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_COMMAND',
538    HCI_LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_COMMAND:        'HCI_LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_COMMAND',
539    HCI_LE_CLEAR_PERIODIC_ADVERTISER_LIST_COMMAND:                     'HCI_LE_CLEAR_PERIODIC_ADVERTISER_LIST_COMMAND',
540    HCI_LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_COMMAND:                 'HCI_LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_COMMAND',
541    HCI_LE_READ_TRANSMIT_POWER_COMMAND:                                'HCI_LE_READ_TRANSMIT_POWER_COMMAND',
542    HCI_LE_READ_RF_PATH_COMPENSATION_COMMAND:                          'HCI_LE_READ_RF_PATH_COMPENSATION_COMMAND',
543    HCI_LE_WRITE_RF_PATH_COMPENSATION_COMMAND:                         'HCI_LE_WRITE_RF_PATH_COMPENSATION_COMMAND',
544    HCI_LE_SET_PRIVACY_MODE_COMMAND:                                   'HCI_LE_SET_PRIVACY_MODE_COMMAND'
545}
546
547
548# HCI Error Codes
549# See Bluetooth spec Vol 2, Part D - 1.3 LIST OF ERROR CODES
550HCI_SUCCESS                                                        = 0x00
551HCI_UNKNOWN_HCI_COMMAND_ERROR                                      = 0x01
552HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR                            = 0x02
553HCI_HARDWARE_FAILURE_ERROR                                         = 0x03
554HCI_PAGE_TIMEOUT_ERROR                                             = 0x04
555HCI_AUTHENTICATION_FAILURE_ERROR                                   = 0x05
556HCI_PIN_OR_KEY_MISSING_ERROR                                       = 0x06
557HCI_MEMORY_CAPACITY_EXCEEDED_ERROR                                 = 0x07
558HCI_CONNECTION_TIMEOUT_ERROR                                       = 0x08
559HCI_CONNECTION_LIMIT_EXCEEDED_ERROR                                = 0x09
560HCI_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED_ERROR        = 0x0A
561HCI_CONNECTION_ALREADY_EXISTS_ERROR                                = 0x0B
562HCI_COMMAND_DISALLOWED_ERROR                                       = 0x0C
563HCI_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES_ERROR             = 0x0D
564HCI_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS_ERROR              = 0x0E
565HCI_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR_ERROR          = 0x0F
566HCI_CONNECTION_ACCEPT_TIMEOUT_ERROR                                = 0x10
567HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE_ERROR                   = 0x11
568HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR                           = 0x12
569HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR                        = 0x13
570HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES_ERROR = 0x14
571HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF_ERROR     = 0x15
572HCI_CONNECTION_TERMINATED_BY_LOCAL_HOST_ERROR                      = 0x16
573HCI_UNACCEPTABLE_CONNECTION_PARAMETERS_ERROR                       = 0x3B
574HCI_CONNECTION_FAILED_TO_BE_ESTABLISHED_ERROR                      = 0x3E
575# TODO: more error codes
576
577HCI_ERROR_NAMES = {
578    HCI_SUCCESS:                                                        'HCI_SUCCESS',
579    HCI_UNKNOWN_HCI_COMMAND_ERROR:                                      'HCI_UNKNOWN_HCI_COMMAND_ERROR',
580    HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR:                            'HCI_UNKNOWN_CONNECTION_IDENTIFIER_ERROR',
581    HCI_HARDWARE_FAILURE_ERROR:                                         'HCI_HARDWARE_FAILURE_ERROR',
582    HCI_PAGE_TIMEOUT_ERROR:                                             'HCI_PAGE_TIMEOUT_ERROR',
583    HCI_AUTHENTICATION_FAILURE_ERROR:                                   'HCI_AUTHENTICATION_FAILURE_ERROR',
584    HCI_PIN_OR_KEY_MISSING_ERROR:                                       'HCI_PIN_OR_KEY_MISSING_ERROR',
585    HCI_MEMORY_CAPACITY_EXCEEDED_ERROR:                                 'HCI_MEMORY_CAPACITY_EXCEEDED_ERROR',
586    HCI_CONNECTION_TIMEOUT_ERROR:                                       'HCI_CONNECTION_TIMEOUT_ERROR',
587    HCI_CONNECTION_LIMIT_EXCEEDED_ERROR:                                'HCI_CONNECTION_LIMIT_EXCEEDED_ERROR',
588    HCI_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED_ERROR:        'HCI_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED_ERROR',
589    HCI_CONNECTION_ALREADY_EXISTS_ERROR:                                'HCI_CONNECTION_ALREADY_EXISTS_ERROR',
590    HCI_COMMAND_DISALLOWED_ERROR:                                       'HCI_COMMAND_DISALLOWED_ERROR',
591    HCI_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES_ERROR:             'HCI_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES_ERROR',
592    HCI_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS_ERROR:              'HCI_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS_ERROR',
593    HCI_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR_ERROR:          'HCI_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR_ERROR',
594    HCI_CONNECTION_ACCEPT_TIMEOUT_ERROR:                                'HCI_CONNECTION_ACCEPT_TIMEOUT_ERROR',
595    HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE_ERROR:                   'HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE_ERROR',
596    HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR:                           'HCI_INVALID_HCI_COMMAND_PARAMETERS_ERROR',
597    HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR:                        'HCI_REMOTE_USER_TERMINATED_CONNECTION_ERROR',
598    HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES_ERROR: 'HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES_ERROR',
599    HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF_ERROR:     'HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF_ERROR',
600    HCI_CONNECTION_TERMINATED_BY_LOCAL_HOST_ERROR:                      'HCI_CONNECTION_TERMINATED_BY_LOCAL_HOST_ERROR',
601    HCI_UNACCEPTABLE_CONNECTION_PARAMETERS_ERROR:                       'HCI_UNACCEPTABLE_CONNECTION_PARAMETERS_ERROR',
602    HCI_CONNECTION_FAILED_TO_BE_ESTABLISHED_ERROR:                      'HCI_CONNECTION_FAILED_TO_BE_ESTABLISHED_ERROR'
603}
604
605# Command Status codes
606HCI_COMMAND_STATUS_PENDING = 0
607
608# LE Event Masks
609LE_CONNECTION_COMPLETE_EVENT_MASK                   = (1 << 0)
610LE_ADVERTISING_REPORT_EVENT_MASK                    = (1 << 1)
611LE_CONNECTION_UPDATE_COMPLETE_EVENT_MASK            = (1 << 2)
612LE_READ_REMOTE_FEATURES_COMPLETE_EVENT_MASK         = (1 << 3)
613LE_LONG_TERM_KEY_REQUEST_EVENT_MASK                 = (1 << 4)
614LE_REMOTE_CONNECTION_PARAMETER_REQUEST_EVENT_MASK   = (1 << 5)
615LE_DATA_LENGTH_CHANGE_EVENT_MASK                    = (1 << 6)
616LE_READ_LOCAL_P_256_PUBLIC_KEY_COMPLETE_EVENT_MASK  = (1 << 7)
617LE_GENERATE_DHKEY_COMPLETE_EVENT_MASK               = (1 << 8)
618LE_ENHANCED_CONNECTION_COMPLETE_EVENT_MASK          = (1 << 9)
619LE_DIRECTED_ADVERTISING_REPORT_EVENT_MASK           = (1 << 10)
620LE_PHY_UPDATE_COMPLETE_EVENT_MASK                   = (1 << 11)
621LE_EXTENDED_ADVERTISING_REPORT_EVENT_MASK           = (1 << 12)
622LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED_EVENT_MASK = (1 << 13)
623LE_PERIODIC_ADVERTISING_REPORT_EVENT_MASK           = (1 << 14)
624LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT_MASK        = (1 << 15)
625LE_EXTENDED_SCAN_TIMEOUT_EVENT_MASK                 = (1 << 16)
626LE_EXTENDED_ADVERTISING_SET_TERMINATED_EVENT_MASK   = (1 << 17)
627LE_SCAN_REQUEST_RECEIVED_EVENT_MASK                 = (1 << 18)
628LE_CHANNEL_SELECTION_ALGORITHM_EVENT_MASK           = (1 << 19)
629
630# ACL
631HCI_ACL_PB_FIRST_NON_FLUSHABLE = 0
632HCI_ACL_PB_CONTINUATION        = 1
633HCI_ACL_PB_FIRST_FLUSHABLE     = 2
634HCI_ACK_PB_COMPLETE_L2CAP      = 3
635
636# Roles
637HCI_CENTRAL_ROLE    = 0
638HCI_PERIPHERAL_ROLE = 1
639
640HCI_ROLE_NAMES = {
641    HCI_CENTRAL_ROLE:    'CENTRAL',
642    HCI_PERIPHERAL_ROLE: 'PERIPHERAL'
643}
644
645# LE PHY Types
646HCI_LE_1M_PHY    = 1
647HCI_LE_2M_PHY    = 2
648HCI_LE_CODED_PHY = 3
649
650HCI_LE_PHY_NAMES = {
651    HCI_LE_1M_PHY:    'LE 1M',
652    HCI_LE_2M_PHY:    'L2 2M',
653    HCI_LE_CODED_PHY: 'LE Coded'
654}
655
656# Connection Parameters
657HCI_CONNECTION_INTERVAL_MS_PER_UNIT = 1.25
658HCI_CONNECTION_LATENCY_MS_PER_UNIT  = 1.25
659HCI_SUPERVISION_TIMEOUT_MS_PER_UNIT = 10
660
661# Inquiry LAP
662HCI_LIMITED_DEDICATED_INQUIRY_LAP = 0x9E8B00
663HCI_GENERAL_INQUIRY_LAP           = 0x9E8B33
664HCI_INQUIRY_LAP_NAMES = {
665    HCI_LIMITED_DEDICATED_INQUIRY_LAP: 'Limited Dedicated Inquiry',
666    HCI_GENERAL_INQUIRY_LAP:           'General Inquiry'
667}
668
669# Inquiry Mode
670HCI_STANDARD_INQUIRY_MODE  = 0x00
671HCI_INQUIRY_WITH_RSSI_MODE = 0x01
672HCI_EXTENDED_INQUIRY_MODE  = 0x02
673
674# Page Scan Repetition Mode
675HCI_R0_PAGE_SCAN_REPETITION_MODE = 0x00
676HCI_R1_PAGE_SCAN_REPETITION_MODE = 0x01
677HCI_R2_PAGE_SCAN_REPETITION_MODE = 0x02
678
679# IO Capability
680HCI_DISPLAY_ONLY_IO_CAPABILITY       = 0x00
681HCI_DISPLAY_YES_NO_IO_CAPABILITY     = 0x01
682HCI_KEYBOARD_ONLY_IO_CAPABILITY      = 0x02
683HCI_NO_INPUT_NO_OUTPUT_IO_CAPABILITY = 0x03
684
685HCI_IO_CAPABILITY_NAMES = {
686    HCI_DISPLAY_ONLY_IO_CAPABILITY:       'HCI_DISPLAY_ONLY_IO_CAPABILITY',
687    HCI_DISPLAY_YES_NO_IO_CAPABILITY:     'HCI_DISPLAY_YES_NO_IO_CAPABILITY',
688    HCI_KEYBOARD_ONLY_IO_CAPABILITY:      'HCI_KEYBOARD_ONLY_IO_CAPABILITY',
689    HCI_NO_INPUT_NO_OUTPUT_IO_CAPABILITY: 'HCI_NO_INPUT_NO_OUTPUT_IO_CAPABILITY'
690}
691
692# Authentication Requirements
693HCI_MITM_NOT_REQUIRED_NO_BONDING_AUTHENTICATION_REQUIREMENTS        = 0x00
694HCI_MITM_REQUIRED_NO_BONDING_AUTHENTICATION_REQUIREMENTS            = 0x01
695HCI_MITM_NOT_REQUIRED_DEDICATED_BONDING_AUTHENTICATION_REQUIREMENTS = 0x02
696HCI_MITM_REQUIRED_DEDICATED_BONDING_AUTHENTICATION_REQUIREMENTS     = 0x03
697HCI_MITM_NOT_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS   = 0x04
698HCI_MITM_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS       = 0x05
699
700HCI_AUTHENTICATION_REQUIREMENTS_NAMES = {
701    HCI_MITM_NOT_REQUIRED_NO_BONDING_AUTHENTICATION_REQUIREMENTS:        'HCI_MITM_NOT_REQUIRED_NO_BONDING_AUTHENTICATION_REQUIREMENTS',
702    HCI_MITM_REQUIRED_NO_BONDING_AUTHENTICATION_REQUIREMENTS:            'HCI_MITM_REQUIRED_NO_BONDING_AUTHENTICATION_REQUIREMENTS',
703    HCI_MITM_NOT_REQUIRED_DEDICATED_BONDING_AUTHENTICATION_REQUIREMENTS: 'HCI_MITM_NOT_REQUIRED_DEDICATED_BONDING_AUTHENTICATION_REQUIREMENTS',
704    HCI_MITM_REQUIRED_DEDICATED_BONDING_AUTHENTICATION_REQUIREMENTS:     'HCI_MITM_REQUIRED_DEDICATED_BONDING_AUTHENTICATION_REQUIREMENTS',
705    HCI_MITM_NOT_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS:   'HCI_MITM_NOT_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS',
706    HCI_MITM_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS:       'HCI_MITM_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS'
707}
708
709# Link Key Types
710HCI_COMBINATION_KEY_TYPE                                      = 0X00
711HCI_LOCAL_UNIT_KEY_TYPE                                       = 0X01
712HCI_REMOTE_UNIT_KEY_TYPE                                      = 0X02
713HCI_DEBUG_COMBINATION_KEY_TYPE                                = 0X03
714HCI_UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_192_TYPE = 0X04
715HCI_AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_192_TYPE   = 0X05
716HCI_CHANGED_COMBINATION_KEY_TYPE                              = 0X06
717HCI_UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_256_TYPE = 0X07
718HCI_AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_256_TYPE   = 0X08
719
720HCI_LINK_TYPE_NAMES = {
721    HCI_COMBINATION_KEY_TYPE:                                      'HCI_COMBINATION_KEY_TYPE',
722    HCI_LOCAL_UNIT_KEY_TYPE:                                       'HCI_LOCAL_UNIT_KEY_TYPE',
723    HCI_REMOTE_UNIT_KEY_TYPE:                                      'HCI_REMOTE_UNIT_KEY_TYPE',
724    HCI_DEBUG_COMBINATION_KEY_TYPE:                                'HCI_DEBUG_COMBINATION_KEY_TYPE',
725    HCI_UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_192_TYPE: 'HCI_UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_192_TYPE',
726    HCI_AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_192_TYPE:   'HCI_AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_192_TYPE',
727    HCI_CHANGED_COMBINATION_KEY_TYPE:                              'HCI_CHANGED_COMBINATION_KEY_TYPE',
728    HCI_UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_256_TYPE: 'HCI_UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_256_TYPE',
729    HCI_AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_256_TYPE:   'HCI_AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P_256_TYPE'
730}
731
732# Address types
733HCI_PUBLIC_DEVICE_ADDRESS_TYPE   = 0x00
734HCI_RANDOM_DEVICE_ADDRESS_TYPE   = 0x01
735HCI_PUBLIC_IDENTITY_ADDRESS_TYPE = 0x02
736HCI_RANDOM_IDENTITY_ADDRESS_TYPE = 0x03
737
738# -----------------------------------------------------------------------------
739STATUS_SPEC = {'size': 1, 'mapper': lambda x: HCI_Constant.status_name(x)}
740
741
742# -----------------------------------------------------------------------------
743class HCI_Constant:
744    @staticmethod
745    def status_name(status):
746        return HCI_ERROR_NAMES.get(status, f'0x{status:02X}')
747
748    @staticmethod
749    def error_name(status):
750        return HCI_ERROR_NAMES.get(status, f'0x{status:02X}')
751
752    @staticmethod
753    def role_name(role):
754        return HCI_ROLE_NAMES.get(role, str(role))
755
756    @staticmethod
757    def le_phy_name(phy):
758        return HCI_LE_PHY_NAMES.get(phy, str(phy))
759
760    @staticmethod
761    def inquiry_lap_name(lap):
762        return HCI_INQUIRY_LAP_NAMES.get(lap, f'0x{lap:06X}')
763
764    @staticmethod
765    def io_capability_name(io_capability):
766        return HCI_IO_CAPABILITY_NAMES.get(io_capability, f'0x{io_capability:02X}')
767
768    @staticmethod
769    def authentication_requirements_name(authentication_requirements):
770        return HCI_AUTHENTICATION_REQUIREMENTS_NAMES.get(
771            authentication_requirements,
772            f'0x{authentication_requirements:02X}'
773        )
774
775    @staticmethod
776    def link_key_type_name(link_key_type):
777        return HCI_LINK_TYPE_NAMES.get(link_key_type, f'0x{link_key_type:02X}')
778
779
780# -----------------------------------------------------------------------------
781class HCI_Error(ProtocolError):
782    def __init__(self, error_code):
783        super().__init__(error_code, 'hci', HCI_Constant.error_name(error_code))
784
785
786# -----------------------------------------------------------------------------
787# Generic HCI object
788# -----------------------------------------------------------------------------
789class HCI_Object:
790    @staticmethod
791    def init_from_fields(object, fields, values):
792        if type(values) is dict:
793            for field_name, _ in fields:
794                setattr(object, field_name, values[field_name])
795        else:
796            for field_name, field_value in zip(fields, values):
797                setattr(object, field_name, field_value)
798
799    @staticmethod
800    def init_from_bytes(object, data, offset, fields):
801        parsed = HCI_Object.dict_from_bytes(data, offset, fields)
802        HCI_Object.init_from_fields(object, parsed.keys(), parsed.values())
803
804    @staticmethod
805    def dict_from_bytes(data, offset, fields):
806        result = collections.OrderedDict()
807        for (field_name, field_type) in fields:
808            # The field_type may be a dictionnary with a mapper, parser, and/or size
809            if type(field_type) is dict:
810                if 'size' in field_type:
811                    field_type = field_type['size']
812                elif 'parser' in field_type:
813                    field_type = field_type['parser']
814
815            # Parse the field
816            if field_type == '*':
817                # The rest of the bytes
818                field_value = data[offset:]
819                offset += len(field_value)
820            elif field_type == 1:
821                # 8-bit unsigned
822                field_value = data[offset]
823                offset += 1
824            elif field_type == -1:
825                # 8-bit signed
826                field_value = struct.unpack_from('b', data, offset)[0]
827                offset += 1
828            elif field_type == 2:
829                # 16-bit unsigned
830                field_value = struct.unpack_from('<H', data, offset)[0]
831                offset += 2
832            elif field_type == '>2':
833                # 16-bit unsigned big-endian
834                field_value = struct.unpack_from('>H', data, offset)[0]
835                offset += 2
836            elif field_type == -2:
837                # 16-bit signed
838                field_value = struct.unpack_from('<h', data, offset)[0]
839                offset += 1
840            elif field_type == 3:
841                # 24-bit unsigned
842                padded = data[offset:offset + 3] + bytes([0])
843                field_value = struct.unpack('<I', padded)[0]
844                offset += 3
845            elif field_type == 4:
846                # 32-bit unsigned
847                field_value = struct.unpack_from('<I', data, offset)[0]
848                offset += 4
849            elif field_type == '>4':
850                # 32-bit unsigned big-endian
851                field_value = struct.unpack_from('>I', data, offset)[0]
852                offset += 4
853            elif type(field_type) is int and field_type > 4 and field_type <= 256:
854                # Byte array (from 5 up to 256 bytes)
855                field_value = data[offset:offset + field_type]
856                offset += field_type
857            elif callable(field_type):
858                offset, field_value = field_type(data, offset)
859            else:
860                raise ValueError(f'unknown field type {field_type}')
861
862            result[field_name] = field_value
863
864        return result
865
866    @staticmethod
867    def dict_to_bytes(object, fields):
868        result = bytearray()
869        for (field_name, field_type) in fields:
870            # The field_type may be a dictionnary with a mapper, parser, serializer, and/or size
871            serializer = None
872            if type(field_type) is dict:
873                if 'serializer' in field_type:
874                    serializer = field_type['serializer']
875                if 'size' in field_type:
876                    field_type = field_type['size']
877
878            # Serialize the field
879            field_value = object[field_name]
880            if serializer:
881                field_bytes = serializer(field_value)
882            elif field_type == 1:
883                # 8-bit unsigned
884                field_bytes = bytes([field_value])
885            elif field_type == -1:
886                # 8-bit signed
887                field_bytes = struct.pack('b', field_value)
888            elif field_type == 2:
889                # 16-bit unsigned
890                field_bytes = struct.pack('<H', field_value)
891            elif field_type == '>2':
892                # 16-bit unsigned big-endian
893                field_bytes = struct.pack('>H', field_value)
894            elif field_type == -2:
895                # 16-bit signed
896                field_bytes = struct.pack('<h', field_value)
897            elif field_type == 3:
898                # 24-bit unsigned
899                field_bytes = struct.pack('<I', field_value)[0:3]
900            elif field_type == 4:
901                # 32-bit unsigned
902                field_bytes = struct.pack('<I', field_value)
903            elif field_type == '>4':
904                # 32-bit unsigned big-endian
905                field_bytes = struct.pack('>I', field_value)
906            elif field_type == '*':
907                if type(field_value) is int:
908                    if field_value >= 0 and field_value <= 255:
909                        field_bytes = bytes([field_value])
910                    else:
911                        raise ValueError('value too large for *-typed field')
912                else:
913                    field_bytes = bytes(field_value)
914            elif type(field_value) is bytes or type(field_value) is bytearray or hasattr(field_value, 'to_bytes'):
915                field_bytes = bytes(field_value)
916                if type(field_type) is int and field_type > 4 and field_type <= 256:
917                    # Truncate or Pad with zeros if the field is too long or too short
918                    if len(field_bytes) < field_type:
919                        field_bytes += bytes(field_type - len(field_bytes))
920                    elif len(field_bytes) > field_type:
921                        field_bytes = field_bytes[:field_type]
922            else:
923                raise ValueError(f"don't know how to serialize type {type(field_value)}")
924
925            result += field_bytes
926
927        return bytes(result)
928
929    @staticmethod
930    def from_bytes(data, offset, fields):
931        return HCI_Object(fields, **HCI_Object.dict_from_bytes(data, offset, fields))
932
933    def to_bytes(self):
934        return HCI_Object.dict_to_bytes(self.__dict__, self.fields)
935
936    @staticmethod
937    def parse_length_prefixed_bytes(data, offset):
938        length = data[offset]
939        return offset + 1 + length, data[offset + 1:offset + 1 + length]
940
941    @staticmethod
942    def serialize_length_prefixed_bytes(data, padded_size=0):
943        prefixed_size = 1 + len(data)
944        padding = bytes(padded_size - prefixed_size) if prefixed_size < padded_size else b''
945        return bytes([len(data)]) + data + padding
946
947    @staticmethod
948    def format_field_value(value, indentation):
949        if type(value) is bytes:
950            return value.hex()
951        elif isinstance(value, HCI_Object):
952            return '\n' + value.to_string(indentation)
953        else:
954            return str(value)
955
956    @staticmethod
957    def format_fields(object, keys, indentation='', value_mappers={}):
958        if not keys:
959            return ''
960
961        # Measure the widest field name
962        max_field_name_length = max([len(key[0] if type(key) is tuple else key) for key in keys])
963
964        # Build array of formatted key:value pairs
965        fields = []
966        for key in keys:
967            value_mapper = None
968            if type(key) is tuple:
969                # The key has an associated specifier
970                key, specifier = key
971
972                # Get the value mapper from the specifier
973                if type(specifier) is dict:
974                    value_mapper = specifier.get('mapper')
975
976            # Get the value for the field
977            value = object[key]
978
979            # Map the value if needed
980            value_mapper = value_mappers.get(key, value_mapper)
981            if value_mapper is not None:
982                value = value_mapper(value)
983
984            # Get the string representation of the value
985            value_str = HCI_Object.format_field_value(value, indentation = indentation + '  ')
986
987            # Add the field to the formatted result
988            key_str = color(f'{key + ":":{1 + max_field_name_length}}', 'cyan')
989            fields.append(f'{indentation}{key_str} {value_str}')
990
991        return '\n'.join(fields)
992
993    def __bytes__(self):
994        return self.to_bytes()
995
996    def __init__(self, fields, **kwargs):
997        self.fields = fields
998        self.init_from_fields(self, fields, kwargs)
999
1000    def to_string(self, indentation='', value_mappers={}):
1001        return HCI_Object.format_fields(self.__dict__, self.fields, indentation, value_mappers)
1002
1003    def __str__(self):
1004        return self.to_string()
1005
1006
1007# -----------------------------------------------------------------------------
1008# Bluetooth Address
1009# -----------------------------------------------------------------------------
1010class Address:
1011    '''
1012    Bluetooth Address (see Bluetooth spec Vol 6, Part B - 1.3 DEVICE ADDRESS)
1013    NOTE: the address bytes are stored in little-endian byte order here, so
1014    address[0] is the LSB of the address, address[5] is the MSB.
1015    '''
1016
1017    PUBLIC_DEVICE_ADDRESS   = 0x00
1018    RANDOM_DEVICE_ADDRESS   = 0x01
1019    PUBLIC_IDENTITY_ADDRESS = 0x02
1020    RANDOM_IDENTITY_ADDRESS = 0x03
1021
1022    ADDRESS_TYPE_NAMES = {
1023        PUBLIC_DEVICE_ADDRESS:   'PUBLIC_DEVICE_ADDRESS',
1024        RANDOM_DEVICE_ADDRESS:   'RANDOM_DEVICE_ADDRESS',
1025        PUBLIC_IDENTITY_ADDRESS: 'PUBLIC_IDENTITY_ADDRESS',
1026        RANDOM_IDENTITY_ADDRESS: 'RANDOM_IDENTITY_ADDRESS'
1027    }
1028
1029    ADDRESS_TYPE_SPEC = {'size': 1, 'mapper': lambda x: Address.address_type_name(x)}
1030
1031    @staticmethod
1032    def address_type_name(address_type):
1033        return name_or_number(Address.ADDRESS_TYPE_NAMES, address_type)
1034
1035    @staticmethod
1036    def parse_address(data, offset):
1037        # Fix the type to a default value. This is used for parsing type-less Classic addresses
1038        return Address.parse_address_with_type(data, offset, Address.PUBLIC_DEVICE_ADDRESS)
1039
1040    @staticmethod
1041    def parse_address_with_type(data, offset, address_type):
1042        return offset + 6, Address(data[offset:offset + 6], address_type)
1043
1044    @staticmethod
1045    def parse_address_preceded_by_type(data, offset):
1046        address_type = data[offset - 1]
1047        return Address.parse_address_with_type(data, offset, address_type)
1048
1049    def __init__(self, address, address_type = RANDOM_DEVICE_ADDRESS):
1050        '''
1051        Initialize an instance. `address` may be a byte array in little-endian
1052        format, or a hex string in big-endian format (with optional ':'
1053        separators between the bytes).
1054        If the address is a string suffixed with '/P', `address_type` is ignored and the type
1055        is set to PUBLIC_DEVICE_ADDRESS.
1056        '''
1057        if type(address) is bytes:
1058            self.address_bytes = address
1059        else:
1060            # Check if there's a '/P' type specifier
1061            if address.endswith('P'):
1062                address_type = Address.PUBLIC_DEVICE_ADDRESS
1063                address = address[:-2]
1064
1065            if len(address) == 12 + 5:
1066                # Form with ':' separators
1067                address = address.replace(':', '')
1068            self.address_bytes = bytes(reversed(bytes.fromhex(address)))
1069
1070        if len(self.address_bytes) != 6:
1071            raise ValueError('invalid address length')
1072
1073        self.address_type = address_type
1074
1075    @property
1076    def is_public(self):
1077        return self.address_type == self.PUBLIC_DEVICE_ADDRESS or self.address_type == self.PUBLIC_IDENTITY_ADDRESS
1078
1079    @property
1080    def is_random(self):
1081        return not self.is_public
1082
1083    @property
1084    def is_resolved(self):
1085        return self.address_type == self.PUBLIC_IDENTITY_ADDRESS or self.address_type == self.RANDOM_IDENTITY_ADDRESS
1086
1087    @property
1088    def is_resolvable(self):
1089        return self.address_type == self.RANDOM_DEVICE_ADDRESS and (self.address_bytes[5] >> 6 == 1)
1090
1091    @property
1092    def is_static(self):
1093        return self.is_random and (self.address_bytes[5] >> 6 == 3)
1094
1095    def to_bytes(self):
1096        return self.address_bytes
1097
1098    def __bytes__(self):
1099        return self.to_bytes()
1100
1101    def __hash__(self):
1102        return hash(self.address_bytes)
1103
1104    def __eq__(self, other):
1105        return self.address_bytes == other.address_bytes and self.is_public == other.is_public
1106
1107    def __str__(self):
1108        '''
1109        String representation of the address, MSB first
1110        '''
1111        return ':'.join([f'{x:02X}' for x in reversed(self.address_bytes)])
1112
1113
1114# -----------------------------------------------------------------------------
1115class HCI_Packet:
1116    '''
1117    Abstract Base class for HCI packets
1118    '''
1119
1120    @staticmethod
1121    def from_bytes(packet):
1122        packet_type = packet[0]
1123        if packet_type == HCI_COMMAND_PACKET:
1124            return HCI_Command.from_bytes(packet)
1125        elif packet_type == HCI_ACL_DATA_PACKET:
1126            return HCI_AclDataPacket.from_bytes(packet)
1127        elif packet_type == HCI_EVENT_PACKET:
1128            return HCI_Event.from_bytes(packet)
1129        else:
1130            return HCI_CustomPacket(packet)
1131
1132    def __init__(self, name):
1133        self.name = name
1134
1135    def __repr__(self) -> str:
1136        return self.name
1137
1138
1139# -----------------------------------------------------------------------------
1140class HCI_CustomPacket(HCI_Packet):
1141    def __init__(self, payload):
1142        super().__init__('HCI_CUSTOM_PACKET')
1143        self.hci_packet_type = payload[0]
1144        self.payload         = payload
1145
1146
1147# -----------------------------------------------------------------------------
1148class HCI_Command(HCI_Packet):
1149    '''
1150    See Bluetooth spec @ Vol 2, Part E - 5.4.1 HCI Command Packet
1151    '''
1152    hci_packet_type = HCI_COMMAND_PACKET
1153    command_classes = {}
1154
1155    @staticmethod
1156    def command(fields=[], return_parameters_fields=[]):
1157        '''
1158        Decorator used to declare and register subclasses
1159        '''
1160
1161        def inner(cls):
1162            cls.name = cls.__name__.upper()
1163            cls.op_code = key_with_value(HCI_COMMAND_NAMES, cls.name)
1164            if cls.op_code is None:
1165                raise KeyError('command not found in HCI_COMMAND_NAMES')
1166            cls.fields = fields
1167            cls.return_parameters_fields = return_parameters_fields
1168
1169            # Patch the __init__ method to fix the op_code
1170            def init(self, parameters=None, **kwargs):
1171                return HCI_Command.__init__(self, cls.op_code, parameters, **kwargs)
1172            cls.__init__ = init
1173
1174            # Register a factory for this class
1175            HCI_Command.command_classes[cls.op_code] = cls
1176
1177            return cls
1178
1179        return inner
1180
1181    @staticmethod
1182    def from_bytes(packet):
1183        op_code, length = struct.unpack_from('<HB', packet, 1)
1184        parameters = packet[4:]
1185        if len(parameters) != length:
1186            raise ValueError('invalid packet length')
1187
1188        # Look for a registered class
1189        cls = HCI_Command.command_classes.get(op_code)
1190        if cls is None:
1191            # No class registered, just use a generic instance
1192            return HCI_Command(op_code, parameters)
1193
1194        # Create a new instance
1195        self = cls.__new__(cls)
1196        HCI_Command.__init__(self, op_code, parameters)
1197        if fields := getattr(self, 'fields', None):
1198            HCI_Object.init_from_bytes(self, parameters, 0, fields)
1199        return self
1200
1201    @staticmethod
1202    def command_name(op_code):
1203        name = HCI_COMMAND_NAMES.get(op_code)
1204        if name is not None:
1205            return name
1206        return f'[OGF=0x{op_code >> 10:02x}, OCF=0x{op_code & 0x3FF:04x}]'
1207
1208    @classmethod
1209    def create_return_parameters(cls, **kwargs):
1210        return HCI_Object(cls.return_parameters_fields, **kwargs)
1211
1212    def __init__(self, op_code, parameters=None, **kwargs):
1213        super().__init__(HCI_Command.command_name(op_code))
1214        if (fields := getattr(self, 'fields', None)) and kwargs:
1215            HCI_Object.init_from_fields(self, fields, kwargs)
1216            if parameters is None:
1217                parameters = HCI_Object.dict_to_bytes(kwargs, fields)
1218        self.op_code    = op_code
1219        self.parameters = parameters
1220
1221    def to_bytes(self):
1222        parameters = b'' if self.parameters is None else self.parameters
1223        return struct.pack('<BHB', HCI_COMMAND_PACKET, self.op_code, len(parameters)) + parameters
1224
1225    def __bytes__(self):
1226        return self.to_bytes()
1227
1228    def __str__(self):
1229        result = color(self.name, 'green')
1230        if fields := getattr(self, 'fields', None):
1231            result += ':\n' + HCI_Object.format_fields(self.__dict__, fields, '  ')
1232        else:
1233            if self.parameters:
1234                result += f': {self.parameters.hex()}'
1235        return result
1236
1237
1238# -----------------------------------------------------------------------------
1239@HCI_Command.command([
1240    ('lap',            {'size': 3, 'mapper': HCI_Constant.inquiry_lap_name}),
1241    ('inquiry_length', 1),
1242    ('num_responses',  1)
1243])
1244class HCI_Inquiry_Command(HCI_Command):
1245    '''
1246    See Bluetooth spec @ 7.1.1 Inquiry Command
1247    '''
1248
1249
1250# -----------------------------------------------------------------------------
1251@HCI_Command.command()
1252class HCI_Inquiry_Cancel_Command(HCI_Command):
1253    '''
1254    See Bluetooth spec @ 7.1.2 Inquiry Cancel Command
1255    '''
1256
1257
1258# -----------------------------------------------------------------------------
1259@HCI_Command.command([
1260    ('bd_addr',                   Address.parse_address),
1261    ('packet_type',               2),
1262    ('page_scan_repetition_mode', 1),
1263    ('reserved',                  1),
1264    ('clock_offset',              2),
1265    ('allow_role_switch',         1)
1266])
1267class HCI_Create_Connection_Command(HCI_Command):
1268    '''
1269    See Bluetooth spec @ 7.1.5 Create Connection Command
1270    '''
1271
1272
1273# -----------------------------------------------------------------------------
1274@HCI_Command.command([
1275    ('connection_handle', 2),
1276    ('reason',            {'size': 1, 'mapper': HCI_Constant.error_name})
1277])
1278class HCI_Disconnect_Command(HCI_Command):
1279    '''
1280    See Bluetooth spec @ 7.1.6 Disconnect Command
1281    '''
1282
1283
1284# -----------------------------------------------------------------------------
1285@HCI_Command.command([
1286    ('bd_addr', Address.parse_address),
1287    ('role',    1)
1288])
1289class HCI_Accept_Connection_Request_Command(HCI_Command):
1290    '''
1291    See Bluetooth spec @ 7.1.8 Accept Connection Request Command
1292    '''
1293
1294
1295# -----------------------------------------------------------------------------
1296@HCI_Command.command([
1297    ('bd_addr',  Address.parse_address),
1298    ('link_key', 16)
1299])
1300class HCI_Link_Key_Request_Reply_Command(HCI_Command):
1301    '''
1302    See Bluetooth spec @ 7.1.10 Link Key Request Reply Command
1303    '''
1304
1305
1306# -----------------------------------------------------------------------------
1307@HCI_Command.command(
1308    fields=[
1309        ('bd_addr', Address.parse_address)
1310    ],
1311    return_parameters_fields=[
1312        ('status',  STATUS_SPEC),
1313        ('bd_addr', Address.parse_address)
1314    ]
1315)
1316class HCI_Link_Key_Request_Negative_Reply_Command(HCI_Command):
1317    '''
1318    See Bluetooth spec @ 7.1.11 Link Key Request Negative Reply Command
1319    '''
1320
1321
1322# -----------------------------------------------------------------------------
1323@HCI_Command.command(
1324    fields=[
1325        ('bd_addr', Address.parse_address)
1326    ],
1327    return_parameters_fields=[
1328        ('status',  STATUS_SPEC),
1329        ('bd_addr', Address.parse_address)
1330    ]
1331)
1332class HCI_PIN_Code_Request_Negative_Reply_Command(HCI_Command):
1333    '''
1334    See Bluetooth spec @ 7.1.13 PIN Code Request Negative Reply Command
1335    '''
1336
1337
1338# -----------------------------------------------------------------------------
1339@HCI_Command.command([
1340    ('connection_handle', 2),
1341    ('packet_type',       2)
1342])
1343class HCI_Change_Connection_Packet_Type_Command(HCI_Command):
1344    '''
1345    See Bluetooth spec @ 7.1.14 Change Connection Packet Type Command
1346    '''
1347
1348
1349# -----------------------------------------------------------------------------
1350@HCI_Command.command([
1351    ('connection_handle', 2)
1352])
1353class HCI_Authentication_Requested_Command(HCI_Command):
1354    '''
1355    See Bluetooth spec @ 7.1.15 Authentication Requested Command
1356    '''
1357
1358
1359# -----------------------------------------------------------------------------
1360@HCI_Command.command([
1361    ('connection_handle', 2),
1362    ('encryption_enable', 1)
1363])
1364class HCI_Set_Connection_Encryption_Command(HCI_Command):
1365    '''
1366    See Bluetooth spec @ 7.1.16 Set Connection Encryption Command
1367    '''
1368
1369
1370# -----------------------------------------------------------------------------
1371@HCI_Command.command([
1372    ('bd_addr',                   Address.parse_address),
1373    ('page_scan_repetition_mode', 1),
1374    ('reserved',                  1),
1375    ('clock_offset',              2)
1376])
1377class HCI_Remote_Name_Request_Command(HCI_Command):
1378    '''
1379    See Bluetooth spec @ 7.1.19 Remote Name Request Command
1380    '''
1381    R0 = 0x00
1382    R1 = 0x01
1383    R2 = 0x02
1384
1385
1386# -----------------------------------------------------------------------------
1387@HCI_Command.command([
1388    ('connection_handle', 2)
1389])
1390class HCI_Read_Remote_Supported_Features_Command(HCI_Command):
1391    '''
1392    See Bluetooth spec @ 7.1.21 Read Remote Supported Features Command
1393    '''
1394
1395
1396# -----------------------------------------------------------------------------
1397@HCI_Command.command([
1398    ('connection_handle', 2),
1399    ('page_number',       1)
1400])
1401class HCI_Read_Remote_Extended_Features_Command(HCI_Command):
1402    '''
1403    See Bluetooth spec @ 7.1.22 Read Remote Extended Features Command
1404    '''
1405
1406
1407# -----------------------------------------------------------------------------
1408@HCI_Command.command([
1409    ('connection_handle', 2)
1410])
1411class HCI_Read_Remote_Version_Information_Command(HCI_Command):
1412    '''
1413    See Bluetooth spec @ 7.1.23 Read Remote Version Information Command
1414    '''
1415
1416
1417# -----------------------------------------------------------------------------
1418@HCI_Command.command([
1419    ('connection_handle', 2)
1420])
1421class HCI_Read_Clock_Offset_Command(HCI_Command):
1422    '''
1423    See Bluetooth spec @ 7.1.23 Read Clock Offset Command
1424    '''
1425
1426
1427# -----------------------------------------------------------------------------
1428@HCI_Command.command(
1429    fields=[
1430        ('bd_addr',                     Address.parse_address),
1431        ('io_capability',               {'size': 1, 'mapper': HCI_Constant.io_capability_name}),
1432        ('oob_data_present',            1),
1433        ('authentication_requirements', {'size': 1, 'mapper': HCI_Constant.authentication_requirements_name})
1434    ],
1435    return_parameters_fields=[
1436        ('status',  STATUS_SPEC),
1437        ('bd_addr', Address.parse_address)
1438    ]
1439)
1440class HCI_IO_Capability_Request_Reply_Command(HCI_Command):
1441    '''
1442    See Bluetooth spec @ 7.1.29 IO Capability Request Reply Command
1443    '''
1444
1445
1446# -----------------------------------------------------------------------------
1447@HCI_Command.command(
1448    fields=[
1449        ('bd_addr', Address.parse_address)
1450    ],
1451    return_parameters_fields=[
1452        ('status',  STATUS_SPEC),
1453        ('bd_addr', Address.parse_address)
1454    ]
1455)
1456class HCI_User_Confirmation_Request_Reply_Command(HCI_Command):
1457    '''
1458    See Bluetooth spec @ 7.1.30 User Confirmation Request Reply Command
1459    '''
1460
1461
1462# -----------------------------------------------------------------------------
1463@HCI_Command.command(
1464    fields=[
1465        ('bd_addr', Address.parse_address)
1466    ],
1467    return_parameters_fields=[
1468        ('status',  STATUS_SPEC),
1469        ('bd_addr', Address.parse_address)
1470    ]
1471)
1472class HCI_User_Confirmation_Request_Negative_Reply_Command(HCI_Command):
1473    '''
1474    See Bluetooth spec @ 7.1.31 User Confirmation Request Negative Reply Command
1475    '''
1476
1477
1478# -----------------------------------------------------------------------------
1479@HCI_Command.command(
1480    fields=[
1481        ('bd_addr', Address.parse_address),
1482        ('numeric_value', 4)
1483    ],
1484    return_parameters_fields=[
1485        ('status',  STATUS_SPEC),
1486        ('bd_addr', Address.parse_address)
1487    ]
1488)
1489class HCI_User_Passkey_Request_Reply_Command(HCI_Command):
1490    '''
1491    See Bluetooth spec @ 7.1.32 User Passkey Request Reply Command
1492    '''
1493
1494
1495# -----------------------------------------------------------------------------
1496@HCI_Command.command(
1497    fields=[
1498        ('bd_addr', Address.parse_address)
1499    ],
1500    return_parameters_fields=[
1501        ('status',  STATUS_SPEC),
1502        ('bd_addr', Address.parse_address)
1503    ]
1504)
1505class HCI_User_Passkey_Request_Negative_Reply_Command(HCI_Command):
1506    '''
1507    See Bluetooth spec @ 7.1.33 User Passkey Request Negative Reply Command
1508    '''
1509
1510
1511# -----------------------------------------------------------------------------
1512@HCI_Command.command([
1513    ('connection_handle',                      2),
1514    ('transmit_bandwidth',                     4),
1515    ('receive_bandwidth',                      4),
1516    ('transmit_coding_format',                 5),
1517    ('receive_coding_format',                  5),
1518    ('transmit_codec_frame_size',              2),
1519    ('receive_codec_frame_size',               2),
1520    ('input_bandwidth',                        4),
1521    ('output_bandwidth',                       4),
1522    ('input_coding_format',                    5),
1523    ('output_coding_format',                   5),
1524    ('input_coded_data_size',                  2),
1525    ('output_coded_data_size',                 2),
1526    ('input_pcm_data_format',                  1),
1527    ('output_pcm_data_format',                 1),
1528    ('input_pcm_sample_payload_msb_position',  1),
1529    ('output_pcm_sample_payload_msb_position', 1),
1530    ('input_data_path',                        1),
1531    ('output_data_path',                       1),
1532    ('input_transport_unit_size',              1),
1533    ('output_transport_unit_size',             1),
1534    ('max_latency',                            2),
1535    ('packet_type',                            2),
1536    ('retransmission_effort',                  1)
1537])
1538class HCI_Enhanced_Setup_Synchronous_Connection_Command(HCI_Command):
1539    '''
1540    See Bluetooth spec @ 7.1.45 Enhanced Setup Synchronous Connection Command
1541    '''
1542
1543
1544# -----------------------------------------------------------------------------
1545@HCI_Command.command([
1546    ('connection_handle',  2),
1547    ('sniff_max_interval', 2),
1548    ('sniff_min_interval', 2),
1549    ('sniff_attempt',      2),
1550    ('sniff_timeout',      2)
1551])
1552class HCI_Sniff_Mode_Command(HCI_Command):
1553    '''
1554    See Bluetooth spec @ 7.2.2 Sniff Mode Command
1555    '''
1556
1557
1558# -----------------------------------------------------------------------------
1559@HCI_Command.command([
1560    ('connection_handle', 2)
1561])
1562class HCI_Exit_Sniff_Mode_Command(HCI_Command):
1563    '''
1564    See Bluetooth spec @ 7.2.3 Exit Sniff Mode Command
1565    '''
1566
1567
1568# -----------------------------------------------------------------------------
1569@HCI_Command.command([
1570    ('bd_addr', Address.parse_address),
1571    ('role',    {'size': 1, 'mapper': HCI_Constant.role_name})
1572])
1573class HCI_Switch_Role_Command(HCI_Command):
1574    '''
1575    See Bluetooth spec @ 7.2.8 Switch Role Command
1576    '''
1577
1578
1579# -----------------------------------------------------------------------------
1580@HCI_Command.command([
1581    ('connection_handle',    2),
1582    ('link_policy_settings', 2)
1583])
1584class HCI_Write_Link_Policy_Settings_Command(HCI_Command):
1585    '''
1586    See Bluetooth spec @ 7.2.10 Write Link Policy Settings Command
1587    '''
1588
1589
1590# -----------------------------------------------------------------------------
1591@HCI_Command.command([
1592    ('default_link_policy_settings', 2)
1593])
1594class HCI_Write_Default_Link_Policy_Settings_Command(HCI_Command):
1595    '''
1596    See Bluetooth spec @ 7.2.12 Write Default Link Policy Settings Command
1597    '''
1598
1599
1600# -----------------------------------------------------------------------------
1601@HCI_Command.command([
1602    ('connection_handle',      2),
1603    ('maximum_latency',        2),
1604    ('minimum_remote_timeout', 2),
1605    ('minimum_local_timeout',  2)
1606])
1607class HCI_Sniff_Subrating_Command(HCI_Command):
1608    '''
1609    See Bluetooth spec @ 7.2.14 Sniff Subrating Command
1610    '''
1611
1612
1613# -----------------------------------------------------------------------------
1614@HCI_Command.command([
1615    ('event_mask', 8)
1616])
1617class HCI_Set_Event_Mask_Command(HCI_Command):
1618    '''
1619    See Bluetooth spec @ 7.3.1 Set Event Mask Command
1620    '''
1621
1622
1623# -----------------------------------------------------------------------------
1624@HCI_Command.command()
1625class HCI_Reset_Command(HCI_Command):
1626    '''
1627    See Bluetooth spec @ 7.3.2 Reset Command
1628    '''
1629
1630
1631# -----------------------------------------------------------------------------
1632@HCI_Command.command([
1633    ('filter_type',       1),
1634    ('filter_condition', '*'),
1635])
1636class HCI_Set_Event_Filter_Command(HCI_Command):
1637    '''
1638    See Bluetooth spec @ 7.3.3 Set Event Filter Command
1639    '''
1640
1641
1642# -----------------------------------------------------------------------------
1643@HCI_Command.command(
1644    fields=[
1645        ('bd_addr',       Address.parse_address),
1646        ('read_all_flag', 1)
1647    ],
1648    return_parameters_fields=[
1649        ('status',        STATUS_SPEC),
1650        ('max_num_keys',  2),
1651        ('num_keys_read', 2)
1652    ]
1653)
1654class HCI_Read_Stored_Link_Key_Command(HCI_Command):
1655    '''
1656    See Bluetooth spec @ 7.3.8 Read Stored Link Key Command
1657    '''
1658
1659
1660# -----------------------------------------------------------------------------
1661@HCI_Command.command(
1662    fields=[
1663        ('bd_addr',         Address.parse_address),
1664        ('delete_all_flag', 1)
1665    ],
1666    return_parameters_fields=[
1667        ('status',           STATUS_SPEC),
1668        ('num_keys_deleted', 2)
1669    ]
1670)
1671class HCI_Delete_Stored_Link_Key_Command(HCI_Command):
1672    '''
1673    See Bluetooth spec @ 7.3.10 Delete Stored Link Key Command
1674    '''
1675
1676
1677# -----------------------------------------------------------------------------
1678@HCI_Command.command([
1679    ('local_name', {'size': 248, 'mapper': map_null_terminated_utf8_string})
1680])
1681class HCI_Write_Local_Name_Command(HCI_Command):
1682    '''
1683    See Bluetooth spec @ 7.3.11 Write Local Name Command
1684    '''
1685
1686
1687# -----------------------------------------------------------------------------
1688@HCI_Command.command(return_parameters_fields=[
1689    ('status',     STATUS_SPEC),
1690    ('local_name', {'size': 248, 'mapper': map_null_terminated_utf8_string})
1691])
1692class HCI_Read_Local_Name_Command(HCI_Command):
1693    '''
1694    See Bluetooth spec @ 7.3.12 Read Local Name Command
1695    '''
1696
1697
1698# -----------------------------------------------------------------------------
1699@HCI_Command.command([
1700    ('conn_accept_timeout', 2)
1701])
1702class HCI_Write_Connection_Accept_Timeout_Command(HCI_Command):
1703    '''
1704    See Bluetooth spec @ 7.3.14 Write Connection Accept Timeout Command
1705    '''
1706
1707
1708# -----------------------------------------------------------------------------
1709@HCI_Command.command([
1710    ('page_timeout', 2)
1711])
1712class HCI_Write_Page_Timeout_Command(HCI_Command):
1713    '''
1714    See Bluetooth spec @ 7.3.16 Write Page Timeout Command
1715    '''
1716
1717
1718# -----------------------------------------------------------------------------
1719@HCI_Command.command([
1720    ('scan_enable', 1)
1721])
1722class HCI_Write_Scan_Enable_Command(HCI_Command):
1723    '''
1724    See Bluetooth spec @ 7.3.18 Write Scan Enable Command
1725    '''
1726
1727
1728# -----------------------------------------------------------------------------
1729@HCI_Command.command(return_parameters_fields=[
1730    ('status',             STATUS_SPEC),
1731    ('page_scan_interval', 2),
1732    ('page_scan_window',   2)
1733])
1734class HCI_Read_Page_Scan_Activity_Command(HCI_Command):
1735    '''
1736    See Bluetooth spec @ 7.3.19 Read Page Scan Activity Command
1737    '''
1738
1739
1740# -----------------------------------------------------------------------------
1741@HCI_Command.command([
1742    ('page_scan_interval', 2),
1743    ('page_scan_window',   2)
1744])
1745class HCI_Write_Page_Scan_Activity_Command(HCI_Command):
1746    '''
1747    See Bluetooth spec @ 7.3.20 Write Page Scan Activity Command
1748    '''
1749
1750
1751# -----------------------------------------------------------------------------
1752@HCI_Command.command([
1753    ('inquiry_scan_interval', 2),
1754    ('inquiry_scan_window',   2)
1755])
1756class HCI_Write_Inquiry_Scan_Activity_Command(HCI_Command):
1757    '''
1758    See Bluetooth spec @ 7.3.22 Write Inquiry Scan Activity Command
1759    '''
1760
1761
1762# -----------------------------------------------------------------------------
1763@HCI_Command.command(return_parameters_fields=[
1764    ('status',          STATUS_SPEC),
1765    ('class_of_device', {'size': 3, 'mapper': map_class_of_device})
1766])
1767class HCI_Read_Class_Of_Device_Command(HCI_Command):
1768    '''
1769    See Bluetooth spec @ 7.3.25 Read Class of Device Command
1770    '''
1771
1772
1773# -----------------------------------------------------------------------------
1774@HCI_Command.command([
1775    ('class_of_device', {'size': 3, 'mapper': map_class_of_device})
1776])
1777class HCI_Write_Class_Of_Device_Command(HCI_Command):
1778    '''
1779    See Bluetooth spec @ 7.3.26 Write Class of Device Command
1780    '''
1781
1782
1783# -----------------------------------------------------------------------------
1784@HCI_Command.command(return_parameters_fields=[
1785    ('status',        STATUS_SPEC),
1786    ('voice_setting', 2)
1787])
1788class HCI_Read_Voice_Setting_Command(HCI_Command):
1789    '''
1790    See Bluetooth spec @ 7.3.27 Read Voice Setting Command
1791    '''
1792
1793
1794# -----------------------------------------------------------------------------
1795@HCI_Command.command([
1796    ('voice_setting', 2)
1797])
1798class HCI_Write_Voice_Setting_Command(HCI_Command):
1799    '''
1800    See Bluetooth spec @ 7.3.28 Write Voice Setting Command
1801    '''
1802
1803
1804# -----------------------------------------------------------------------------
1805class HCI_Read_Synchronous_Flow_Control_Enable_Command(HCI_Command):
1806    '''
1807    See Bluetooth spec @ 7.3.36 Write Synchronous Flow Control Enable Command
1808    '''
1809
1810
1811# -----------------------------------------------------------------------------
1812@HCI_Command.command([
1813    ('synchronous_flow_control_enable', 1)
1814])
1815class HCI_Write_Synchronous_Flow_Control_Enable_Command(HCI_Command):
1816    '''
1817    See Bluetooth spec @ 7.3.37 Write Synchronous Flow Control Enable Command
1818    '''
1819
1820
1821# -----------------------------------------------------------------------------
1822@HCI_Command.command([
1823    ('host_acl_data_packet_length',             2),
1824    ('host_synchronous_data_packet_length',     1),
1825    ('host_total_num_acl_data_packets',         2),
1826    ('host_total_num_synchronous_data_packets', 2)
1827])
1828class HCI_Host_Buffer_Size_Command(HCI_Command):
1829    '''
1830    See Bluetooth spec @ 7.3.39 Host Buffer Size Command
1831    '''
1832
1833
1834# -----------------------------------------------------------------------------
1835@HCI_Command.command(
1836    fields=[
1837        ('handle',                   2),
1838        ('link_supervision_timeout', 2)
1839    ],
1840    return_parameters_fields=[
1841        ('status', STATUS_SPEC),
1842        ('handle', 2),
1843    ]
1844)
1845class HCI_Write_Link_Supervision_Timeout_Command(HCI_Command):
1846    '''
1847    See Bluetooth spec @ 7.3.42 Write Link Supervision Timeout Command
1848    '''
1849
1850
1851# -----------------------------------------------------------------------------
1852@HCI_Command.command(return_parameters_fields=[
1853    ('status',          STATUS_SPEC),
1854    ('num_support_iac', 1)
1855])
1856class HCI_Read_Number_Of_Supported_IAC_Command(HCI_Command):
1857    '''
1858    See Bluetooth spec @ 7.3.43 Read Number Of Supported IAC Command
1859    '''
1860
1861
1862# -----------------------------------------------------------------------------
1863@HCI_Command.command(return_parameters_fields=[
1864    ('status',          STATUS_SPEC),
1865    ('num_current_iac', 1),
1866    ('iac_lap',         '*')  # TODO: this should be parsed as an array
1867])
1868class HCI_Read_Current_IAC_LAP_Command(HCI_Command):
1869    '''
1870    See Bluetooth spec @ 7.3.44 Read Current IAC LAP Command
1871    '''
1872
1873
1874# -----------------------------------------------------------------------------
1875@HCI_Command.command([
1876    ('scan_type', 1)
1877])
1878class HCI_Write_Inquiry_Scan_Type_Command(HCI_Command):
1879    '''
1880    See Bluetooth spec @ 7.3.48 Write Inquiry Scan Type Command
1881    '''
1882
1883
1884# -----------------------------------------------------------------------------
1885@HCI_Command.command([
1886    ('inquiry_mode', 1)
1887])
1888class HCI_Write_Inquiry_Mode_Command(HCI_Command):
1889    '''
1890    See Bluetooth spec @ 7.3.50 Write Inquiry Mode Command
1891    '''
1892
1893
1894# -----------------------------------------------------------------------------
1895@HCI_Command.command(return_parameters_fields=[
1896    ('status',         STATUS_SPEC),
1897    ('page_scan_type', 1)
1898])
1899class HCI_Read_Page_Scan_Type_Command(HCI_Command):
1900    '''
1901    See Bluetooth spec @ 7.3.51 Read Page Scan Type Command
1902    '''
1903
1904
1905# -----------------------------------------------------------------------------
1906@HCI_Command.command([
1907    ('page_scan_type', 1)
1908])
1909class HCI_Write_Page_Scan_Type_Command(HCI_Command):
1910    '''
1911    See Bluetooth spec @ 7.3.52 Write Page Scan Type Command
1912    '''
1913
1914
1915# -----------------------------------------------------------------------------
1916@HCI_Command.command([
1917    ('fec_required',              1),
1918    ('extended_inquiry_response', {'size': 240, 'serializer': lambda x: padded_bytes(x, 240)})
1919])
1920class HCI_Write_Extended_Inquiry_Response_Command(HCI_Command):
1921    '''
1922    See Bluetooth spec @ 7.3.56 Write Extended Inquiry Response Command
1923    '''
1924
1925
1926# -----------------------------------------------------------------------------
1927@HCI_Command.command([
1928    ('simple_pairing_mode', 1)
1929])
1930class HCI_Write_Simple_Pairing_Mode_Command(HCI_Command):
1931    '''
1932    See Bluetooth spec @ 7.3.59 Write Simple Pairing Mode Command
1933    '''
1934
1935
1936# -----------------------------------------------------------------------------
1937@HCI_Command.command(return_parameters_fields=[
1938    ('status',   STATUS_SPEC),
1939    ('tx_power', -1)
1940])
1941class HCI_Read_Inquiry_Response_Transmit_Power_Level_Command(HCI_Command):
1942    '''
1943    See Bluetooth spec @ 7.3.61 Read Inquiry Response Transmit Power Level Command
1944    '''
1945
1946
1947# -----------------------------------------------------------------------------
1948@HCI_Command.command(return_parameters_fields=[
1949    ('status',                   STATUS_SPEC),
1950    ('erroneous_data_reporting', 1)
1951])
1952class HCI_Read_Default_Erroneous_Data_Reporting_Command(HCI_Command):
1953    '''
1954    See Bluetooth spec @ 7.3.64 Read Default Erroneous Data Reporting Command
1955    '''
1956
1957
1958# -----------------------------------------------------------------------------
1959@HCI_Command.command([
1960    ('event_mask_page_2', 8)
1961])
1962class HCI_Set_Event_Mask_Page_2_Command(HCI_Command):
1963    '''
1964    See Bluetooth spec @ 7.3.69 Set Event Mask Page 2 Command
1965    '''
1966
1967
1968# -----------------------------------------------------------------------------
1969@HCI_Command.command()
1970class HCI_Read_LE_Host_Support_Command(HCI_Command):
1971    '''
1972    See Bluetooth spec @ 7.3.78 Read LE Host Support Command
1973    '''
1974
1975
1976# -----------------------------------------------------------------------------
1977@HCI_Command.command([
1978    ('le_supported_host',    1),
1979    ('simultaneous_le_host', 1)
1980])
1981class HCI_Write_LE_Host_Support_Command(HCI_Command):
1982    '''
1983    See Bluetooth spec @ 7.3.79 Write LE Host Support Command
1984    '''
1985
1986
1987# -----------------------------------------------------------------------------
1988@HCI_Command.command([
1989    ('secure_connections_host_support', 1)
1990])
1991class HCI_Write_Secure_Connections_Host_Support_Command(HCI_Command):
1992    '''
1993    See Bluetooth spec @ 7.3.92 Write Secure Connections Host Support Command
1994    '''
1995
1996
1997# -----------------------------------------------------------------------------
1998@HCI_Command.command([
1999    ('connection_handle',             2),
2000    ('authenticated_payload_timeout', 2)
2001])
2002class HCI_Write_Authenticated_Payload_Timeout_Command(HCI_Command):
2003    '''
2004    See Bluetooth spec @ 7.3.94 Write Authenticated Payload Timeout Command
2005    '''
2006
2007
2008# -----------------------------------------------------------------------------
2009@HCI_Command.command(return_parameters_fields=[
2010    ('status',             STATUS_SPEC),
2011    ('hci_version',        1),
2012    ('hci_revsion',        2),
2013    ('lmp_pal_version',    1),
2014    ('manufacturer_name',  2),
2015    ('lmp_pal_subversion', 2)
2016])
2017class HCI_Read_Local_Version_Information_Command(HCI_Command):
2018    '''
2019    See Bluetooth spec @ 7.4.1 Read Local Version Information Command
2020    '''
2021
2022
2023# -----------------------------------------------------------------------------
2024@HCI_Command.command(return_parameters_fields=[
2025    ('status',             STATUS_SPEC),
2026    ('supported_commands', 64)
2027])
2028class HCI_Read_Local_Supported_Commands_Command(HCI_Command):
2029    '''
2030    See Bluetooth spec @ 7.4.2 Read Local Supported Commands Command
2031    '''
2032
2033
2034# -----------------------------------------------------------------------------
2035@HCI_Command.command()
2036class HCI_Read_Local_Supported_Features_Command(HCI_Command):
2037    '''
2038    See Bluetooth spec @ 7.4.3 Read Local Supported Features Command
2039    '''
2040
2041
2042# -----------------------------------------------------------------------------
2043@HCI_Command.command(
2044    fields=[
2045        ('page_number', 1)
2046    ],
2047    return_parameters_fields=[
2048        ('status',                STATUS_SPEC),
2049        ('page_number',           1),
2050        ('maximum_page_number',   1),
2051        ('extended_lmp_features', 8)
2052    ]
2053)
2054class HCI_Read_Local_Extended_Features_Command(HCI_Command):
2055    '''
2056    See Bluetooth spec @ 7.4.4 Read Local Extended Features Command
2057    '''
2058
2059
2060# -----------------------------------------------------------------------------
2061@HCI_Command.command(return_parameters_fields=[
2062    ('status',                                STATUS_SPEC),
2063    ('hc_acl_data_packet_length',             2),
2064    ('hc_synchronous_data_packet_length',     1),
2065    ('hc_total_num_acl_data_packets',         2),
2066    ('hc_total_num_synchronous_data_packets', 2)
2067])
2068class HCI_Read_Buffer_Size_Command(HCI_Command):
2069    '''
2070    See Bluetooth spec @ 7.4.5 Read Buffer Size Command
2071    '''
2072
2073
2074# -----------------------------------------------------------------------------
2075@HCI_Command.command(return_parameters_fields=[
2076    ('status',  STATUS_SPEC),
2077    ('bd_addr', Address.parse_address)
2078])
2079class HCI_Read_BD_ADDR_Command(HCI_Command):
2080    '''
2081    See Bluetooth spec @ 7.4.6 Read BD_ADDR Command
2082    '''
2083
2084
2085# -----------------------------------------------------------------------------
2086@HCI_Command.command()
2087class HCI_Read_Local_Supported_Codecs_Command(HCI_Command):
2088    '''
2089    See Bluetooth spec @ 7.4.8 Read Local Supported Codecs Command
2090    '''
2091
2092
2093# -----------------------------------------------------------------------------
2094@HCI_Command.command(
2095    fields=[
2096        ('connection_handle', 2)
2097    ],
2098    return_parameters_fields=[
2099        ('status',            STATUS_SPEC),
2100        ('connection_handle', 2),
2101        ('key_size',          1)
2102    ]
2103)
2104class HCI_Read_Encryption_Key_Size_Command(HCI_Command):
2105    '''
2106    See Bluetooth spec @ 7.5.7 Read Encryption Key Size Command
2107    '''
2108
2109
2110# -----------------------------------------------------------------------------
2111@HCI_Command.command([
2112    ('le_event_mask', 8)
2113])
2114class HCI_LE_Set_Event_Mask_Command(HCI_Command):
2115    '''
2116    See Bluetooth spec @ 7.8.1 LE Set Event Mask Command
2117    '''
2118
2119
2120# -----------------------------------------------------------------------------
2121@HCI_Command.command(return_parameters_fields=[
2122    ('status',                           STATUS_SPEC),
2123    ('hc_le_acl_data_packet_length',     2),
2124    ('hc_total_num_le_acl_data_packets', 1)
2125])
2126class HCI_LE_Read_Buffer_Size_Command(HCI_Command):
2127    '''
2128    See Bluetooth spec @ 7.8.2 LE Read Buffer Size Command
2129    '''
2130
2131
2132# -----------------------------------------------------------------------------
2133@HCI_Command.command([
2134    ('random_address', lambda data, offset: Address.parse_address_with_type(data, offset, Address.RANDOM_DEVICE_ADDRESS))
2135])
2136class HCI_LE_Set_Random_Address_Command(HCI_Command):
2137    '''
2138    See Bluetooth spec @ 7.8.4 LE Set Random Address Command
2139    '''
2140
2141
2142# -----------------------------------------------------------------------------
2143@HCI_Command.command([
2144    ('advertising_interval_min',  2),
2145    ('advertising_interval_max',  2),
2146    ('advertising_type',          {'size': 1, 'mapper': lambda x: HCI_LE_Set_Advertising_Parameters_Command.advertising_type_name(x)}),
2147    ('own_address_type',          Address.ADDRESS_TYPE_SPEC),
2148    ('peer_address_type',         Address.ADDRESS_TYPE_SPEC),
2149    ('peer_address',              Address.parse_address_preceded_by_type),
2150    ('advertising_channel_map',   1),
2151    ('advertising_filter_policy', 1),
2152])
2153class HCI_LE_Set_Advertising_Parameters_Command(HCI_Command):
2154    '''
2155    See Bluetooth spec @ 7.8.5 LE Set Advertising Parameters Command
2156    '''
2157
2158    ADV_IND         = 0x00
2159    ADV_DIRECT_IND  = 0x01
2160    ADV_SCAN_IND    = 0x02
2161    ADV_NONCONN_IND = 0x03
2162    ADV_DIRECT_IND  = 0x04
2163
2164    ADVERTISING_TYPE_NAMES = {
2165        ADV_IND:         'ADV_IND',
2166        ADV_DIRECT_IND:  'ADV_DIRECT_IND',
2167        ADV_SCAN_IND:    'ADV_SCAN_IND',
2168        ADV_NONCONN_IND: 'ADV_NONCONN_IND',
2169        ADV_DIRECT_IND:  'ADV_DIRECT_IND'
2170    }
2171
2172    @classmethod
2173    def advertising_type_name(cls, advertising_type):
2174        return name_or_number(cls.ADVERTISING_TYPE_NAMES, advertising_type)
2175
2176
2177# -----------------------------------------------------------------------------
2178@HCI_Command.command()
2179class HCI_LE_Read_Advertising_Channel_Tx_Power_Command(HCI_Command):
2180    '''
2181    See Bluetooth spec @ 7.8.6 LE Read Advertising Channel Tx Power Command
2182    '''
2183
2184
2185# -----------------------------------------------------------------------------
2186@HCI_Command.command([
2187    ('advertising_data', {
2188        'parser':     HCI_Object.parse_length_prefixed_bytes,
2189        'serializer': functools.partial(HCI_Object.serialize_length_prefixed_bytes, padded_size=32)
2190    })
2191])
2192class HCI_LE_Set_Advertising_Data_Command(HCI_Command):
2193    '''
2194    See Bluetooth spec @ 7.8.7 LE Set Advertising Data Command
2195    '''
2196
2197
2198# -----------------------------------------------------------------------------
2199@HCI_Command.command([
2200    ('scan_response_data', {
2201        'parser':     HCI_Object.parse_length_prefixed_bytes,
2202        'serializer': functools.partial(HCI_Object.serialize_length_prefixed_bytes, padded_size=32)
2203    })
2204])
2205class HCI_LE_Set_Scan_Response_Data_Command(HCI_Command):
2206    '''
2207    See Bluetooth spec @ 7.8.8 LE Set Scan Response Data Command
2208    '''
2209
2210
2211# -----------------------------------------------------------------------------
2212@HCI_Command.command([
2213    ('advertising_enable', 1)
2214])
2215class HCI_LE_Set_Advertising_Enable_Command(HCI_Command):
2216    '''
2217    See Bluetooth spec @ 7.8.9 LE Set Advertising Enable Command
2218    '''
2219
2220
2221# -----------------------------------------------------------------------------
2222@HCI_Command.command([
2223    ('le_scan_type',           1),
2224    ('le_scan_interval',       2),
2225    ('le_scan_window',         2),
2226    ('own_address_type',       Address.ADDRESS_TYPE_SPEC),
2227    ('scanning_filter_policy', 1)
2228])
2229class HCI_LE_Set_Scan_Parameters_Command(HCI_Command):
2230    '''
2231    See Bluetooth spec @ 7.8.10 LE Set Scan Parameters Command
2232    '''
2233    PASSIVE_SCANNING = 0
2234    ACTIVE_SCANNING  = 1
2235
2236    BASIC_UNFILTERED_POLICY    = 0x00
2237    BASIC_FILTERED_POLICY      = 0x01
2238    EXTENDED_UNFILTERED_POLICY = 0x02
2239    EXTENDED_FILTERED_POLICY   = 0x03
2240
2241
2242# -----------------------------------------------------------------------------
2243@HCI_Command.command([
2244    ('le_scan_enable',    1),
2245    ('filter_duplicates', 1),
2246])
2247class HCI_LE_Set_Scan_Enable_Command(HCI_Command):
2248    '''
2249    See Bluetooth spec @ 7.8.11 LE Set Scan Enable Command
2250    '''
2251
2252
2253# -----------------------------------------------------------------------------
2254@HCI_Command.command([
2255    ('le_scan_interval',        2),
2256    ('le_scan_window',          2),
2257    ('initiator_filter_policy', 1),
2258    ('peer_address_type',       Address.ADDRESS_TYPE_SPEC),
2259    ('peer_address',            Address.parse_address_preceded_by_type),
2260    ('own_address_type',        Address.ADDRESS_TYPE_SPEC),
2261    ('conn_interval_min',       2),
2262    ('conn_interval_max',       2),
2263    ('conn_latency',            2),
2264    ('supervision_timeout',     2),
2265    ('minimum_ce_length',       2),
2266    ('maximum_ce_length',       2)
2267])
2268class HCI_LE_Create_Connection_Command(HCI_Command):
2269    '''
2270    See Bluetooth spec @ 7.8.12 LE Create Connection Command
2271    '''
2272
2273
2274# -----------------------------------------------------------------------------
2275@HCI_Command.command()
2276class HCI_LE_Create_Connection_Cancel_Command(HCI_Command):
2277    '''
2278    See Bluetooth spec @ 7.8.13 LE Create Connection Cancel Command
2279    '''
2280
2281
2282# -----------------------------------------------------------------------------
2283@HCI_Command.command()
2284class HCI_LE_Read_White_List_Size_Command(HCI_Command):
2285    '''
2286    See Bluetooth spec @ 7.8.14 LE Read White List Size Command
2287    '''
2288
2289
2290# -----------------------------------------------------------------------------
2291@HCI_Command.command()
2292class HCI_LE_Clear_White_List_Command(HCI_Command):
2293    '''
2294    See Bluetooth spec @ 7.8.15 LE Clear White List Command
2295    '''
2296
2297
2298# -----------------------------------------------------------------------------
2299@HCI_Command.command([
2300    ('address_type', Address.ADDRESS_TYPE_SPEC),
2301    ('address',      Address.parse_address_preceded_by_type)
2302])
2303class HCI_LE_Add_Device_To_White_List_Command(HCI_Command):
2304    '''
2305    See Bluetooth spec @ 7.8.16 LE Add Device To White List Command
2306    '''
2307
2308
2309# -----------------------------------------------------------------------------
2310@HCI_Command.command([
2311    ('address_type', Address.ADDRESS_TYPE_SPEC),
2312    ('address',      Address.parse_address_preceded_by_type)
2313])
2314class HCI_LE_Remove_Device_From_White_List_Command(HCI_Command):
2315    '''
2316    See Bluetooth spec @ 7.8.17 LE Remove Device From White List Command
2317    '''
2318
2319
2320# -----------------------------------------------------------------------------
2321@HCI_Command.command([
2322    ('connection_handle',   2),
2323    ('conn_interval_min',   2),
2324    ('conn_interval_max',   2),
2325    ('conn_latency',        2),
2326    ('supervision_timeout', 2),
2327    ('minimum_ce_length',   2),
2328    ('maximum_ce_length',   2)
2329])
2330class HCI_LE_Connection_Update_Command(HCI_Command):
2331    '''
2332    See Bluetooth spec @ 7.8.18 LE Connection Update Command
2333    '''
2334
2335
2336# -----------------------------------------------------------------------------
2337@HCI_Command.command([
2338    ('connection_handle', 2)
2339])
2340class HCI_LE_Read_Remote_Features_Command(HCI_Command):
2341    '''
2342    See Bluetooth spec @ 7.8.21 LE Read Remote Features Command
2343    '''
2344
2345
2346# -----------------------------------------------------------------------------
2347@HCI_Command.command([
2348    ('connection_handle',     2),
2349    ('random_number',         8),
2350    ('encrypted_diversifier', 2),
2351    ('long_term_key',         16)
2352])
2353class HCI_LE_Start_Encryption_Command(HCI_Command):
2354    '''
2355    See Bluetooth spec @ 7.8.24 LE Start Encryption Command
2356    (renamed to "LE Enable Encryption Command" in version 5.2 of the specification)
2357    '''
2358
2359
2360# -----------------------------------------------------------------------------
2361@HCI_Command.command([
2362    ('connection_handle', 2),
2363    ('long_term_key',     16)
2364])
2365class HCI_LE_Long_Term_Key_Request_Reply_Command(HCI_Command):
2366    '''
2367    See Bluetooth spec @ 7.8.25 LE Long Term Key Request Reply Command
2368    '''
2369
2370
2371# -----------------------------------------------------------------------------
2372@HCI_Command.command([
2373    ('connection_handle', 2)
2374])
2375class HCI_LE_Long_Term_Key_Request_Negative_Reply_Command(HCI_Command):
2376    '''
2377    See Bluetooth spec @ 7.8.26 LE Long Term Key Request Negative Reply Command
2378    '''
2379
2380
2381# -----------------------------------------------------------------------------
2382@HCI_Command.command()
2383class HCI_LE_Read_Supported_States_Command(HCI_Command):
2384    '''
2385    See Bluetooth spec @ 7.8.27 LE Read Supported States Command
2386    '''
2387
2388
2389# -----------------------------------------------------------------------------
2390@HCI_Command.command([
2391    ('connection_handle', 2),
2392    ('interval_min',      2),
2393    ('interval_max',      2),
2394    ('latency',           2),
2395    ('timeout',           2),
2396    ('minimum_ce_length', 2),
2397    ('maximum_ce_length', 2)
2398])
2399class HCI_LE_Remote_Connection_Parameter_Request_Reply_Command(HCI_Command):
2400    '''
2401    See Bluetooth spec @ 7.8.31 LE Remote Connection Parameter Request Reply Command
2402    '''
2403
2404
2405# -----------------------------------------------------------------------------
2406@HCI_Command.command([
2407    ('connection_handle', 2),
2408    ('reason',            {'size': 1, 'mapper': HCI_Constant.error_name})
2409])
2410class HCI_LE_Remote_Connection_Parameter_Request_Negative_Reply_Command(HCI_Command):
2411    '''
2412    See Bluetooth spec @ 7.8.32 LE Remote Connection Parameter Request Negative Reply Command
2413    '''
2414
2415
2416# -----------------------------------------------------------------------------
2417@HCI_Command.command([
2418    ('suggested_max_tx_octets', 2),
2419    ('suggested_max_tx_time',   2)
2420])
2421class HCI_LE_Write_Suggested_Default_Data_Length_Command(HCI_Command):
2422    '''
2423    See Bluetooth spec @ 7.8.35 LE Write Suggested Default Data Length Command
2424    '''
2425
2426
2427# -----------------------------------------------------------------------------
2428@HCI_Command.command([
2429    ('peer_identity_address_type', Address.ADDRESS_TYPE_SPEC),
2430    ('peer_identity_address',      Address.parse_address_preceded_by_type),
2431    ('peer_irk',                   16),
2432    ('local_irk',                  16),
2433])
2434class HCI_LE_Add_Device_To_Resolving_List_Command(HCI_Command):
2435    '''
2436    See Bluetooth spec @ 7.8.38 LE Add Device To Resolving List Command
2437    '''
2438
2439
2440# -----------------------------------------------------------------------------
2441@HCI_Command.command()
2442class HCI_LE_Clear_Resolving_List_Command(HCI_Command):
2443    '''
2444    See Bluetooth spec @ 7.8.40 LE Clear Resolving List Command
2445    '''
2446
2447
2448# -----------------------------------------------------------------------------
2449@HCI_Command.command([
2450    ('all_phys', 1),
2451    ('tx_phys',  1),
2452    ('rx_phys',  1)
2453])
2454class HCI_LE_Set_Default_PHY_Command(HCI_Command):
2455    '''
2456    See Bluetooth spec @ 7.8.48 LE Set Default PHY Command
2457    '''
2458
2459
2460# -----------------------------------------------------------------------------
2461@HCI_Command.command([
2462    ('address_resolution_enable', 1)
2463])
2464class HCI_LE_Set_Address_Resolution_Enable_Command(HCI_Command):
2465    '''
2466    See Bluetooth spec @ 7.8.44 LE Set Address Resolution Enable Command
2467    '''
2468
2469
2470# -----------------------------------------------------------------------------
2471@HCI_Command.command([
2472    ('rpa_timeout', 2)
2473])
2474class HCI_LE_Set_Resolvable_Private_Address_Timeout_Command(HCI_Command):
2475    '''
2476    See Bluetooth spec @ 7.8.45 LE Set Resolvable Private Address Timeout Command
2477    '''
2478
2479
2480# -----------------------------------------------------------------------------
2481# HCI Events
2482# -----------------------------------------------------------------------------
2483class HCI_Event(HCI_Packet):
2484    '''
2485    See Bluetooth spec @ Vol 2, Part E - 5.4.4 HCI Event Packet
2486    '''
2487    hci_packet_type    = HCI_EVENT_PACKET
2488    event_classes      = {}
2489    meta_event_classes = {}
2490
2491    @staticmethod
2492    def event(fields=[]):
2493        '''
2494        Decorator used to declare and register subclasses
2495        '''
2496
2497        def inner(cls):
2498            cls.name = cls.__name__.upper()
2499            cls.event_code = key_with_value(HCI_EVENT_NAMES, cls.name)
2500            if cls.event_code is None:
2501                raise KeyError('event not found in HCI_EVENT_NAMES')
2502            cls.fields = fields
2503
2504            # Patch the __init__ method to fix the event_code
2505            def init(self, parameters=None, **kwargs):
2506                return HCI_Event.__init__(self, cls.event_code, parameters, **kwargs)
2507            cls.__init__ = init
2508
2509            # Register a factory for this class
2510            HCI_Event.event_classes[cls.event_code] = cls
2511
2512            return cls
2513
2514        return inner
2515
2516    @staticmethod
2517    def registered(cls):
2518        cls.name = cls.__name__.upper()
2519        cls.event_code = key_with_value(HCI_EVENT_NAMES, cls.name)
2520        if cls.event_code is None:
2521            raise KeyError('event not found in HCI_EVENT_NAMES')
2522
2523        # Register a factory for this class
2524        HCI_Event.event_classes[cls.event_code] = cls
2525
2526        return cls
2527
2528    @staticmethod
2529    def from_bytes(packet):
2530        event_code = packet[1]
2531        length     = packet[2]
2532        parameters = packet[3:]
2533        if len(parameters) != length:
2534            raise ValueError('invalid packet length')
2535
2536        if event_code == HCI_LE_META_EVENT:
2537            # We do this dispatch here and not in the subclass in order to avoid call loops
2538            subevent_code = parameters[0]
2539            cls = HCI_Event.meta_event_classes.get(subevent_code)
2540            if cls is None:
2541                # No class registered, just use a generic class instance
2542                return HCI_LE_Meta_Event(subevent_code, parameters)
2543
2544        else:
2545            cls = HCI_Event.event_classes.get(event_code)
2546            if cls is None:
2547                # No class registered, just use a generic class instance
2548                return HCI_Event(event_code, parameters)
2549
2550        # Invoke the factory to create a new instance
2551        return cls.from_parameters(parameters)
2552
2553    @classmethod
2554    def from_parameters(cls, parameters):
2555        self = cls.__new__(cls)
2556        HCI_Event.__init__(self, self.event_code, parameters)
2557        if fields := getattr(self, 'fields', None):
2558            HCI_Object.init_from_bytes(self, parameters, 0, fields)
2559        return self
2560
2561    @staticmethod
2562    def event_name(event_code):
2563        return name_or_number(HCI_EVENT_NAMES, event_code)
2564
2565    def __init__(self, event_code, parameters=None, **kwargs):
2566        super().__init__(HCI_Event.event_name(event_code))
2567        if (fields := getattr(self, 'fields', None)) and kwargs:
2568            HCI_Object.init_from_fields(self, fields, kwargs)
2569            if parameters is None:
2570                parameters = HCI_Object.dict_to_bytes(kwargs, fields)
2571        self.event_code = event_code
2572        self.parameters = parameters
2573
2574    def to_bytes(self):
2575        parameters = b'' if self.parameters is None else self.parameters
2576        return bytes([HCI_EVENT_PACKET, self.event_code, len(parameters)]) + parameters
2577
2578    def __str__(self):
2579        result = color(self.name, 'magenta')
2580        if fields := getattr(self, 'fields', None):
2581            result += ':\n' + HCI_Object.format_fields(self.__dict__, fields, '  ')
2582        else:
2583            if self.parameters:
2584                result += f': {self.parameters.hex()}'
2585        return result
2586
2587
2588# -----------------------------------------------------------------------------
2589class HCI_LE_Meta_Event(HCI_Event):
2590    '''
2591    See Bluetooth spec @ 7.7.65 LE Meta Event
2592    '''
2593
2594    @staticmethod
2595    def event(fields=[]):
2596        '''
2597        Decorator used to declare and register subclasses
2598        '''
2599
2600        def inner(cls):
2601            cls.name = cls.__name__.upper()
2602            cls.subevent_code = key_with_value(HCI_SUBEVENT_NAMES, cls.name)
2603            if cls.subevent_code is None:
2604                raise KeyError('subevent not found in HCI_SUBEVENT_NAMES')
2605            cls.fields = fields
2606
2607            # Patch the __init__ method to fix the subevent_code
2608            def init(self, parameters=None, **kwargs):
2609                return HCI_LE_Meta_Event.__init__(self, cls.subevent_code, parameters, **kwargs)
2610            cls.__init__ = init
2611
2612            # Register a factory for this class
2613            HCI_Event.meta_event_classes[cls.subevent_code] = cls
2614
2615            return cls
2616
2617        return inner
2618
2619    @classmethod
2620    def from_parameters(cls, parameters):
2621        self = cls.__new__(cls)
2622        HCI_LE_Meta_Event.__init__(self, self.subevent_code, parameters)
2623        if fields := getattr(self, 'fields', None):
2624            HCI_Object.init_from_bytes(self, parameters, 1, fields)
2625        return self
2626
2627    @staticmethod
2628    def subevent_name(subevent_code):
2629        return name_or_number(HCI_SUBEVENT_NAMES, subevent_code)
2630
2631    def __init__(self, subevent_code, parameters, **kwargs):
2632        self.subevent_code = subevent_code
2633        if parameters is None and (fields := getattr(self, 'fields', None)) and kwargs:
2634            parameters = bytes([subevent_code]) + HCI_Object.dict_to_bytes(kwargs, fields)
2635        super().__init__(HCI_LE_META_EVENT, parameters, **kwargs)
2636
2637        # Override the name in order to adopt the subevent name instead
2638        self.name = self.subevent_name(subevent_code)
2639
2640    def __str__(self):
2641        result = color(self.subevent_name(self.subevent_code), 'magenta')
2642        if fields := getattr(self, 'fields', None):
2643            result += ':\n' + HCI_Object.format_fields(self.__dict__, fields, '  ')
2644        else:
2645            if self.parameters:
2646                result += f': {self.parameters.hex()}'
2647        return result
2648
2649
2650# -----------------------------------------------------------------------------
2651@HCI_LE_Meta_Event.event([
2652    ('status',                STATUS_SPEC),
2653    ('connection_handle',     2),
2654    ('role',                  {'size': 1, 'mapper': lambda x: 'CENTRAL' if x == 0 else 'PERIPHERAL'}),
2655    ('peer_address_type',     Address.ADDRESS_TYPE_SPEC),
2656    ('peer_address',          Address.parse_address_preceded_by_type),
2657    ('conn_interval',         2),
2658    ('conn_latency',          2),
2659    ('supervision_timeout',   2),
2660    ('master_clock_accuracy', 1)
2661])
2662class HCI_LE_Connection_Complete_Event(HCI_LE_Meta_Event):
2663    '''
2664    See Bluetooth spec @ 7.7.65.1 LE Connection Complete Event
2665    '''
2666
2667
2668# -----------------------------------------------------------------------------
2669class HCI_LE_Advertising_Report_Event(HCI_LE_Meta_Event):
2670    '''
2671    See Bluetooth spec @ 7.7.65.2 LE Advertising Report Event
2672    '''
2673    subevent_code = HCI_LE_ADVERTISING_REPORT_EVENT
2674
2675    # Event Types
2676    ADV_IND         = 0x00
2677    ADV_DIRECT_IND  = 0x01
2678    ADV_SCAN_IND    = 0x02
2679    ADV_NONCONN_IND = 0x03
2680    SCAN_RSP        = 0x04
2681
2682    EVENT_TYPE_NAMES = {
2683        ADV_IND:         'ADV_IND',          # Connectable and scannable undirected advertising
2684        ADV_DIRECT_IND:  'ADV_DIRECT_IND',   # Connectable directed advertising
2685        ADV_SCAN_IND:    'ADV_SCAN_IND',     # Scannable undirected advertising
2686        ADV_NONCONN_IND: 'ADV_NONCONN_IND',  # Non connectable undirected advertising
2687        SCAN_RSP:        'SCAN_RSP'          # Scan Response
2688    }
2689
2690    REPORT_FIELDS = [
2691        ('event_type',   1),
2692        ('address_type', Address.ADDRESS_TYPE_SPEC),
2693        ('address',      Address.parse_address_preceded_by_type),
2694        ('data',         {'parser': HCI_Object.parse_length_prefixed_bytes, 'serializer': HCI_Object.serialize_length_prefixed_bytes}),
2695        ('rssi',         -1)
2696    ]
2697
2698    @classmethod
2699    def event_type_name(cls, event_type):
2700        return name_or_number(cls.EVENT_TYPE_NAMES, event_type)
2701
2702    @staticmethod
2703    def from_parameters(parameters):
2704        num_reports = parameters[1]
2705        reports = []
2706        offset = 2
2707        for _ in range(num_reports):
2708            report = HCI_Object.from_bytes(parameters, offset, HCI_LE_Advertising_Report_Event.REPORT_FIELDS)
2709            offset += 10 + len(report.data)
2710            reports.append(report)
2711
2712        return HCI_LE_Advertising_Report_Event(reports)
2713
2714    def __init__(self, reports):
2715        self.reports = reports[:]
2716
2717        # Serialize the fields
2718        parameters = bytes([HCI_LE_ADVERTISING_REPORT_EVENT, len(reports)]) + b''.join([bytes(report) for report in reports])
2719
2720        super().__init__(self.subevent_code, parameters)
2721
2722    def __str__(self):
2723        reports = '\n'.join([report.to_string('  ', {
2724            'event_type':   self.event_type_name,
2725            'address_type': Address.address_type_name,
2726            'data': lambda x: str(AdvertisingData.from_bytes(x))
2727        }) for report in self.reports])
2728        return f'{color(self.subevent_name(self.subevent_code), "magenta")}:\n{reports}'
2729
2730
2731HCI_Event.meta_event_classes[HCI_LE_ADVERTISING_REPORT_EVENT] = HCI_LE_Advertising_Report_Event
2732
2733
2734# -----------------------------------------------------------------------------
2735@HCI_LE_Meta_Event.event([
2736    ('status',              STATUS_SPEC),
2737    ('connection_handle',   2),
2738    ('conn_interval',       2),
2739    ('conn_latency',        2),
2740    ('supervision_timeout', 2)
2741])
2742class HCI_LE_Connection_Update_Complete_Event(HCI_LE_Meta_Event):
2743    '''
2744    See Bluetooth spec @ 7.7.65.3 LE Connection Update Complete Event
2745    '''
2746
2747
2748# -----------------------------------------------------------------------------
2749@HCI_LE_Meta_Event.event([
2750    ('status',            STATUS_SPEC),
2751    ('connection_handle', 2),
2752    ('le_features',       8)
2753])
2754class HCI_LE_Read_Remote_Features_Complete_Event(HCI_LE_Meta_Event):
2755    '''
2756    See Bluetooth spec @ 7.7.65.4 LE Read Remote Features Complete Event
2757    '''
2758
2759
2760# -----------------------------------------------------------------------------
2761@HCI_LE_Meta_Event.event([
2762    ('connection_handle',     2),
2763    ('random_number',         8),
2764    ('encryption_diversifier', 2)
2765])
2766class HCI_LE_Long_Term_Key_Request_Event(HCI_LE_Meta_Event):
2767    '''
2768    See Bluetooth spec @ 7.7.65.5 LE Long Term Key Request Event
2769    '''
2770
2771
2772# -----------------------------------------------------------------------------
2773@HCI_LE_Meta_Event.event([
2774    ('connection_handle', 2),
2775    ('interval_min',      2),
2776    ('interval_max',      2),
2777    ('latency',           2),
2778    ('timeout',           2)
2779])
2780class HCI_LE_Remote_Connection_Parameter_Request_Event(HCI_LE_Meta_Event):
2781    '''
2782    See Bluetooth spec @ 7.7.65.6 LE Remote Connection Parameter Request Event
2783    '''
2784
2785
2786# -----------------------------------------------------------------------------
2787@HCI_LE_Meta_Event.event([
2788    ('connection_handle', 2),
2789    ('max_tx_octets',     2),
2790    ('max_tx_time',       2),
2791    ('max_rx_octets',     2),
2792    ('max_rx_time',       2),
2793])
2794class HCI_LE_Data_Length_Change_Event(HCI_LE_Meta_Event):
2795    '''
2796    See Bluetooth spec @ 7.7.65.7 LE Data Length Change Event
2797    '''
2798
2799
2800# -----------------------------------------------------------------------------
2801@HCI_LE_Meta_Event.event([
2802    ('status',                           STATUS_SPEC),
2803    ('connection_handle',                2),
2804    ('role',                             {'size': 1, 'mapper': lambda x: 'CENTRAL' if x == 0 else 'PERIPHERAL'}),
2805    ('peer_address_type',                Address.ADDRESS_TYPE_SPEC),
2806    ('peer_address',                     Address.parse_address_preceded_by_type),
2807    ('local_resolvable_private_address', Address.parse_address),
2808    ('peer_resolvable_private_address',  Address.parse_address),
2809    ('conn_interval',                    2),
2810    ('conn_latency',                     2),
2811    ('supervision_timeout',              2),
2812    ('master_clock_accuracy',            1)
2813])
2814class HCI_LE_Enhanced_Connection_Complete_Event(HCI_LE_Meta_Event):
2815    '''
2816    See Bluetooth spec @ 7.7.65.10 LE Enhanced Connection Complete Event
2817    '''
2818
2819
2820# -----------------------------------------------------------------------------
2821@HCI_LE_Meta_Event.event([
2822    ('status',            STATUS_SPEC),
2823    ('connection_handle', 2),
2824    ('tx_phy',            {'size': 1, 'mapper': HCI_Constant.le_phy_name}),
2825    ('rx_phy',            {'size': 1, 'mapper': HCI_Constant.le_phy_name})
2826])
2827class HCI_LE_PHY_Update_Complete_Event(HCI_LE_Meta_Event):
2828    '''
2829    See Bluetooth spec @ 7.7.65.12 LE PHY Update Complete Event
2830    '''
2831
2832
2833# -----------------------------------------------------------------------------
2834@HCI_LE_Meta_Event.event([
2835    ('connection_handle',           2),
2836    ('channel_selection_algorithm', 1)
2837])
2838class HCI_LE_Channel_Selection_Algorithm_Event(HCI_LE_Meta_Event):
2839    '''
2840    See Bluetooth spec @ 7.7.65.20 LE Channel Selection Algorithm Event
2841    '''
2842
2843
2844# -----------------------------------------------------------------------------
2845@HCI_Event.event([
2846    ('status', STATUS_SPEC)
2847])
2848class HCI_Inquiry_Complete_Event(HCI_Event):
2849    '''
2850    See Bluetooth spec @ 7.7.1 Inquiry Complete Event
2851    '''
2852
2853
2854# -----------------------------------------------------------------------------
2855@HCI_Event.registered
2856class HCI_Inquiry_Result_Event(HCI_Event):
2857    '''
2858    See Bluetooth spec @ 7.7.2 Inquiry Result Event
2859    '''
2860
2861    RESPONSE_FIELDS = [
2862        ('bd_addr',                   Address.parse_address),
2863        ('page_scan_repetition_mode', 1),
2864        ('reserved',                  1),
2865        ('reserved',                  1),
2866        ('class_of_device',           {'size': 3, 'mapper': map_class_of_device}),
2867        ('clock_offset',              2)
2868    ]
2869
2870    @staticmethod
2871    def from_parameters(parameters):
2872        num_responses = parameters[0]
2873        responses = []
2874        offset = 1
2875        for _ in range(num_responses):
2876            response = HCI_Object.from_bytes(parameters, offset, HCI_Inquiry_Result_Event.RESPONSE_FIELDS)
2877            offset += 14
2878            responses.append(response)
2879
2880        return HCI_Inquiry_Result_Event(responses)
2881
2882    def __init__(self, responses):
2883        self.responses = responses[:]
2884
2885        # Serialize the fields
2886        parameters = bytes([HCI_INQUIRY_RESULT_EVENT, len(responses)]) + b''.join([bytes(response) for response in responses])
2887
2888        super().__init__(HCI_INQUIRY_RESULT_EVENT, parameters)
2889
2890    def __str__(self):
2891        responses = '\n'.join([response.to_string(indentation='  ') for response in self.responses])
2892        return f'{color("HCI_INQUIRY_RESULT_EVENT", "magenta")}:\n{responses}'
2893
2894
2895# -----------------------------------------------------------------------------
2896@HCI_Event.event([
2897    ('status',             STATUS_SPEC),
2898    ('connection_handle',  2),
2899    ('bd_addr',            Address.parse_address),
2900    ('link_type',          {'size': 1, 'mapper': lambda x: HCI_Connection_Complete_Event.link_type_name(x)}),
2901    ('encryption_enabled', 1)
2902])
2903class HCI_Connection_Complete_Event(HCI_Event):
2904    '''
2905    See Bluetooth spec @ 7.7.3 Connection Complete Event
2906    '''
2907
2908    SCO_LINK_TYPE  = 0x00
2909    ACL_LINK_TYPE  = 0x01
2910    ESCO_LINK_TYPE = 0x02
2911
2912    LINK_TYPE_NAMES = {
2913        SCO_LINK_TYPE:  'SCO',
2914        ACL_LINK_TYPE:  'ACL',
2915        ESCO_LINK_TYPE: 'eSCO'
2916    }
2917
2918    @staticmethod
2919    def link_type_name(link_type):
2920        return name_or_number(HCI_Connection_Complete_Event.LINK_TYPE_NAMES, link_type)
2921
2922
2923# -----------------------------------------------------------------------------
2924@HCI_Event.event([
2925    ('bd_addr',         Address.parse_address),
2926    ('class_of_device', 3),
2927    ('link_type',       {'size': 1, 'mapper': lambda x: HCI_Connection_Complete_Event.link_type_name(x)})
2928])
2929class HCI_Connection_Request_Event(HCI_Event):
2930    '''
2931    See Bluetooth spec @ 7.7.4 Connection Request Event
2932    '''
2933
2934
2935# -----------------------------------------------------------------------------
2936@HCI_Event.event([
2937    ('status',            STATUS_SPEC),
2938    ('connection_handle', 2),
2939    ('reason',            {'size': 1, 'mapper': HCI_Constant.error_name})
2940])
2941class HCI_Disconnection_Complete_Event(HCI_Event):
2942    '''
2943    See Bluetooth spec @ 7.7.5 Disconnection Complete Event
2944    '''
2945
2946
2947# -----------------------------------------------------------------------------
2948@HCI_Event.event([
2949    ('status',            STATUS_SPEC),
2950    ('connection_handle', 2)
2951])
2952class HCI_Authentication_Complete_Event(HCI_Event):
2953    '''
2954    See Bluetooth spec @ 7.7.6 Authentication Complete Event
2955    '''
2956
2957
2958# -----------------------------------------------------------------------------
2959@HCI_Event.event([
2960    ('status',      STATUS_SPEC),
2961    ('bd_addr',     Address.parse_address),
2962    ('remote_name', {'size': 248, 'mapper': map_null_terminated_utf8_string})
2963])
2964class HCI_Remote_Name_Request_Complete_Event(HCI_Event):
2965    '''
2966    See Bluetooth spec @ 7.7.7 Remote Name Request Complete Event
2967    '''
2968
2969
2970# -----------------------------------------------------------------------------
2971@HCI_Event.event([
2972    ('status',             STATUS_SPEC),
2973    ('connection_handle',  2),
2974    ('encryption_enabled', {'size': 1, 'mapper': lambda x: HCI_Encryption_Change_Event.encryption_enabled_name(x)})
2975])
2976class HCI_Encryption_Change_Event(HCI_Event):
2977    '''
2978    See Bluetooth spec @ 7.7.8 Encryption Change Event
2979    '''
2980
2981    OFF           = 0x00
2982    E0_OR_AES_CCM = 0x01
2983    AES_CCM       = 0x02
2984
2985    ENCYRPTION_ENABLED_NAMES = {
2986        OFF:           'OFF',
2987        E0_OR_AES_CCM: 'E0_OR_AES_CCM',
2988        AES_CCM:       'AES_CCM'
2989    }
2990
2991    @staticmethod
2992    def encryption_enabled_name(encryption_enabled):
2993        return name_or_number(HCI_Encryption_Change_Event.ENCYRPTION_ENABLED_NAMES, encryption_enabled)
2994
2995
2996# -----------------------------------------------------------------------------
2997@HCI_Event.event([
2998    ('status',            STATUS_SPEC),
2999    ('connection_handle', 2),
3000    ('lmp_features',      8)
3001])
3002class HCI_Read_Remote_Supported_Features_Complete_Event(HCI_Event):
3003    '''
3004    See Bluetooth spec @ 7.7.11 Read Remote Supported Features Complete Event
3005    '''
3006
3007
3008# -----------------------------------------------------------------------------
3009@HCI_Event.event([
3010    ('status',            STATUS_SPEC),
3011    ('connection_handle', 2),
3012    ('version',           1),
3013    ('manufacturer_name', 2),
3014    ('subversion',        2)
3015])
3016class HCI_Read_Remote_Version_Information_Complete_Event(HCI_Event):
3017    '''
3018    See Bluetooth spec @ 7.7.12 Read Remote Version Information Complete Event
3019    '''
3020
3021
3022# -----------------------------------------------------------------------------
3023@HCI_Event.event([
3024    ('num_hci_command_packets', 1),
3025    ('command_opcode',          {'size': 2, 'mapper': HCI_Command.command_name}),
3026    ('return_parameters',       '*')
3027])
3028class HCI_Command_Complete_Event(HCI_Event):
3029    '''
3030    See Bluetooth spec @ 7.7.14 Command Complete Event
3031    '''
3032
3033    def map_return_parameters(self, return_parameters):
3034        # Map simple 'status' return parameters to their named constant form
3035        if type(return_parameters) is bytes and len(return_parameters) == 1:
3036            # Byte-array form
3037            return HCI_Constant.status_name(return_parameters[0])
3038        elif type(return_parameters) is int:
3039            # Already converted to an integer status code
3040            return HCI_Constant.status_name(return_parameters)
3041        else:
3042            return return_parameters
3043
3044    @staticmethod
3045    def from_parameters(parameters):
3046        self = HCI_Command_Complete_Event.__new__(HCI_Command_Complete_Event)
3047        HCI_Event.__init__(self, self.event_code, parameters)
3048        HCI_Object.init_from_bytes(self, parameters, 0, HCI_Command_Complete_Event.fields)
3049
3050        # Parse the return parameters
3051        if type(self.return_parameters) is bytes and len(self.return_parameters) == 1:
3052            # All commands with 1-byte return parameters return a 'status' field, convert it to an integer
3053            self.return_parameters = self.return_parameters[0]
3054        else:
3055            cls = HCI_Command.command_classes.get(self.command_opcode)
3056            if cls and cls.return_parameters_fields:
3057                self.return_parameters = HCI_Object.from_bytes(self.return_parameters, 0, cls.return_parameters_fields)
3058                self.return_parameters.fields = cls.return_parameters_fields
3059
3060        return self
3061
3062    def __str__(self):
3063        return f'{color(self.name, "magenta")}:\n' + HCI_Object.format_fields(self.__dict__, self.fields, '  ', {
3064            'return_parameters': self.map_return_parameters
3065        })
3066
3067
3068# -----------------------------------------------------------------------------
3069@HCI_Event.event([
3070    ('status',                  {'size': 1, 'mapper': lambda x: HCI_Command_Status_Event.status_name(x)}),
3071    ('num_hci_command_packets', 1),
3072    ('command_opcode',          {'size': 2, 'mapper': HCI_Command.command_name})
3073])
3074class HCI_Command_Status_Event(HCI_Event):
3075    '''
3076    See Bluetooth spec @ 7.7.15 Command Complete Event
3077    '''
3078    PENDING = 0
3079
3080    @staticmethod
3081    def status_name(status):
3082        if status == HCI_Command_Status_Event.PENDING:
3083            return 'PENDING'
3084        else:
3085            return HCI_Constant.error_name(status)
3086
3087
3088# -----------------------------------------------------------------------------
3089@HCI_Event.event([
3090    ('status',   STATUS_SPEC),
3091    ('bd_addr',  Address.parse_address),
3092    ('new_role', {'size': 1, 'mapper': HCI_Constant.role_name})
3093])
3094class HCI_Role_Change_Event(HCI_Event):
3095    '''
3096    See Bluetooth spec @ 7.7.18 Role Change Event
3097    '''
3098
3099
3100# -----------------------------------------------------------------------------
3101@HCI_Event.registered
3102class HCI_Number_Of_Completed_Packets_Event(HCI_Event):
3103    '''
3104    See Bluetooth spec @ 7.7.19 Number Of Completed Packets Event
3105    '''
3106
3107    @classmethod
3108    def from_parameters(cls, parameters):
3109        self = cls.__new__(cls)
3110        self.parameters = parameters
3111        num_handles = parameters[0]
3112        self.connection_handles = []
3113        self.num_completed_packets = []
3114        for i in range(num_handles):
3115            self.connection_handles.append(
3116                struct.unpack_from('<H', parameters, 1 + i * 4)[0]
3117            )
3118            self.num_completed_packets.append(
3119                struct.unpack_from('<H', parameters, 1 + i * 4 + 2)[0]
3120            )
3121
3122        return self
3123
3124    def __init__(self, connection_handle_and_completed_packets_list):
3125        self.connection_handles = []
3126        self.num_completed_packets = []
3127        parameters = bytes([len(connection_handle_and_completed_packets_list)])
3128        for handle, completed_packets in connection_handle_and_completed_packets_list:
3129            self.connection_handles.append(handle)
3130            self.num_completed_packets.append(completed_packets)
3131            parameters += struct.pack('<H', handle)
3132            parameters += struct.pack('<H', completed_packets)
3133        super().__init__(HCI_NUMBER_OF_COMPLETED_PACKETS_EVENT, parameters)
3134
3135    def __str__(self):
3136        lines = [
3137            color(self.name, 'magenta') + ':',
3138            color('  number_of_handles:         ', 'cyan') + f'{len(self.connection_handles)}'
3139        ]
3140        for i in range(len(self.connection_handles)):
3141            lines.append(color(f'  connection_handle[{i}]:     ', 'cyan') + f'{self.connection_handles[i]}')
3142            lines.append(color(f'  num_completed_packets[{i}]: ', 'cyan') + f'{self.num_completed_packets[i]}')
3143        return '\n'.join(lines)
3144
3145
3146# -----------------------------------------------------------------------------
3147@HCI_Event.event([
3148    ('status',            STATUS_SPEC),
3149    ('connection_handle', 2),
3150    ('current_mode',      {'size': 1, 'mapper': lambda x: HCI_Mode_Change_Event.mode_name(x)}),
3151    ('interval',          2)
3152])
3153class HCI_Mode_Change_Event(HCI_Event):
3154    '''
3155    See Bluetooth spec @ 7.7.20 Mode Change Event
3156    '''
3157
3158    ACTIVE_MODE = 0x00
3159    HOLD_MODE   = 0x01
3160    SNIFF_MODE  = 0x02
3161
3162    MODE_NAMES = {
3163        ACTIVE_MODE: 'ACTIVE_MODE',
3164        HOLD_MODE:   'HOLD_MODE',
3165        SNIFF_MODE:  'SNIFF_MODE'
3166    }
3167
3168    @staticmethod
3169    def mode_name(mode):
3170        return name_or_number(HCI_Mode_Change_Event.MODE_NAMES, mode)
3171
3172
3173# -----------------------------------------------------------------------------
3174@HCI_Event.event([
3175    ('bd_addr', Address.parse_address)
3176])
3177class HCI_PIN_Code_Request_Event(HCI_Event):
3178    '''
3179    See Bluetooth spec @ 7.7.22 PIN Code Request Event
3180    '''
3181
3182
3183# -----------------------------------------------------------------------------
3184@HCI_Event.event([
3185    ('bd_addr',  Address.parse_address)
3186])
3187class HCI_Link_Key_Request_Event(HCI_Event):
3188    '''
3189    See Bluetooth spec @ 7.7.24 7.7.23 Link Key Request Event
3190    '''
3191
3192
3193# -----------------------------------------------------------------------------
3194@HCI_Event.event([
3195    ('bd_addr',  Address.parse_address),
3196    ('link_key', 16),
3197    ('key_type', {'size': 1, 'mapper': HCI_Constant.link_key_type_name})
3198])
3199class HCI_Link_Key_Notification_Event(HCI_Event):
3200    '''
3201    See Bluetooth spec @ 7.7.24 Link Key Notification Event
3202    '''
3203
3204
3205# -----------------------------------------------------------------------------
3206@HCI_Event.event([
3207    ('connection_handle', 2),
3208    ('lmp_max_slots',     1)
3209])
3210class HCI_Max_Slots_Change_Event(HCI_Event):
3211    '''
3212    See Bluetooth spec @ 7.7.27 Max Slots Change Event
3213    '''
3214
3215
3216# -----------------------------------------------------------------------------
3217@HCI_Event.event([
3218    ('status',            STATUS_SPEC),
3219    ('connection_handle', 2),
3220    ('clock_offset',      2)
3221])
3222class HCI_Read_Clock_Offset_Complete_Event(HCI_Event):
3223    '''
3224    See Bluetooth spec @ 7.7.28 Read Clock Offset Complete Event
3225    '''
3226
3227
3228# -----------------------------------------------------------------------------
3229@HCI_Event.event([
3230    ('status',            STATUS_SPEC),
3231    ('connection_handle', 2),
3232    ('packet_type',       2)
3233])
3234class HCI_Connection_Packet_Type_Changed_Event(HCI_Event):
3235    '''
3236    See Bluetooth spec @ 7.7.29 Connection Packet Type Changed Event
3237    '''
3238
3239
3240# -----------------------------------------------------------------------------
3241@HCI_Event.event([
3242    ('bd_addr',                   Address.parse_address),
3243    ('page_scan_repetition_mode', 1)
3244])
3245class HCI_Page_Scan_Repetition_Mode_Change_Event(HCI_Event):
3246    '''
3247    See Bluetooth spec @ 7.7.31 Page Scan Repetition Mode Change Event
3248    '''
3249
3250
3251# -----------------------------------------------------------------------------
3252@HCI_Event.registered
3253class HCI_Inquiry_Result_With_Rssi_Event(HCI_Event):
3254    '''
3255    See Bluetooth spec @ 7.7.33 Inquiry Result with RSSI Event
3256    '''
3257
3258    RESPONSE_FIELDS = [
3259        ('bd_addr',                   Address.parse_address),
3260        ('page_scan_repetition_mode', 1),
3261        ('reserved',                  1),
3262        ('class_of_device',           {'size': 3, 'mapper': map_class_of_device}),
3263        ('clock_offset',              2),
3264        ('rssi',                      -1)
3265    ]
3266
3267    @staticmethod
3268    def from_parameters(parameters):
3269        num_responses = parameters[0]
3270        responses = []
3271        offset = 1
3272        for _ in range(num_responses):
3273            response = HCI_Object.from_bytes(parameters, offset, HCI_Inquiry_Result_With_Rssi_Event.RESPONSE_FIELDS)
3274            offset += 14
3275            responses.append(response)
3276
3277        return HCI_Inquiry_Result_With_Rssi_Event(responses)
3278
3279    def __init__(self, responses):
3280        self.responses = responses[:]
3281
3282        # Serialize the fields
3283        parameters = bytes([HCI_INQUIRY_RESULT_WITH_RSSI_EVENT, len(responses)]) + b''.join([bytes(response) for response in responses])
3284
3285        super().__init__(HCI_INQUIRY_RESULT_WITH_RSSI_EVENT, parameters)
3286
3287    def __str__(self):
3288        responses = '\n'.join([response.to_string(indentation='  ') for response in self.responses])
3289        return f'{color("HCI_INQUIRY_RESULT_WITH_RSSI_EVENT", "magenta")}:\n{responses}'
3290
3291
3292# -----------------------------------------------------------------------------
3293@HCI_Event.event([
3294    ('status',                STATUS_SPEC),
3295    ('connection_handle',     2),
3296    ('page_number',           1),
3297    ('maximum_page_number',   1),
3298    ('extended_lmp_features', 8)
3299])
3300class HCI_Read_Remote_Extended_Features_Complete_Event(HCI_Event):
3301    '''
3302    See Bluetooth spec @ 7.7.34 Read Remote Extended Features Complete Event
3303    '''
3304
3305
3306# -----------------------------------------------------------------------------
3307@HCI_Event.event([
3308    ('status',                STATUS_SPEC),
3309    ('connection_handle',     2),
3310    ('bd_addr',               Address.parse_address),
3311    ('link_type',             {'size': 1, 'mapper': lambda x: HCI_Synchronous_Connection_Complete_Event.link_type_name(x)}),
3312    ('transmission_interval', 1),
3313    ('retransmission_window', 1),
3314    ('rx_packet_length',      2),
3315    ('tx_packet_length',      2),
3316    ('air_mode',              {'size': 1, 'mapper': lambda x: HCI_Synchronous_Connection_Complete_Event.air_mode_name(x)}),
3317])
3318class HCI_Synchronous_Connection_Complete_Event(HCI_Event):
3319    '''
3320    See Bluetooth spec @ 7.7.35 Synchronous Connection Complete Event
3321    '''
3322
3323    SCO_CONNECTION_LINK_TYPE = 0x00
3324    ESCO_CONNECTION_LINK_TYPE = 0x02
3325
3326    LINK_TYPE_NAMES = {
3327        SCO_CONNECTION_LINK_TYPE:  'SCO',
3328        ESCO_CONNECTION_LINK_TYPE: 'eSCO'
3329    }
3330
3331    U_LAW_LOG_AIR_MODE        = 0x00
3332    A_LAW_LOG_AIR_MORE        = 0x01
3333    CVSD_AIR_MODE             = 0x02
3334    TRANSPARENT_DATA_AIR_MODE = 0x03
3335
3336    AIR_MODE_NAMES = {
3337        U_LAW_LOG_AIR_MODE:        'u-law log',
3338        A_LAW_LOG_AIR_MORE:        'A-law log',
3339        CVSD_AIR_MODE:             'CVSD',
3340        TRANSPARENT_DATA_AIR_MODE: 'Transparend Data'
3341    }
3342
3343    @staticmethod
3344    def link_type_name(link_type):
3345        return name_or_number(HCI_Synchronous_Connection_Complete_Event.LINK_TYPE_NAMES, link_type)
3346
3347    @staticmethod
3348    def air_mode_name(air_mode):
3349        return name_or_number(HCI_Synchronous_Connection_Complete_Event.AIR_MODE_NAMES, air_mode)
3350
3351
3352# -----------------------------------------------------------------------------
3353@HCI_Event.event([
3354    ('status',                STATUS_SPEC),
3355    ('connection_handle',     2),
3356    ('transmission_interval', 1),
3357    ('retransmission_window', 1),
3358    ('rx_packet_length',      2),
3359    ('tx_packet_length',      2)
3360])
3361class HCI_Synchronous_Connection_Changed_Event(HCI_Event):
3362    '''
3363    See Bluetooth spec @ 7.7.36 Synchronous Connection Changed Event
3364    '''
3365
3366
3367# -----------------------------------------------------------------------------
3368@HCI_Event.event([
3369    ('num_responses',             1),
3370    ('bd_addr',                   Address.parse_address),
3371    ('page_scan_repetition_mode', 1),
3372    ('reserved',                  1),
3373    ('class_of_device',          {'size': 3, 'mapper': map_class_of_device}),
3374    ('clock_offset',              2),
3375    ('rssi',                     -1),
3376    ('extended_inquiry_response', 240),
3377])
3378class HCI_Extended_Inquiry_Result_Event(HCI_Event):
3379    '''
3380    See Bluetooth spec @ 7.7.38 Extended Inquiry Result Event
3381    '''
3382
3383
3384# -----------------------------------------------------------------------------
3385@HCI_Event.event([
3386    ('status',            STATUS_SPEC),
3387    ('connection_handle', 2)
3388])
3389class HCI_Encryption_Key_Refresh_Complete_Event(HCI_Event):
3390    '''
3391    See Bluetooth spec @ 7.7.39 Encryption Key Refresh Complete Event
3392    '''
3393
3394
3395# -----------------------------------------------------------------------------
3396@HCI_Event.event([
3397    ('bd_addr', Address.parse_address)
3398])
3399class HCI_IO_Capability_Request_Event(HCI_Event):
3400    '''
3401    See Bluetooth spec @ 7.7.40 IO Capability Request Event
3402    '''
3403
3404
3405# -----------------------------------------------------------------------------
3406@HCI_Event.event([
3407    ('bd_addr',                     Address.parse_address),
3408    ('io_capability',               {'size': 1, 'mapper': HCI_Constant.io_capability_name}),
3409    ('oob_data_present',            1),
3410    ('authentication_requirements', {'size': 1, 'mapper': HCI_Constant.authentication_requirements_name})
3411])
3412class HCI_IO_Capability_Response_Event(HCI_Event):
3413    '''
3414    See Bluetooth spec @ 7.7.41 IO Capability Response Event
3415    '''
3416
3417
3418# -----------------------------------------------------------------------------
3419@HCI_Event.event([
3420    ('bd_addr',       Address.parse_address),
3421    ('numeric_value', 4)
3422])
3423class HCI_User_Confirmation_Request_Event(HCI_Event):
3424    '''
3425    See Bluetooth spec @ 7.7.42 User Confirmation Request Event
3426    '''
3427
3428
3429# -----------------------------------------------------------------------------
3430@HCI_Event.event([
3431    ('bd_addr', Address.parse_address)
3432])
3433class HCI_User_Passkey_Request_Event(HCI_Event):
3434    '''
3435    See Bluetooth spec @ 7.7.43 User Passkey Request Event
3436    '''
3437
3438
3439# -----------------------------------------------------------------------------
3440@HCI_Event.event([
3441    ('status',  STATUS_SPEC),
3442    ('bd_addr', Address.parse_address)
3443])
3444class HCI_Simple_Pairing_Complete_Event(HCI_Event):
3445    '''
3446    See Bluetooth spec @ 7.7.45 Simple Pairing Complete Event
3447    '''
3448
3449
3450# -----------------------------------------------------------------------------
3451@HCI_Event.event([
3452    ('connection_handle',        2),
3453    ('link_supervision_timeout', 2)
3454])
3455class HCI_Link_Supervision_Timeout_Changed_Event(HCI_Event):
3456    '''
3457    See Bluetooth spec @ 7.7.46 Link Supervision Timeout Changed Event
3458    '''
3459
3460
3461# -----------------------------------------------------------------------------
3462@HCI_Event.event([
3463    ('bd_addr',                 Address.parse_address),
3464    ('host_supported_features', 8)
3465])
3466class HCI_Remote_Host_Supported_Features_Notification_Event(HCI_Event):
3467    '''
3468    See Bluetooth spec @ 7.7.50 Remote Host Supported Features Notification Event
3469    '''
3470
3471
3472# -----------------------------------------------------------------------------
3473class HCI_AclDataPacket(HCI_Packet):
3474    '''
3475    See Bluetooth spec @ 5.4.2 HCI ACL Data Packets
3476    '''
3477    hci_packet_type = HCI_ACL_DATA_PACKET
3478
3479    @staticmethod
3480    def from_bytes(packet):
3481        # Read the header
3482        h, data_total_length = struct.unpack_from('<HH', packet, 1)
3483        connection_handle = h & 0xFFF
3484        pb_flag = (h >> 12) & 3
3485        bc_flag = (h >> 14) & 3
3486        data = packet[5:]
3487        if len(data) != data_total_length:
3488            raise ValueError('invalid packet length')
3489        return HCI_AclDataPacket(connection_handle, pb_flag, bc_flag, data_total_length, data)
3490
3491    def to_bytes(self):
3492        h = (self.pb_flag << 12) | (self.bc_flag << 14) | self.connection_handle
3493        return struct.pack('<BHH', HCI_ACL_DATA_PACKET, h, self.data_total_length) + self.data
3494
3495    def __init__(self, connection_handle, pb_flag, bc_flag, data_total_length, data):
3496        self.connection_handle = connection_handle
3497        self.pb_flag = pb_flag
3498        self.bc_flag = bc_flag
3499        self.data_total_length = data_total_length
3500        self.data = data
3501
3502    def __bytes__(self):
3503        return self.to_bytes()
3504
3505    def __str__(self):
3506        return f'{color("ACL", "blue")}: handle=0x{self.connection_handle:04x}, pb={self.pb_flag}, bc={self.bc_flag}, data_total_length={self.data_total_length}, data={self.data.hex()}'
3507
3508
3509# -----------------------------------------------------------------------------
3510class HCI_AclDataPacketAssembler:
3511    def __init__(self, callback):
3512        self.callback         = callback
3513        self.current_data     = None
3514        self.l2cap_pdu_length = 0
3515
3516    def feed_packet(self, packet):
3517        if packet.pb_flag == HCI_ACL_PB_FIRST_NON_FLUSHABLE or packet.pb_flag == HCI_ACL_PB_FIRST_FLUSHABLE:
3518            (l2cap_pdu_length,)   = struct.unpack_from('<H', packet.data, 0)
3519            self.current_data     = packet.data
3520            self.l2cap_pdu_length = l2cap_pdu_length
3521        elif packet.pb_flag == HCI_ACL_PB_CONTINUATION:
3522            if self.current_data is None:
3523                logger.warning('!!! ACL continuation without start')
3524                return
3525            self.current_data += packet.data
3526
3527        if len(self.current_data) == self.l2cap_pdu_length + 4:
3528            # The packet is complete, invoke the callback
3529            logger.debug(f'<<< ACL PDU: {self.current_data.hex()}')
3530            self.callback(self.current_data)
3531
3532            # Reset
3533            self.current_data     = None
3534            self.l2cap_pdu_length = 0
3535        else:
3536            # Sanity check
3537            if len(self.current_data) > self.l2cap_pdu_length + 4:
3538                logger.warning('!!! ACL data exceeds L2CAP PDU')
3539                self.current_data     = None
3540                self.l2cap_pdu_length = 0
3541