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# ----------------------------------------------------------------------------- 18from bumble.hci import * 19 20 21# ----------------------------------------------------------------------------- 22def basic_check(x): 23 packet = x.to_bytes() 24 print(packet.hex()) 25 parsed = HCI_Packet.from_bytes(packet) 26 x_str = str(x) 27 parsed_str = str(parsed) 28 print(x_str) 29 parsed_bytes = parsed.to_bytes() 30 assert(x_str == parsed_str) 31 assert(packet == parsed_bytes) 32 33 34# ----------------------------------------------------------------------------- 35def test_HCI_Event(): 36 event = HCI_Event(0xF9) 37 basic_check(event) 38 39 event = HCI_Event(0xF8, bytes.fromhex('AABBCC')) 40 basic_check(event) 41 42 43# ----------------------------------------------------------------------------- 44def test_HCI_LE_Connection_Complete_Event(): 45 address = Address('00:11:22:33:44:55') 46 event = HCI_LE_Connection_Complete_Event( 47 status = HCI_SUCCESS, 48 connection_handle = 1, 49 role = 1, 50 peer_address_type = 1, 51 peer_address = address, 52 conn_interval = 3, 53 conn_latency = 4, 54 supervision_timeout = 5, 55 master_clock_accuracy = 6 56 ) 57 basic_check(event) 58 59 60# ----------------------------------------------------------------------------- 61def test_HCI_LE_Advertising_Report_Event(): 62 address = Address('00:11:22:33:44:55') 63 report = HCI_Object( 64 HCI_LE_Advertising_Report_Event.REPORT_FIELDS, 65 event_type = HCI_LE_Advertising_Report_Event.ADV_IND, 66 address_type = Address.PUBLIC_DEVICE_ADDRESS, 67 address = address, 68 data = bytes.fromhex('0201061106ba5689a6fabfa2bd01467d6e00fbabad08160a181604659b03'), 69 rssi = 100 70 ) 71 event = HCI_LE_Advertising_Report_Event([report]) 72 basic_check(event) 73 74 75# ----------------------------------------------------------------------------- 76def test_HCI_LE_Read_Remote_Features_Complete_Event(): 77 event = HCI_LE_Read_Remote_Features_Complete_Event( 78 status = HCI_SUCCESS, 79 connection_handle = 0x007, 80 le_features = bytes.fromhex('0011223344556677') 81 ) 82 basic_check(event) 83 84 85# ----------------------------------------------------------------------------- 86def test_HCI_LE_Connection_Update_Complete_Event(): 87 event = HCI_LE_Connection_Update_Complete_Event( 88 status = HCI_SUCCESS, 89 connection_handle = 0x007, 90 conn_interval = 10, 91 conn_latency = 3, 92 supervision_timeout = 5 93 ) 94 basic_check(event) 95 96 97# ----------------------------------------------------------------------------- 98def test_HCI_LE_Channel_Selection_Algorithm_Event(): 99 event = HCI_LE_Channel_Selection_Algorithm_Event( 100 connection_handle = 7, 101 channel_selection_algorithm = 1 102 ) 103 basic_check(event) 104 105 106# ----------------------------------------------------------------------------- 107def test_HCI_Command_Complete_Event(): 108 # With a serializable object 109 event = HCI_Command_Complete_Event( 110 num_hci_command_packets = 34, 111 command_opcode = HCI_LE_READ_BUFFER_SIZE_COMMAND, 112 return_parameters = HCI_LE_Read_Buffer_Size_Command.create_return_parameters( 113 status = 0, 114 hc_le_acl_data_packet_length = 1234, 115 hc_total_num_le_acl_data_packets = 56 116 ) 117 ) 118 basic_check(event) 119 120 # With an arbitrary byte array 121 event = HCI_Command_Complete_Event( 122 num_hci_command_packets = 1, 123 command_opcode = HCI_RESET_COMMAND, 124 return_parameters = bytes([1, 2, 3, 4]) 125 ) 126 basic_check(event) 127 128 # With a simple status as a 1-byte array 129 event = HCI_Command_Complete_Event( 130 num_hci_command_packets = 1, 131 command_opcode = HCI_RESET_COMMAND, 132 return_parameters = bytes([7]) 133 ) 134 basic_check(event) 135 event = HCI_Packet.from_bytes(event.to_bytes()) 136 assert(event.return_parameters == 7) 137 138 # With a simple status as an integer status 139 event = HCI_Command_Complete_Event( 140 num_hci_command_packets = 1, 141 command_opcode = HCI_RESET_COMMAND, 142 return_parameters = 9 143 ) 144 basic_check(event) 145 assert(event.return_parameters == 9) 146 147 148# ----------------------------------------------------------------------------- 149def test_HCI_Command_Status_Event(): 150 event = HCI_Command_Status_Event( 151 status = 0, 152 num_hci_command_packets = 37, 153 command_opcode = HCI_DISCONNECT_COMMAND 154 ) 155 basic_check(event) 156 157 158# ----------------------------------------------------------------------------- 159def test_HCI_Number_Of_Completed_Packets_Event(): 160 event = HCI_Number_Of_Completed_Packets_Event([ 161 (1, 2), 162 (3, 4) 163 ]) 164 basic_check(event) 165 166 167# ----------------------------------------------------------------------------- 168def test_HCI_Command(): 169 command = HCI_Command(0x5566) 170 basic_check(command) 171 172 command = HCI_Command(0x5566, bytes.fromhex('AABBCC')) 173 basic_check(command) 174 175 176# ----------------------------------------------------------------------------- 177def test_HCI_Reset_Command(): 178 command = HCI_Reset_Command() 179 basic_check(command) 180 181 182# ----------------------------------------------------------------------------- 183def test_HCI_Read_Local_Version_Information_Command(): 184 command = HCI_Read_Local_Version_Information_Command() 185 basic_check(command) 186 187 188# ----------------------------------------------------------------------------- 189def test_HCI_Read_Local_Supported_Commands_Command(): 190 command = HCI_Read_Local_Supported_Commands_Command() 191 basic_check(command) 192 193 194# ----------------------------------------------------------------------------- 195def test_HCI_Read_Local_Supported_Features_Command(): 196 command = HCI_Read_Local_Supported_Features_Command() 197 basic_check(command) 198 199 200# ----------------------------------------------------------------------------- 201def test_HCI_Disconnect_Command(): 202 command = HCI_Disconnect_Command( 203 connection_handle = 123, 204 reason = 0x11 205 ) 206 basic_check(command) 207 208 209# ----------------------------------------------------------------------------- 210def test_HCI_Set_Event_Mask_Command(): 211 command = HCI_Set_Event_Mask_Command( 212 event_mask = bytes.fromhex('0011223344556677') 213 ) 214 basic_check(command) 215 216 217# ----------------------------------------------------------------------------- 218def test_HCI_LE_Set_Event_Mask_Command(): 219 command = HCI_LE_Set_Event_Mask_Command( 220 le_event_mask = bytes.fromhex('0011223344556677') 221 ) 222 basic_check(command) 223 224 225# ----------------------------------------------------------------------------- 226def test_HCI_LE_Set_Random_Address_Command(): 227 command = HCI_LE_Set_Random_Address_Command( 228 random_address = Address('00:11:22:33:44:55') 229 ) 230 basic_check(command) 231 232 233# ----------------------------------------------------------------------------- 234def test_HCI_LE_Set_Advertising_Parameters_Command(): 235 command = HCI_LE_Set_Advertising_Parameters_Command( 236 advertising_interval_min = 20, 237 advertising_interval_max = 30, 238 advertising_type = HCI_LE_Set_Advertising_Parameters_Command.ADV_NONCONN_IND, 239 own_address_type = Address.PUBLIC_DEVICE_ADDRESS, 240 peer_address_type = Address.RANDOM_DEVICE_ADDRESS, 241 peer_address = Address('00:11:22:33:44:55'), 242 advertising_channel_map = 0x03, 243 advertising_filter_policy = 1 244 ) 245 basic_check(command) 246 247 248# ----------------------------------------------------------------------------- 249def test_HCI_LE_Set_Advertising_Data_Command(): 250 command = HCI_LE_Set_Advertising_Data_Command( 251 advertising_data = bytes.fromhex('AABBCC') 252 ) 253 basic_check(command) 254 255 256# ----------------------------------------------------------------------------- 257def test_HCI_LE_Set_Scan_Parameters_Command(): 258 command = HCI_LE_Set_Scan_Parameters_Command( 259 le_scan_type = 1, 260 le_scan_interval = 20, 261 le_scan_window = 10, 262 own_address_type = 1, 263 scanning_filter_policy = 0 264 ) 265 basic_check(command) 266 267 268# ----------------------------------------------------------------------------- 269def test_HCI_LE_Set_Scan_Enable_Command(): 270 command = HCI_LE_Set_Scan_Enable_Command( 271 le_scan_enable = 1, 272 filter_duplicates = 0 273 ) 274 basic_check(command) 275 276 277# ----------------------------------------------------------------------------- 278def test_HCI_LE_Create_Connection_Command(): 279 command = HCI_LE_Create_Connection_Command( 280 le_scan_interval = 4, 281 le_scan_window = 5, 282 initiator_filter_policy = 1, 283 peer_address_type = 1, 284 peer_address = Address('00:11:22:33:44:55'), 285 own_address_type = 2, 286 conn_interval_min = 7, 287 conn_interval_max = 8, 288 conn_latency = 9, 289 supervision_timeout = 10, 290 minimum_ce_length = 11, 291 maximum_ce_length = 12 292 ) 293 basic_check(command) 294 295 296# ----------------------------------------------------------------------------- 297def test_HCI_LE_Add_Device_To_White_List_Command(): 298 command = HCI_LE_Add_Device_To_White_List_Command( 299 address_type = 1, 300 address = Address('00:11:22:33:44:55') 301 ) 302 basic_check(command) 303 304 305# ----------------------------------------------------------------------------- 306def test_HCI_LE_Remove_Device_From_White_List_Command(): 307 command = HCI_LE_Remove_Device_From_White_List_Command( 308 address_type = 1, 309 address = Address('00:11:22:33:44:55') 310 ) 311 basic_check(command) 312 313 314# ----------------------------------------------------------------------------- 315def test_HCI_LE_Connection_Update_Command(): 316 command = HCI_LE_Connection_Update_Command( 317 connection_handle = 0x0002, 318 conn_interval_min = 10, 319 conn_interval_max = 20, 320 conn_latency = 7, 321 supervision_timeout = 3, 322 minimum_ce_length = 100, 323 maximum_ce_length = 200 324 ) 325 basic_check(command) 326 327 328# ----------------------------------------------------------------------------- 329def test_HCI_LE_Read_Remote_Features_Command(): 330 command = HCI_LE_Read_Remote_Features_Command( 331 connection_handle = 0x0002 332 ) 333 basic_check(command) 334 335 336# ----------------------------------------------------------------------------- 337def test_HCI_LE_Set_Default_PHY_Command(): 338 command = HCI_LE_Set_Default_PHY_Command( 339 all_phys = 0, 340 tx_phys = 1, 341 rx_phys = 1 342 ) 343 basic_check(command) 344 345 346# ----------------------------------------------------------------------------- 347def test_address(): 348 a = Address('C4:F2:17:1A:1D:BB') 349 assert(not a.is_public) 350 assert(a.is_random) 351 assert(a.address_type == Address.RANDOM_DEVICE_ADDRESS) 352 assert(not a.is_resolvable) 353 assert(not a.is_resolved) 354 assert(a.is_static) 355 356 357# ----------------------------------------------------------------------------- 358def test_custom(): 359 data = bytes([0x77, 0x02, 0x01, 0x03]) 360 packet = HCI_CustomPacket(data) 361 assert(packet.hci_packet_type == 0x77) 362 assert(packet.payload == data) 363 364 365# ----------------------------------------------------------------------------- 366def run_test_events(): 367 test_HCI_Event() 368 test_HCI_LE_Connection_Complete_Event() 369 test_HCI_LE_Advertising_Report_Event() 370 test_HCI_LE_Connection_Update_Complete_Event() 371 test_HCI_LE_Read_Remote_Features_Complete_Event() 372 test_HCI_LE_Channel_Selection_Algorithm_Event() 373 test_HCI_Command_Complete_Event() 374 test_HCI_Command_Status_Event() 375 test_HCI_Number_Of_Completed_Packets_Event() 376 377 378# ----------------------------------------------------------------------------- 379def run_test_commands(): 380 test_HCI_Command() 381 test_HCI_Reset_Command() 382 test_HCI_Read_Local_Version_Information_Command() 383 test_HCI_Read_Local_Supported_Commands_Command() 384 test_HCI_Read_Local_Supported_Features_Command() 385 test_HCI_Disconnect_Command() 386 test_HCI_Set_Event_Mask_Command() 387 test_HCI_LE_Set_Event_Mask_Command() 388 test_HCI_LE_Set_Random_Address_Command() 389 test_HCI_LE_Set_Advertising_Parameters_Command() 390 test_HCI_LE_Set_Advertising_Data_Command() 391 test_HCI_LE_Set_Scan_Parameters_Command() 392 test_HCI_LE_Set_Scan_Enable_Command() 393 test_HCI_LE_Create_Connection_Command() 394 test_HCI_LE_Add_Device_To_White_List_Command() 395 test_HCI_LE_Remove_Device_From_White_List_Command() 396 test_HCI_LE_Connection_Update_Command() 397 test_HCI_LE_Read_Remote_Features_Command() 398 test_HCI_LE_Set_Default_PHY_Command() 399 400 401# ----------------------------------------------------------------------------- 402if __name__ == '__main__': 403 run_test_events() 404 run_test_commands() 405 test_address() 406 test_custom() 407