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