1# -*- coding: utf-8 -*- 2# Copyright 2019 Oticon A/S 3# SPDX-License-Identifier: Apache-2.0 4 5# from enum import IntFlag; 6from components.utils import *; 7from components.basic_commands import *; 8from components.address import *; 9from components.events import *; 10from components.scanner import *; 11 12# class LE_Events(IntFlag): 13# LE_Connection_Complete_Event = 1<<0 14# LE_Advertising_Report_Event = 1<<1 15# LE_Connection_Update_Complete_Event = 1<<2 16# LE_Read_Remote_Features_Complete_Event = 1<<3 17# LE_Long_Term_Key_Request_Event = 1<<4 18# LE_Remote_Connection_Parameter_Request_Event = 1<<5 19# LE_Data_Length_Change_Event = 1<<6 20# LE_Read_Local_P_256_Public_Key_Complete_Event = 1<<7 21# LE_Generate_DHKey_Complete_Event = 1<<8 22# LE_Enhanced_Connection_Complete_Event = 1<<9 23# LE_Directed_Advertising_Report_Event = 1<<10 24# LE_PHY_Update_Complete_Event = 1<<11 25# LE_Extended_Advertising_Report_Event = 1<<12 26# LE_Periodic_Advertising_Sync_Established_Event = 1<<13 27# LE_Periodic_Advertising_Report_Event = 1<<14 28# LE_Periodic_Advertising_Sync_Lost_Event = 1<<15 29# LE_Extended_Scan_Timeout_Event = 1<<16 30# LE_Extended_Advertising_Set_Terminated_Event = 1<<17 31# LE_Scan_Request_Received_Event = 1<<18 32# LE_Channel_Selection_Algorithm_Event = 1<<19 33# LE_Events_All = (1<<20)-1 34 35def __verifyAndShowEvent(transport, idx, expectedEvent, trace): 36 37 event = get_event(transport, idx, 100); 38 trace.trace(7, str(event)); 39 return event.event == expectedEvent; 40 41def __verifyAndShowMetaEvent(transport, idx, expectedEvent, trace): 42 43 event = get_event(transport, idx, 100); 44 trace.trace(7, str(event)); 45 return event.subEvent == expectedEvent; 46 47def __verifyAndFetchEvent(transport, idx, expectedEvent, trace): 48 49 event = get_event(transport, idx, 100)[1:]; 50 trace.trace(7, str(event)); 51 return event.event == expectedEvent, event.data; 52 53def __verifyAndFetchMetaEvent(transport, idx, expectedEvent, trace): 54 55 event = get_event(transport, idx, 100)[1:]; 56 trace.trace(7, str(event)); 57 return event.subEvent == expectedEvent, event.data; 58 59def __getCommandCompleteEvent(transport, idx, trace): 60 61 return __verifyAndShowEvent(transport, idx, Events.BT_HCI_EVT_CMD_COMPLETE, trace); 62 63def __random(transport, idx, trace): 64 status, rand = le_rand(transport, idx, 100); 65 trace.trace(6, "LE Rand Command returns status: 0x%02X; rand: 0x%016X" % (status, toNumber(rand))); 66 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 67 return success, rand; 68 69def __encrypt(transport, idx, key, plaintext, trace): 70 status, encrypted = le_encrypt(transport, idx, key, plaintext, 2000); 71 trace.trace(6, "LE Encrypt Command returns status: 0x%02X" % status); 72 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 73 return success, encrypted; 74 75""" 76 Prepare for testing, by 77 - Resetting the DUT 78 - Read Local Supported Features and insure that 'LE Supported (Controller)' and 'BR/EDR Not Supported' are both set 79 - Read LE Local Supported Features 80 - Set Event Masks: 'Event Mask', 'LE Event Mask' and 'Event Mask Page 2' 81 82 Returns a boolean indicating whether all went well. 83""" 84def preamble_standby(transport, idx, trace): 85 trace.trace(3, "Standby preamble steps..."); 86 87 try: 88 flush_events(transport, idx, 100); 89 le_data_flush(transport, idx, 100); 90 91 status = reset(transport, idx, 100); 92 trace.trace(6, "Reset Command returns status: 0x%02X" % status); 93 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 94 if not success: 95 trace.trace(6, "RESET command not confirmed!"); 96 97 status, features = read_local_supported_features(transport, idx, 100); 98 trace.trace(6, "Read Local Supported Features Command returns status: 0x%02X" % status); 99 """ 100 Check that features 'BR/EDR Not Supported' and 'LE Supported (Controller)' are both enabled 101 """ 102 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and ((features[4] & 0x60) == 0x60) and success; 103 104 status, features = le_read_local_supported_features(transport, idx, 100); 105 trace.trace(6, "LE Read Local Supported Features Command returns status: 0x%02X" % status); 106 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and success; 107 """ 108 Bit Parameter Description 109 0 Inquiry Complete Event 110 1 Inquiry Result Event 111 2 Connection Complete Event 112 3 Connection Request Event 113 4 Disconnection Complete Event 114 5 Authentication Complete Event 115 6 Remote Name Request Complete Event 116 7 Encryption Change Event 117 8 Change Connection Link Key Complete Event 118 9 Central Link Key Complete Event 119 10 Read Remote Supported Features Complete Event 120 11 Read Remote Version Information Complete Event 121 12 QoS Setup Complete Event 122 13 Reserved for future use 123 14 Reserved for future use 124 15 Hardware Error Event 125 16 Flush Occurred Event 126 17 Role Change Event 127 18 Reserved for future use 128 19 Mode Change Event 129 20 Return Link Keys Event 130 21 PIN Code Request Event 131 22 Link Key Request Event 132 23 Link Key Notification Event 133 24 Loopback Command Event 134 25 Data Buffer Overflow Event 135 26 Max Slots Change Event 136 27 Read Clock Offset Complete Event 137 28 Connection Packet Type Changed Event 138 29 QoS Violation Event 139 30 Page Scan Mode Change Event [deprecated] 140 31 Page Scan Repetition Mode Change Event 141 32 Flow Specification Complete Event 142 33 Inquiry Result with RSSI Event 143 34 Read Remote Extended Features Complete Event 144 35 Reserved for future use 145 36 Reserved for future use 146 37 Reserved for future use 147 38 Reserved for future use 148 39 Reserved for future use 149 40 Reserved for future use 150 41 Reserved for future use 151 42 Reserved for future use 152 43 Synchronous Connection Complete Event 153 44 Synchronous Connection Changed Event 154 45 Sniff Subrating Event 155 46 Extended Inquiry Result Event 156 47 Encryption Key Refresh Complete Event 157 48 IO Capability Request Event 158 49 IO Capability Response Event 159 50 User Confirmation Request Event 160 51 User Passkey Request Event 161 52 Remote OOB Data Request Event 162 53 Simple Pairing Complete Event 163 54 Reserved for future use 164 55 Link Supervision Timeout Changed Event 165 56 Enhanced Flush Complete Event 166 57 Reserved for Future Use 167 58 User Passkey Notification Event 168 59 Keypress Notification Event 169 60 Remote Host Supported Features Notification Event 170 61 LE Meta Event 171 62 Reserved for future use 172 63 Reserved for future use 173 174 Bit: 5 4 4 3 2 1 0 0 175 6 8 0 2 4 6 8 0 176 0x00 00 1F FF FF FF FF FF ~ Default. 177 0x20 00 9F FF FF FF FF FF ~ Default + Bit 47 ~ Encryption Key Refresh Complete Event + Bit 61 ~ LE Meta Event 178 """ 179 180 events = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x00, 0x20]; 181 status = set_event_mask(transport, idx, events, 100); 182 trace.trace(6, "Set Event Mask Command returns status: 0x%02X" % status); 183 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and success; 184 """ 185 Bit LE Subevent Types 186 0 LE Connection Complete Event 187 1 LE Advertising Report Event 188 2 LE Connection Update Complete Event 189 3 LE Read Remote Features Complete Event 190 4 LE Long Term Key Request Event 191 5 LE Remote Connection Parameter Request Event 192 6 LE Data Length Change Event 193 7 LE Read Local P-256 Public Key Complete Event 194 8 LE Generate DHKey Complete Event 195 9 LE Enhanced Connection Complete Event 196 10 LE Directed Advertising Report Event 197 11 LE PHY Update Complete Event 198 12 LE Extended Advertising Report Event 199 13 LE Periodic Advertising Sync Established Event 200 14 LE Periodic Advertising Report Event 201 15 LE Periodic Advertising Sync Lost Event 202 16 LE Extended Scan Timeout Event 203 17 LE Extended Advertising Set Terminated Event 204 18 LE Scan Request Received Event 205 19 LE Channel Selection Algorithm Event 206 20 LE Connectionless IQ Report event 207 21 LE Connection IQ Report event 208 22 LE CTE Request Failed event 209 23 LE Periodic Advertising Sync Transfer Received event 210 24 LE CIS Established event 211 25 LE CIS Request event 212 26 LE Create BIG Complete event 213 27 LE Terminate BIG Complete event 214 28 LE BIG Sync Established event 215 29 LE BIG Sync Lost event 216 30 LE Request Peer SCA Complete event 217 31 LE Path Loss Threshold event 218 32 LE Transmit Power Reporting event 219 33 LE BIGInfo Advertising Report event 220 221 Bit: 5 4 4 3 2 1 0 0 222 6 8 0 2 4 6 8 0 223 0x00 00 00 00 00 00 00 1F ~ Default. 224 0x00 00 00 03 FF F7 FF FF ~ All except 'LE Channel Selection Algorithm Event' 225 """ 226 227 events = [0xFF, 0xFF, 0xF7, 0xFF, 0x03, 0x00, 0x00, 0x00]; 228 status = le_set_event_mask(transport, idx, events, 100); 229 trace.trace(6, "LE Set Event Mask Command returns status: 0x%02X" % status); 230 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and success; 231 """ 232 0x00 00 00 00 00 00 00 00 ~ Default. 233 """ 234 events = [0 for _ in range(8)]; 235 236 status = set_event_mask_page_2(transport, idx, events, 100); 237 trace.trace(6, "Set Event Mask Page2 Command returns status: 0x%02X" % status); 238 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and success; 239 except Exception as e: 240 import traceback 241 traceback.print_exc() 242 trace.trace(3, "Standby preamble steps failed: %s" % str(e)); 243 success = False; 244 245 return success; 246 247""" 248 Calculate IRK from IR 249""" 250def __calculateIRK(transport, idx, key, trace): 251 plaintext = [1 if i == 0 else 0 for i in range(16)]; 252 success, irk = __encrypt(transport, idx, key, plaintext, trace); 253 return success, irk; 254 255""" 256 Generate a random static address from IRK 257""" 258def preamble_random_static_address(transport, idx, key, trace): 259 success, rand = __random(transport, idx, trace); 260 261 nrand = (toNumber(rand) & 0xFFFFFF) | 0xC00000; 262 _success, localHash = __encrypt(transport, idx, key, toArray(nrand, 16), trace); 263 success = success and _success; 264 265 nlocalHash = toNumber(localHash) & 0xFFFFFF; 266 address = nlocalHash | (nrand << 24); 267 return success, toArray(address, 6); 268 269""" 270 Generate a private non-resolvable random address from IRK 271""" 272def preamble_random_non_resolvable_address(transport, idx, key, trace): 273 success, rand = __random(transport, idx, trace); 274 275 nrand = toNumber(rand) & 0x3FFFFF; 276 _success, localHash = __encrypt(transport, idx, key, toArray(nrand, 16), trace); 277 success = success and _success; 278 279 nlocalHash = toNumber(localHash) & 0xFFFFFF; 280 address = nlocalHash | (nrand << 24); 281 return success, toArray(address, 6); 282 283""" 284 Calculates a Random Private Address based on the IR (passed to the function) 285 286 The random address generation behavior is an extract from GAP [1] Section 2.1.2 and represents here the typical HCI sequences required from a Controller. 287 The identity resolving key ‘irk’ is used in the test procedures in group ‘SEC’. 288 289 key is the IR - Identity Root 290""" 291def preamble_random_address_calculated(transport, idx, key, trace): 292 trace.trace(4, "Random Address Calculated preamble steps..."); 293 294 try: 295 """ 296 Generate IRK from IR 297 """ 298 success, irk = __calculateIRK(transport, idx, key, trace); 299 trace.trace(7, "IRK: 0x%032X" % toNumber(irk)); 300 301 _success, address = preamble_random_static_address(transport, idx, irk, trace); 302 success = success and _success; 303 trace.trace(7, "Random address: 0x%012X" % toNumber(address)); 304 305 except Exception as e: 306 trace.trace(3, "Random Address Calculated preamble failed: %s" % str(e)); 307 success = False; 308 address = [0 for _ in range(6)]; 309 310 return (success, irk, address); 311 312""" 313 Calculates Encryption Keys based on the IR (identity root) and the ER (encryption root) 314 315 Encryption keys are input to a Controller from [1](part H, section 2.4.2). 316 The identity root, IR is referred to as 'ir' and has the default value 0x112233445566778899AABBCCDDEEFF00. 317 The encryption root, ER is referred to as 'er' and has the default value 0x112233445566778899AABBCCDDEEFF00. 318""" 319def preamble_encryption_keys_calculated(transport, idx, trace): 320 trace.trace(4, "Encryption Keys Calculated preamble steps..."); 321 322 try: 323 success, div = __random(transport, idx, trace); 324 325 _success, rand = __random(transport, idx, trace); 326 success = success and _success; 327 328 ir = er = 0x112233445566778899AABBCCDDEEFF00; 329 330 _success, dhk = __encrypt(transport, idx, toArray(ir, 16), toArray(0x02, 16), trace); 331 success = success and _success; 332 333 _success, y = __encrypt(transport, idx, dhk, rand, trace); 334 success = success and _success; 335 336 _success, ltk = __encrypt(transport, idx, toArray(er, 16), div, trace); 337 success = success and _success; 338 trace.trace(6, "Generated LTK: 0x%032X" % toNumber(ltk)); 339 340 ediv = toArray(toNumber(y) ^ toNumber(div), 16); 341 ediv = ediv[:2] 342 343 except Exception as e: 344 trace.trace(3, "Encryption Keys Calculated preamble failed: %s" % str(e)); 345 success = False; 346 rand = [0 for _ in range(8)]; 347 ediv = [0 for _ in range(2)]; 348 ltk = [0 for _ in range(16)]; 349 350 return success, toNumber(rand), toNumber(ediv), ltk 351 352def preamble_set_public_address(transport, idx, address, trace): 353 trace.trace(4, "Set Public Address preamble steps..."); 354 355 try: 356 status = write_bd_addr(transport, idx, toArray(address, 6), 100); 357 trace.trace(6, "Write BD_ADDR Command returns status: 0x%02X" % status); 358 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 359 except Exception as e: 360 trace.trace(3, "Set Public Address preamble failed: %s" % str(e)); 361 success = False; 362 363 return success; 364 365""" 366 The preamble_set_random_address function can be used to set three different kinds of random addresses. 367 368 See [Vol 6] Part B, Section 1.3 - 369 370 - A Static address (two MSBs are 11) 371 - A static address is a 48-bit randomly generated address and shall meet the following requirements: 372 • The two most significant bits of the address shall be equal to 1 373 • At least one bit of the random part of the address shall be 0 374 • At least one bit of the random part of the address shall be 1 375 - A Private address 376 - A non-resolvable Private adress (two MSBs are 00) 377 - To generate a non-resolvable address, the device shall generate a 48-bit address with the following requirements: 378 • The two most significant bits of the address shall be equal to 0 379 • At least one bit of the random part of the address shall be 1 380 • At least one bit of the random part of the address shall be 0 381 • The address shall not be equal to the public address 382 - A resolvable Private address (two MSBs are 01) 383 - To generate a resolvable private address, the device must have either the Local Identity Resolving Key (IRK) or the Peer Identity Resolving Key (IRK). 384 The resolvable private address shall be generated with the IRK and a randomly generated 24-bit number. The random number is known as prand and shall 385 meet the following requirements: 386 • The two most significant bits of prand shall be equal to 0 and 1. 387 • At least one bit of the random part of prand shall be 0 388 • At least one bit of the random part of prand shall be 1 389""" 390def preamble_set_random_address(transport, idx, address, trace): 391 trace.trace(4, "Set Random Address preamble steps..."); 392 393 try: 394 status = le_set_random_address(transport, idx, toArray(address, 6), 100); 395 trace.trace(6, "LE Set Random Address Command returns status: 0x%02X" % status); 396 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 397 except Exception as e: 398 trace.trace(3, "Set Random Address preamble failed: %s" % str(e)); 399 success = False; 400 401 return success; 402 403 404""" 405 When the IUT is in advertising state or peripheral role, a default value for the scanning, initiating or central address used is 0x123456789ABC. 406 When the IUT is in scanning state, initiating state or central role, a default value for the address used for the state of advertising 407 or the role of peripheral is 0x456789ABCDEF. 408 409 When it is required to modify the Lower Tester address either in the company_assigned field, the company_id field, 410 it has to be done by exchanging bytes 1 and 3 of company_assigned field or company_id field. 411 If it is required to modify the Lower Tester address in the company_assigned and company_id fields, 412 it has to be done by exchanging bytes 1 of company_assigned and company_id fields. 413""" 414def preamble_device_address_set(transport, idx, trace): 415 trace.trace(4, "Device Address Set preamble steps..."); 416 417 try: 418 """ 419 The Identity Root IR has the default value 0x112233445566778899AABBCCDDEEFF00 420 """ 421 ir = 0x00112233445566778899AABBCCDDEEFF if idx == 0 else 0x112233445566778899AABBCCDDEEFF00; 422 trace.trace(6, "Using default identity root value ir: 0x%032X" % ir); 423 424 success, irk, randAddress = preamble_random_address_calculated(transport, idx, toArray(ir, 16), trace); 425 trace.trace(6, "Generated IRK: 0x%032X" % toNumber(irk)); 426 trace.trace(6, "Generated random address %s" % formatAddress(randAddress)); 427 success = True; 428 429 address = 0x123456789ABC if idx == 0 else 0x456789ABCDEF; 430 success = success and preamble_set_public_address(transport, idx, address, trace); 431 success = success and preamble_set_random_address(transport, idx, toNumber(randAddress), trace); 432 433 except Exception as e: 434 trace.trace(3, "Device address set preamble failed: %s" % str(e)); 435 success = False; 436 irk = [0 for _ in range(16)]; 437 438 return (success, irk, randAddress); 439 440""" 441 The Bluetooth address (BD_ADDR) is 48 bit unique number. BD_ADDR ~ (NAP | UAP | LAP) - OUI ~ (NAP | UAP). 442 The most significant 16 bits - the NAP - is a company specific id. 443 The next significant 8 bits - the UAP - is a company specific id. 444 The least significant 24 bits - the LAP - is a company assigned number. 445 446 The upper half of a Bluetooth Address (most-significant 24 bits) is so called Organizationally Unique Identifier (OUI). 447 It can be used to determine the manufacturer of a device (Bluetooth MAC Address Lookup form). 448 OUI prefixes are assigned by the Institute of Electrical and Electronics Engineers (IEEE). 449 450 NAP 451 Non-significant Address Part (2 bytes). Contains first 16 bits of the OUI. 452 The NAP value is used in Frequency Hopping Synchronization frames. 453 UAP 454 Upper Address Part (1 byte). Contains remaining 8 bits of the OUI. 455 The UAP value is used for seeding in various Bluetooth specification algorithms. 456 LAP 457 Lower Address Part (3 bytes). This portion of Bluetooth Address is allocated by the vendor of device. 458 The LAP value uniquely identifies a Bluetooth device as part of the Access Code in every transmitted frame. 459 The LAP and the UAP make the significant address part (SAP) of the Bluetooth Address. 460""" 461 462""" 463 Scramble the company_id part of the Bluetooth address. 464""" 465def address_scramble_OUI(address): 466 return (address ^ 0xff00ff000000); 467 468""" 469 Scramble the company_assigned part of the Bluetooth address. 470""" 471def address_scramble_LAP(address): 472 return (address ^ 0x000000ff00ff); 473 474""" 475 Scramble both the company_id part and the company_assigned part of the Bluetooth address. 476""" 477def address_exchange_OUI_LAP(address): 478 return (address ^ 0xff00000000ff); 479 480def preamble_specific_filter_accept_listed(transport, idx, addresses, trace): 481 trace.trace(5, "Specific Filter Accept Listed preamble steps..."); 482 483 try: 484 status = le_clear_filter_accept_list(transport, idx, 100); 485 trace.trace(6, "LE Clear Filter Accept List Command returns status: 0x%02X" % status); 486 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 487 488 for i in range(len(addresses)): 489 address = toArray(addresses[i][1], 6); 490 trace.trace(7, "Addding Device to Filter Accept List %s" % formatAddress(address, addresses[i][0])); 491 status = le_add_device_to_filter_accept_list(transport, idx, addresses[i][0], address, 100); 492 trace.trace(6, "LE Add Device to Filter Accept List Command returns status: 0x%02X" % status); 493 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and success; 494 except Exception as e: 495 trace.trace(3, "Specific Filter Accept Listed preamble failed: %s" % str(e)); 496 success = False; 497 498 return success; 499 500def preamble_buffer_size_read(transport, idx, trace): 501 trace.trace(5, "Buffer Size Read preamble steps..."); 502 503 try: 504 status, LeMaxLen, LeMaxNum = le_read_buffer_size(transport, idx, 100); 505 trace.trace(6, "LE Read Buffer Size Command returns status: 0x%02X" % status); 506 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 507 508 if LeMaxLen == 0 and LeMaxNum == 0: 509 status, AclMaxLen, ScoMaxLen, AclMaxNum, ScoMaxNum = read_buffer_size(transport, idx, 100); 510 trace.trace(6, "Read Buffer Size Command returns status: 0x%02X" % status); 511 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and success; 512 """ 513 0x90 88 01 00 00 80 00 20 ~ 0x2000800000018890 514 """ 515 events = [0x90, 0x88, 0x01, 0x00, 0x00, 0x80, 0x00, 0x20]; 516 517 status = set_event_mask(transport, idx, events, 100); 518 trace.trace(6, "Set Event Mask Command returns status: 0x%02X" % status); 519 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0) and success; 520 except Exception as e: 521 trace.trace(3, "Buffer Size Read preamble failed: %s" % str(e)); 522 success = False; 523 524 return success; 525 526def preamble_ext_advertising_parameters_set(transport, idx, Handle, Properties, PrimMinInterval, PrimMaxInterval, PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower, PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace): 527 trace.trace(5, "Extended Advertising Parameters Set preamble steps..."); 528 529 try: 530 status = le_set_extended_advertising_parameters(transport, idx, Handle, Properties, PrimMinInterval, PrimMaxInterval, PrimChannelMap, OwnAddrType, PeerAddrType, \ 531 PeerAddress, FilterPolicy, TxPower, PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, 100); 532 trace.trace(6, "LE Set Extended Advertising Parameters Command returns status: 0x%02X" % status); 533 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 534 except Exception as e: 535 trace.trace(3, "Extended Advertising Parameters Set preamble failed: %s" % str(e)); 536 success = False; 537 538 return success; 539 540def preamble_ext_advertising_data_set(transport, idx, Handle, Operation, FragPreference, advData, trace): 541 trace.trace(5, "Extended Advertising Data Set preamble steps..."); 542 543 try: 544 advertiseData = advData[ : ]; 545 if len(advData) > 251: 546 advertiseData = advertiseData[:251]; 547 548 status = le_set_extended_advertising_data(transport, idx, Handle, Operation, FragPreference, advertiseData, 100); 549 trace.trace(6, "LE Set Extended Advertising Data Command returns status: 0x%02X" % status); 550 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 551 except Exception as e: 552 trace.trace(3, "Extended Advertising Data Set preamble failed: %s" % str(e)); 553 success = False; 554 555 return success; 556 557def preamble_ext_scan_response_data_set(transport, idx, Handle, Operation, FragPreference, advData, trace): 558 trace.trace(5, "Extended Scan Response Data Set preamble steps..."); 559 560 try: 561 advertiseData = advData[ : ]; 562 if len(advData) > 251: 563 advertiseData = advertiseData[:251]; 564 565 status = le_set_extended_scan_response_data(transport, idx, Handle, Operation, FragPreference, advertiseData, 100); 566 trace.trace(6, "LE Set Extended Scan Response Data Command returns status: 0x%02X" % status); 567 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 568 except Exception as e: 569 trace.trace(3, "Extended Scan Response Data Set preamble failed: %s" % str(e)); 570 success = False; 571 572 return success; 573 574def preamble_ext_advertise_enable(transport, idx, enable, SHandle, SDuration, SMaxExtAdvEvts, trace): 575 trace.trace(5, "Extended Advertising " + ("Enable" if enable else "Disable") + " preamble steps..."); 576 577 try: 578 NumberOfSets = max(len(SHandle), len(SDuration), len(SMaxExtAdvEvts)); 579 if len(SHandle) < NumberOfSets: 580 SHandle += [ 0 for _ in range(len(SHandle), NumberOfSets) ]; 581 if len(SDuration) < NumberOfSets: 582 SDuration += [ 0 for _ in range(len(SDuration), NumberOfSets) ]; 583 if len(SMaxExtAdvEvts) < NumberOfSets: 584 SMaxExtAdvEvts += [ 0 for _ in range(len(SMaxExtAdvEvts), NumberOfSets) ]; 585 586 status = le_set_extended_advertising_enable(transport, idx, enable, NumberOfSets, SHandle, SDuration, SMaxExtAdvEvts, 100); 587 trace.trace(6, "LE Set Extended Advertising Enable Command returns status: 0x%02X" % status); 588 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 589 except Exception as e: 590 trace.trace(3, "Extended Advertising " + "Enable" if enable else "Disable" + " preamble failed: %s" % str(e)); 591 success = False; 592 593 return success; 594 595def preamble_scan_parameters_set(transport, idx, scanType, scanInterval, scanWindow, addrType, filterPolicy, trace): 596 trace.trace(5, "Scan Parameters Set preamble steps..."); 597 598 try: 599 status = le_set_scan_parameters(transport, idx, scanType, scanInterval, scanWindow, addrType, filterPolicy, 100); 600 trace.trace(6, "LE Set Scan Parameters Command returns status: 0x%02X" % status); 601 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 602 except Exception as e: 603 trace.trace(3, "Scan Parameters Set preamble failed: %s" % str(e)); 604 success = False; 605 606 return success; 607 608def preamble_scan_enable(transport, idx, enable, filterDuplicate, trace): 609 trace.trace(5, "Scanning " + ("Enable" if enable else "Disable") + " preamble steps..."); 610 611 try: 612 status = le_set_scan_enable(transport, idx, enable, filterDuplicate, 100); 613 trace.trace(6, "LE Set Scan Enable Command returns status: 0x%02X" % status); 614 success = (status == 0); 615 while not __getCommandCompleteEvent(transport, idx, trace): 616 pass; 617 except Exception as e: 618 trace.trace(3, "Scanning " + ("Enable" if enable else "Disable") + " preamble failed: %s" % str(e)); 619 success = False; 620 621 return success; 622 623def preamble_passive_scanning(transport, idx, scanInterval, scanWindow, addrType, filterPolicy, trace): 624 trace.trace(5, "Passive Scanning preamble steps..."); 625 626 success = preamble_scan_parameters_set(transport, idx, ScanType.PASSIVE, scanInterval, scanWindow, addrType, filterPolicy, trace); 627 success = success and preamble_scan_enable(transport, idx, Scan.ENABLE, ScanFilterDuplicate.DISABLE, trace); 628 return success; 629 630def preamble_default_physical_channel(transport, idx, AllPhys, TxPhys, RxPhys, trace): 631 trace.trace(5, "Default physical channels preamble steps..."); 632 633 try: 634 status = le_set_default_phy(transport, idx, AllPhys, TxPhys, RxPhys, 100); 635 success = __getCommandCompleteEvent(transport, idx, trace) and (status == 0); 636 except Exception as e: 637 trace.trace(3, "Default physical channels preamble failed: %s" % str(e)); 638 success = False; 639 640 return success; 641 642def public_address( address ): 643 return ExtendedAddressType.PUBLIC, toArray(address, 6); 644 645def random_address( address ): 646 return ExtendedAddressType.RANDOM, toArray(address, 6); 647 648def public_identity_address( address ): 649 return ExtendedAddressType.RESOLVABLE_OR_PUBLIC, toArray(address, 6); 650 651def random_identity_address( address ): 652 return ExtendedAddressType.RESOLVABLE_OR_RANDOM, toArray(address, 6); 653