1# -*- coding: utf-8 -*-
2# Copyright 2019 Oticon A/S
3# SPDX-License-Identifier: Apache-2.0
4
5import math
6from numpy import random;
7import copy
8import statistics;
9import os;
10import numpy;
11import csv;
12import tests.test_utils;
13from collections import defaultdict, namedtuple
14from enum import IntEnum;
15from components.utils import *;
16from components.basic_commands import *;
17from components.address import *;
18from components.events import *;
19from components.resolvable import *;
20from components.advertiser import *;
21from components.scanner import *;
22from components.initiator import *;
23from components.addata import *;
24from components.preambles import *;
25from components.test_spec import TestSpec;
26from components.dump import PacketType, channel_num_to_index;
27from tests.test_utils import *
28
29global lowerIRK, upperIRK, ENC_KEYS
30
31class FragmentPreference(IntEnum):
32    FRAGMENT_ALL_DATA = 0          # The Controller may fragment all Host advertising data
33    FRAGMENT_MIN_DATA = 1          # The Controller should not fragment or should minimize fragmentation of Host advertising data
34
35class PreferredPhysicalChannel(IntEnum):
36    LE_1M    = 0                   # 0 ~ The Host prefers to use the LE 1M transmitter PHY (possibly among others)
37    LE_2M    = 1                   # 1 ~ The Host prefers to use the LE 2M transmitter PHY (possibly among others)
38    LE_CODED = 2                   # 2 ~ The Host prefers to use the LE Coded transmitter PHY (possibly among others)
39
40"""
41    LL/DDI/ADV/BV-01-C [Non-Connectable Advertising Packets on one channel]
42
43    Last modified: 30-07-2019
44    Reviewed and verified: 30-07-2019 Henrik Eriksen
45"""
46def ll_ddi_adv_bv_01_c(transport, upperTester, lowerTester, trace):
47
48    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 100, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
49
50    success = advertiser.enable();
51    if success:
52        success = scanner.enable() and success;
53        scanner.monitor();
54        success = scanner.disable() and success;
55        success = success and scanner.qualifyReports( 100, None, advertiser.advertiseData );
56
57        success = advertiser.disable() and success;
58
59    return success;
60
61"""
62    LL/DDI/ADV/BV-02-C [Undirected Advertising Packets on one channel]
63
64    Last modified: 30-07-2019
65    Reviewed and verified: 30-07-2019 Henrik Eriksen
66"""
67def ll_ddi_adv_bv_02_c(transport, upperTester, lowerTester, trace):
68
69    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 100, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
70
71    success = advertiser.enable();
72    if success:
73        success = scanner.enable() and success;
74        scanner.monitor();
75        success = scanner.disable() and success;
76        success = success and scanner.qualifyReports( 100, None, advertiser.advertiseData );
77
78        success = advertiser.disable() and success;
79
80    return success;
81
82"""
83    LL/DDI/ADV/BV-03-C [Non-Connectable Advertising Packets on all channels]
84
85    Last modified: 30-07-2019
86    Reviewed and verified: 30-07-2019 Henrik Eriksen
87"""
88def ll_ddi_adv_bv_03_c(transport, upperTester, lowerTester, trace):
89
90    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 50, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
91    success = True;
92    adData = ADData();
93    adData.encode( ADType.COMPLETE_LOCAL_NAME, 'THIS IS JUST A RANDOM NAME...' );
94
95    for dataLength in [ 1, 0, 31, 0 ]:
96        trace.trace(7, '-'*80);
97
98        advertiser.advertiseData = [ ] if dataLength == 0 else [ 0x01 ] if dataLength == 1 else adData.asBytes();
99
100        advertising = advertiser.enable();
101        success = success and advertising;
102        if advertising:
103            success = scanner.enable() and success;
104            scanner.monitor();
105            success = scanner.disable() and success;
106            success = scanner.qualifyReports( 50, None, list(advertiser.advertiseData) ) and success;
107            success = advertiser.disable() and success;
108
109    return success;
110
111"""
112    LL/DDI/ADV/BV-04-C [Undirected Advertising with Data on all channels ]
113
114    Last modified: 30-07-2019
115    Reviewed and verified: 30-07-2019 Henrik Eriksen
116"""
117def ll_ddi_adv_bv_04_c(transport, upperTester, lowerTester, trace):
118
119    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 50, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
120    success = True;
121    adData = ADData();
122
123    for dataLength in [ 1, 0, 31, 0 ]:
124        trace.trace(7, '-'*80);
125
126        advertiser.advertiseData = [ ] if dataLength == 0 else [ 0x01 ] if dataLength == 1 else \
127                                   adData.encode( ADType.COMPLETE_LOCAL_NAME, 'THIS IS JUST A RANDOM NAME...' );
128
129        advertising = advertiser.enable();
130        success = success and advertising;
131        if advertising:
132            success = scanner.enable() and success;
133            scanner.monitor();
134            success = scanner.disable() and success;
135            success = success and scanner.qualifyReports( 50, None, advertiser.advertiseData );
136
137            success = advertiser.disable() and success;
138
139    return success;
140
141"""
142    LL/DDI/ADV/BV-05-C [Undirected Connectable Advertising with Scan Request/Response ]
143
144    Last modified: 30-07-2019
145    Reviewed and verified: 30-07-2019 Henrik Eriksen
146"""
147def ll_ddi_adv_bv_05_c(transport, upperTester, lowerTester, trace):
148
149    advertiser, scanner = setActiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 30, 1);
150
151    success = True;
152    adData = ADData();
153
154    for address in [ 0x456789ABCDEF, address_scramble_OUI( 0x456789ABCDEF ), address_exchange_OUI_LAP( 0x456789ABCDEF ) ]:
155        for nameLength in [ 2, 31 ]:
156            trace.trace(7, '-'*80);
157
158            advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, '' ) if nameLength < 31 else \
159                                      adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT IUT IUT IUT IUT IUT IUT IUT' );
160
161            advertising = advertiser.enable();
162            success = success and advertising;
163
164            trace.trace(6, "\nUsing scanner address: %s SCAN_RSP data length: %d\n" % (formatAddress( toArray(address, 6), SimpleAddressType.PUBLIC), nameLength) );
165            success = success and preamble_set_public_address( transport, lowerTester, address, trace );
166
167            if advertising:
168                success = scanner.enable() and success;
169                scanner.monitor();
170                success = scanner.disable() and success;
171                success = success and scanner.qualifyReports( 1 );
172                success = success and scanner.qualifyResponses( 1, advertiser.responseData );
173
174                success = advertiser.disable() and success;
175
176    return success;
177
178"""
179    LL/DDI/ADV/BV-06-C [Stop Advertising on Connection Request]
180
181    Last modified: 30-07-2019
182    Reviewed and verified: 30-07-2019 Henrik Eriksen
183"""
184def ll_ddi_adv_bv_06_c(transport, upperTester, lowerTester, trace):
185
186    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 0);
187
188    success = True;
189    adData = ADData();
190    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT' );
191
192    initiatorAddress = Address( ExtendedAddressType.PUBLIC );
193    initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, publicIdentityAddress(upperTester));
194
195    for address in [ 0x456789ABCDEF, address_scramble_OUI( 0x456789ABCDEF ), address_scramble_LAP( 0x456789ABCDEF ), address_exchange_OUI_LAP( 0x456789ABCDEF ) ]:
196        trace.trace(7, '-'*80);
197
198        trace.trace(6, "\nUsing initiator address: %s\n" % formatAddress( toArray(address, 6), SimpleAddressType.PUBLIC));
199        success = success and preamble_set_public_address( transport, lowerTester, address, trace );
200
201        success = advertiser.enable() and success;
202        connected = initiator.connect();
203        success = success and connected;
204
205        if connected:
206            """
207                If a connection was established Advertising should have seized...
208            """
209            scanner.expectedResponses = None;
210            success = scanner.enable() and success;
211            scanner.monitor();
212            success = scanner.disable() and success;
213            success = success and not scanner.qualifyReports( 1 );
214
215            success = initiator.disconnect(0x13) and success;
216        else:
217            success = advertiser.disable() and success;
218
219        if not success:
220            break;
221
222    return success;
223
224"""
225    LL/DDI/ADV/BV-07-C [Scan Request/Response followed by Connection Request]
226
227    Last modified: 30-07-2019
228    Reviewed and verified: 30-07-2019 Henrik Eriksen
229"""
230def ll_ddi_adv_bv_07_c(transport, upperTester, lowerTester, trace):
231
232    advertiser, scanner = setActiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 1, 1);
233
234    success = True;
235    adData = ADData();
236    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT' );
237
238    success = advertiser.enable();
239    success = scanner.enable() and success;
240    scanner.monitor();
241    success = scanner.disable() and success;
242    success = success and scanner.qualifyReports( 1 );
243    success = success and scanner.qualifyResponses( 1, advertiser.responseData );
244
245    initiatorAddress = Address( ExtendedAddressType.PUBLIC );
246    initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, publicIdentityAddress(upperTester));
247    connected = initiator.connect();
248    success = success and connected;
249
250    if connected:
251        """
252            If a connection was established Advertising should have seized...
253        """
254        scanner.expectedResponses = None;
255        success = scanner.enable() and success;
256        scanner.monitor();
257        success = scanner.disable() and success;
258        success = success and not scanner.qualifyReports( 1 );
259
260        success = initiator.disconnect(0x13) and success;
261    else:
262        success = advertiser.disable() and success;
263
264    return success;
265
266"""
267    LL/DDI/ADV/BV-08-C [Advertiser Filtering Scan requests]
268
269    Last modified: 30-07-2019
270    Reviewed and verified: 30-07-2019 Henrik Eriksen
271"""
272def ll_ddi_adv_bv_08_c(transport, upperTester, lowerTester, trace):
273
274    advertiser, scanner = setActiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
275    """
276        Place Public and static Random addresses of lowerTester in the Filter Accept List for the Advertiser
277    """
278    ownAddress = Address( ExtendedAddressType.PUBLIC );
279    peerAddresses = [ Address( IdentityAddressType.PUBLIC, 0x456789ABCDEF ), Address( IdentityAddressType.RANDOM, 0x456789ABCDEF | 0xC00000000000 ) ];
280    success = addAddressesToFilterAcceptList(transport, upperTester, peerAddresses, trace);
281
282    adData = ADData();
283    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT' );
284
285    for filterPolicy in [ AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS, AdvertisingFilterPolicy.FILTER_SCAN_REQUESTS ]:
286        trace.trace(7, "\nTesting Advertising Filter Policy: %s" % filterPolicy.name);
287        advertiser.filterPolicy = filterPolicy;
288
289        for addressType, peerAddress in zip([ ExtendedAddressType.PUBLIC, ExtendedAddressType.RANDOM ], peerAddresses):
290
291            advertiser.peerAddress = peerAddress;
292            success = advertiser.enable() and success;
293
294            for i in range(3):
295                useAddressType = addressType;
296                trace.trace(7, '-'*80);
297                if   i == 0:
298                    """
299                        Correct Address Type - scrambled Address
300                    """
301                    if useAddressType == ExtendedAddressType.PUBLIC:
302                        trace.trace(7, "-- (%s,%d) Using scrambled PUBLIC address..." % (addressType.name,i));
303                        success = success and preamble_set_public_address( transport, lowerTester, address_scramble_LAP( 0x456789ABCDEF ), trace );
304                    else:
305                        trace.trace(7, "-- (%s,%d) Using scrambled RANDOM static address..." % (addressType.name,i));
306                        success = success and preamble_set_random_address( transport, lowerTester, address_scramble_LAP( 0x456789ABCDEF ) | 0xC00000000000, trace );
307                elif i == 1:
308                    """
309                        Incorrect Address Type - correct Address
310                    """
311                    useAddressType = ExtendedAddressType.RANDOM if addressType == ExtendedAddressType.PUBLIC else ExtendedAddressType.PUBLIC;
312                    if useAddressType == ExtendedAddressType.PUBLIC:
313                        trace.trace(7, "-- (%s,%d) Using incorrect PUBLIC address..." % (addressType.name,i));
314                        success = success and preamble_set_public_address( transport, lowerTester, toNumber(peerAddresses[1].address), trace );
315                    else:
316                        trace.trace(7, "-- (%s,%d) Using incorrect RANDOM static address..." % (addressType.name,i));
317                        success = success and preamble_set_random_address( transport, lowerTester, toNumber(peerAddresses[0].address), trace );
318                else:
319                    """
320                        Correct Address Type - correct Address
321                    """
322                    if useAddressType == ExtendedAddressType.PUBLIC:
323                        trace.trace(7, "-- (%s,%d) Using PUBLIC address..." % (addressType.name,i));
324                        success = success and preamble_set_public_address( transport, lowerTester, toNumber(peerAddresses[0].address), trace );
325                    else:
326                        trace.trace(7, "-- (%s,%d) Using RANDOM static address..." % (addressType.name,i));
327                        success = success and preamble_set_random_address( transport, lowerTester, toNumber(peerAddresses[1].address), trace );
328
329                scanner.ownAddress.type = useAddressType;
330                scanner.expectedReports = 30;
331                scanner.expectedResponses = 1 if (i == 2) else None;
332
333                success = scanner.enable() and success;
334                scanner.monitor();
335                success = scanner.disable() and success;
336                success = success and scanner.qualifyReports( scanner.expectedReports );
337                if not scanner.expectedResponses is None:
338                    success = success and scanner.qualifyResponses( 1, advertiser.responseData );
339                else:
340                    success = success and not scanner.qualifyResponses( 1 );
341
342            success = advertiser.disable() and success;
343
344    return success;
345
346"""
347    LL/DDI/ADV/BV-09-C [Advertiser Filtering Connection requests]
348
349    Last modified: 30-07-2019
350    Reviewed and verified: 30-07-2019 Henrik Eriksen
351"""
352def ll_ddi_adv_bv_09_c(transport, upperTester, lowerTester, trace):
353
354    """
355        Place Public address and Random static address of lowerTester in the Filter Accept List for the Advertiser
356    """
357    ownAddress = Address( ExtendedAddressType.PUBLIC );
358    peerAddresses = [ Address( IdentityAddressType.PUBLIC, 0x456789ABCDEF ), Address( IdentityAddressType.RANDOM, 0x456789ABCDEF | 0xC00000000000 ) ];
359    success = addAddressesToFilterAcceptList(transport, upperTester, peerAddresses, trace);
360    """
361        Initialize Advertiser with Connectable Undirected advertising using a Public Address
362    """
363    advertiser = Advertiser(transport, upperTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \
364                            ownAddress, peerAddresses[0], AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
365
366    adData = ADData();
367    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT' );
368
369    for filterPolicy in [ AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS, AdvertisingFilterPolicy.FILTER_CONNECTION_REQUESTS, AdvertisingFilterPolicy.FILTER_SCAN_REQUESTS ]:
370        trace.trace(7, "\nTesting Advertising Filter Policy: %s" % filterPolicy.name);
371        advertiser.filterPolicy = filterPolicy;
372
373        for addressType, peerAddress in zip([ ExtendedAddressType.PUBLIC, ExtendedAddressType.RANDOM ], peerAddresses):
374
375            advertiser.peerAddress = peerAddress;
376
377            for i in range(3):
378                useAddressType = addressType;
379                success = advertiser.enable() and success;
380                trace.trace(7, '-'*80);
381                if   i == 0:
382                    """
383                        Correct Address Type - scrambled Address
384                    """
385                    if useAddressType == ExtendedAddressType.PUBLIC:
386                        trace.trace(7, "-- (%s,%d) Using scrambled PUBLIC address..." % (addressType.name,i));
387                        success = success and preamble_set_public_address( transport, lowerTester, address_scramble_OUI( 0x456789ABCDEF ), trace );
388                    else:
389                        trace.trace(7, "-- (%s,%d) Using scrambled RANDOM static address..." % (addressType.name,i));
390                        success = success and preamble_set_random_address( transport, lowerTester, address_scramble_OUI( 0x456789ABCDEF ) | 0xC00000000000, trace );
391                elif i == 1:
392                    """
393                        Incorrect Address Type - correct Address
394                    """
395                    useAddressType = ExtendedAddressType.RANDOM if addressType == ExtendedAddressType.PUBLIC else ExtendedAddressType.PUBLIC;
396                    if useAddressType == ExtendedAddressType.PUBLIC:
397                        trace.trace(7, "-- (%s,%d) Using incorrect PUBLIC address..." % (addressType.name,i));
398                        success = success and preamble_set_public_address( transport, lowerTester, toNumber(peerAddresses[1].address), trace );
399                    else:
400                        trace.trace(7, "-- (%s,%d) Using incorrect RANDOM static address..." % (addressType.name,i));
401                        success = success and preamble_set_random_address( transport, lowerTester, toNumber(peerAddresses[0].address), trace );
402                else:
403                    """
404                        Correct Address Type - correct Address
405                    """
406                    if useAddressType == ExtendedAddressType.PUBLIC:
407                        trace.trace(7, "-- (%s,%d) Using correct PUBLIC address..." % (addressType.name,i));
408                        success = success and preamble_set_public_address( transport, lowerTester, toNumber(peerAddresses[0].address), trace );
409                    else:
410                        trace.trace(7, "-- (%s,%d) Using correct RANDOM static address..." % (addressType.name,i));
411                        success = success and preamble_set_random_address( transport, lowerTester, toNumber(peerAddresses[1].address), trace );
412
413                initiatorAddress = Address( useAddressType );
414                initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, publicIdentityAddress(upperTester));
415
416                for j in range(30):
417                    connected = initiator.connect();
418                    success = success and (connected if (i == 2 or filterPolicy == AdvertisingFilterPolicy.FILTER_SCAN_REQUESTS) else not connected);
419
420                    if connected:
421                        """
422                            If a connection was established - disconnect...
423                        """
424                        success = initiator.disconnect(0x13) and success;
425                        break;
426
427                if not connected:
428                    success = advertiser.disable() and success;
429
430    return success;
431
432"""
433    LL/DDI/ADV/BV-11-C [High Duty Cycle Connectable Directed Advertising on all channels]
434
435    Last modified: 30-07-2019
436    Reviewed and verified: 30-07-2019 Henrik Eriksen
437"""
438def ll_ddi_adv_bv_11_c(transport, upperTester, lowerTester, trace):
439
440    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED, 30, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
441    """
442        Place Public address of lowerTester in the Filter Accept List
443    """
444    ownAddress = Address( ExtendedAddressType.PUBLIC );
445    peerAddress = publicIdentityAddress(lowerTester);
446    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
447
448    success = scanner.enable() and success;
449    success = advertiser.enable() and success;
450    scanner.monitor(True);
451    success = advertiser.timeout() and success;
452    success = scanner.disable() and success;
453
454    success = success and scanner.qualifyReportTime( 30, 1300 );
455
456    success = advertiser.enable() and success;
457
458    initiator = Initiator(transport, lowerTester, upperTester, trace, ownAddress, publicIdentityAddress(upperTester));
459    connected = initiator.connect();
460    success = success and connected;
461    if connected:
462        success = initiator.disconnect(0x13) and success;
463    else:
464        success = advertiser.disable() and success;
465
466    return success;
467
468"""
469    LL/DDI/ADV/BV-15-C [Discoverable Undirected Advertising on all channels]
470
471    Last modified: 30-07-2019
472    Reviewed and verified: 30-07-2019 Henrik Eriksen
473"""
474def ll_ddi_adv_bv_15_c(transport, upperTester, lowerTester, trace):
475
476    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 100, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
477    """
478        Place Public address of lowerTester in the Filter Accept List
479    """
480    peerAddress = publicIdentityAddress(lowerTester);
481    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
482
483    success = scanner.enable() and success;
484    success = advertiser.enable() and success;
485    scanner.monitor();
486    success = advertiser.disable() and success;
487    success = scanner.disable() and success;
488    success = success and scanner.qualifyReports( 100, None, advertiser.advertiseData );
489
490    return success;
491
492"""
493    LL/DDI/ADV/BV-16-C [Discoverable Undirected Advertising with Data on all channels]
494
495    Last modified: 30-07-2019
496    Reviewed and verified: 30-07-2019 Henrik Eriksen
497"""
498def ll_ddi_adv_bv_16_c(transport, upperTester, lowerTester, trace):
499
500    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 50);
501
502    success = True;
503
504    for i in range(4):
505        advertiser.advertiseData = [ 0x01 ] if i == 0 else [ ] if i == 1 or i == 3 else [ 0x1E if _ == 0 else 0x00 for _ in range(31) ];
506
507        success = scanner.enable() and success;
508        success = advertiser.enable() and success;
509        scanner.monitor();
510        success = advertiser.disable()and success;
511        success = scanner.disable() and success;
512        success = success and scanner.qualifyReports( 50, None, advertiser.advertiseData );
513
514    return success;
515
516"""
517    LL/DDI/ADV/BV-17-C [Discoverable Undirected Advertising with Scan Request/Response]
518
519    Last modified: 30-07-2019
520    Reviewed and verified: 30-07-2019 Henrik Eriksen
521"""
522def ll_ddi_adv_bv_17_c(transport, upperTester, lowerTester, trace):
523
524    advertiser, scanner = setActiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 30, 5);
525
526    success = True;
527    adData = ADData();
528
529    for i in range(3):
530        for j in range(2):
531            advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, '' ) if j == 0 else \
532                                      adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT IUT IUT IUT IUT IUT IUT I' );
533            if   i == 1:
534                success = success and preamble_set_public_address( transport, lowerTester, address_scramble_OUI( 0x456789ABCDEF ), trace );
535            elif i == 2:
536                success = success and preamble_set_public_address( transport, lowerTester, address_exchange_OUI_LAP( 0x456789ABCDEF ), trace );
537
538            success = scanner.enable() and success;
539            success = advertiser.enable() and success;
540            scanner.monitor();
541            success = advertiser.disable() and success;
542            success = scanner.disable() and success;
543            success = success and scanner.qualifyReports( 5 );
544            success = success and scanner.qualifyResponses( 5, advertiser.responseData );
545
546    return success;
547
548"""
549    LL/DDI/ADV/BV-18-C [Discoverable Undirected Advertiser Filtering Scan requests ]
550
551    Last modified: 30-07-2019
552    Reviewed and verified: 30-07-2019 Henrik Eriksen
553"""
554def ll_ddi_adv_bv_18_c(transport, upperTester, lowerTester, trace):
555
556    advertiser, scanner = setActiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 30, None, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
557    """
558        Place Public address of lowerTester in the Filter Accept List
559    """
560    ownAddress = Address( ExtendedAddressType.PUBLIC );
561    peerAddress = publicIdentityAddress(lowerTester);
562    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
563
564    adData = ADData();
565    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT' );
566
567    success = advertiser.enable() and success;
568
569    for i, addressType in enumerate([ ExtendedAddressType.PUBLIC, ExtendedAddressType.RANDOM, ExtendedAddressType.PUBLIC ]):
570        if   i == 0:
571            success = success and preamble_set_public_address( transport, lowerTester, address_scramble_LAP( 0x456789ABCDEF ), trace);
572        elif i == 1:
573            success = success and preamble_set_random_address( transport, lowerTester, 0x456789ABCDEF, trace );
574        else:
575            success = success and preamble_set_public_address( transport, lowerTester, 0x456789ABCDEF, trace );
576            scanner.expectedResponses = 1;
577
578        scanner.ownAddress = Address( addressType );
579
580        success = scanner.enable() and success;
581        scanner.monitor();
582        success = scanner.disable() and success;
583        success = success and scanner.qualifyReports( 1 if i > 1 else 30 );
584        success = success and scanner.qualifyResponses( 1 if i > 1 else 0, advertiser.responseData if i > 1 else None );
585
586    success = advertiser.disable() and success;
587
588    return success;
589
590"""
591    LL/DDI/ADV/BV-19-C [Low Duty Cycle Directed Advertising on all channels]
592
593    Last modified: 30-07-2019
594    Reviewed and verified: 30-07-2019 Henrik Eriksen (NOTE: The automatic disconnect due to supervision timeout cannot be achieved)
595"""
596def ll_ddi_adv_bv_19_c(transport, upperTester, lowerTester, trace):
597
598    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED, 100, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
599    """
600        Place Public address of lowerTester in the Filter Accept List
601    """
602    ownAddress = Address( ExtendedAddressType.PUBLIC );
603    peerAddress = publicIdentityAddress(lowerTester);
604    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
605
606    success = advertiser.enable() and success;
607
608    success = scanner.enable() and success;
609    scanner.monitor();
610    success = scanner.disable() and success;
611    success = success and scanner.qualifyReports( 100 );
612
613    initiator = Initiator(transport, lowerTester, upperTester, trace, ownAddress, publicIdentityAddress(upperTester));
614    connected = initiator.connect();
615    success = success and connected;
616
617    if connected:
618        success = initiator.disconnect(0x13) and success;
619    else:
620        success = advertiser.disable() and success;
621
622    return success;
623
624"""
625    LL/DDI/ADV/BV-20-C [Advertising on the LE 1M PHY on all channels]
626
627    Last modified: 30-07-2019
628    Reviewed and verified: 30-07-2019 Henrik Eriksen (NOTE: The PHY channel used in advertising can only be verified by looking at the Air trace)
629"""
630def ll_ddi_adv_bv_20_c(transport, upperTester, lowerTester, trace):
631
632    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 100, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
633    """
634        Place Public address of lowerTester in the Filter Accept List
635    """
636    peerAddress = publicIdentityAddress(lowerTester);
637    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
638
639    AllPhys, TxPhys, RxPhys = 0, PreferredPhysicalChannel.LE_2M, PreferredPhysicalChannel.LE_2M;
640
641    success = success and preamble_default_physical_channel(transport, upperTester, AllPhys, TxPhys, RxPhys, trace);
642
643    success = scanner.enable() and success;
644    success = advertiser.enable() and success;
645    scanner.monitor();
646    success = advertiser.disable() and success;
647    success = scanner.disable() and success;
648    success = success and scanner.qualifyReports( 100 );
649
650    return success;
651
652"""
653    LL/DDI/ADV/BV-21-C [Non-Connectable Extended Legacy Advertising with Data on all channels]
654"""
655def ll_ddi_adv_bv_21_c(transport, upperTester, lowerTester, trace):
656
657    Handle          = 0;
658    Properties      = ExtAdvertiseType.LEGACY;
659    PrimMinInterval = toArray(0x0020, 3); # Minimum Advertise Interval = 32 x 0.625 ms = 20.00 ms
660    PrimMaxInterval = toArray(0x0022, 3); # Maximum Advertise Interval = 34 x 0.625 ms = 21.25 ms
661    PrimChannelMap  = 0x07;  # Advertise on all three channels (#37, #38 and #39)
662    OwnAddrType     = SimpleAddressType.PUBLIC;
663    PeerAddrType, PeerAddress = random_address( 0x456789ABCDEF );
664    FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE;
665    TxPower         = 0;
666    PrimAdvPhy      = PhysicalChannel.LE_1M; # Primary advertisement PHY is LE 1M
667    SecAdvMaxSkip   = 0;     # AUX_ADV_IND shall be sent prior to the next advertising event
668    SecAdvPhy       = PhysicalChannel.LE_2M;
669    Sid             = 0;
670    ScanReqNotifyEnable = 0; # Scan request notifications disabled
671
672    success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval, \
673                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower, \
674                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace);
675
676    for i in range(3):
677        if i == 0:
678            AdvData = [ 0x01 ];
679        elif i == 1:
680            AdvData = [ ];
681        else:
682            AdvData = [ 0x1F ] + [ 0 for _ in range(30) ];
683
684        Operation      = FragmentOperation.COMPLETE_FRAGMENT;
685        FragPreference = FragmentPreference.FRAGMENT_ALL_DATA;
686
687        success = success and preamble_ext_advertising_data_set(transport, upperTester, Handle, Operation, FragPreference, AdvData, trace);
688
689        scanInterval = 32; # Scan Interval = 32 x 0.625 ms = 20.0 ms
690        scanWindow   = 32; # Scan Window   = 32 x 0.625 ms = 20.0 ms
691        addrType     = SimpleAddressType.RANDOM;
692        filterPolicy = ScanningFilterPolicy.FILTER_NONE;
693
694        success = success and preamble_passive_scanning(transport, lowerTester, scanInterval, scanWindow, addrType, filterPolicy, trace);
695
696        SHandle        = [ Handle ];
697        SDuration      = [ 0 ];
698        SMaxExtAdvEvts = [ 0 ];
699
700        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, SHandle, SDuration, SMaxExtAdvEvts, trace);
701
702        deltas = [];
703        reports = 0;
704        while reports < 50:
705            if has_event(transport, lowerTester, 100)[0]:
706                event = get_event(transport, lowerTester, 100);
707                # showEvent(event, eventData, trace);
708                isReport = event.subEvent == MetaEvents.BT_HCI_EVT_LE_ADVERTISING_REPORT;
709                if isReport:
710                    eventType, data = event.decode()[0:3:2];
711                    if eventType == AdvertisingReport.ADV_NONCONN_IND:
712                        reports += 1;
713                        reportData = data;
714                        if reports > 1:
715                            deltas += [event.time - prevTime];
716                        prevTime = event.time;
717
718        success = success and preamble_scan_enable(transport, lowerTester, Scan.DISABLE, ScanFilterDuplicate.DISABLE, trace);
719        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.DISABLE, SHandle, SDuration, SMaxExtAdvEvts, trace);
720        success = success and (reportData == AdvData);
721
722        trace.trace(7, "Mean distance between Advertise Events %d ms std. deviation %.1f ms" % (statistics.mean(deltas), statistics.pstdev(deltas)));
723
724    return success;
725
726"""
727    LL/DDI/ADV/BV-22-C [Extended Advertising, Legacy PDUs, Undirected, CSA #2]
728"""
729def ll_ddi_adv_bv_22_c(transport, upperTester, lowerTester, trace, packets):
730
731    RoundData = namedtuple('RoundData', ['AdvData', 'ChIdxToScan'])
732    rounds = [
733        RoundData([0x01], 37),
734        RoundData([], 38),
735        RoundData([0xF8] + [0x00]*30, 39),
736    ]
737
738    advInterval = 0x20 # 32 x 0.625 ms = 20.00 ms
739    Handle          = 0
740    Properties      = 0b00010011 # ADV_IND legacy PDU
741    PrimMinInterval = toArray(advInterval, 3)
742    PrimMaxInterval = toArray(advInterval, 3)
743    PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
744    OwnAddrType     = SimpleAddressType.PUBLIC
745    PeerAddrType    = SimpleAddressType.PUBLIC
746    PeerAddress     = toArray(0x456789ABCDEF, 6)
747    FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
748    TxPower         = 0
749    PrimAdvPhy      = PhysicalChannel.LE_1M
750    SecAdvMaxSkip   = 0
751    SecAdvPhy       = 0
752    Sid             = 0
753    ScanReqNotifyEnable = 0
754
755    success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
756                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
757                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
758    if not success:
759        return success
760
761    for round in rounds:
762
763        success = success and le_set_extended_advertising_data(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, 0x00, round.AdvData, 100) == 0
764        if not success:
765            return False
766
767        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0x00], [0x00], trace)
768        if not success:
769            return success
770
771        # Wait until at least 50 advertising events should have been sent
772        transport.wait(math.ceil((advInterval*0.625 + 10) * 50))
773
774        # "Scan" on a single primary advertising channel as indicated in RoundData and expect
775        # the IUT to send ADV_IND packets, with ChSel set as specified, including the data submitted
776        packetCount = 0
777        chNumToScan = 0 if round.ChIdxToScan == 37 else 12 if round.ChIdxToScan == 38 else 39
778        for packet in packets.fetch(packet_filter=('ADV_IND')):
779            if packet.channel_num == chNumToScan:
780                packetCount += 1
781                success = success and packet.header.ChSel == 1
782                success = success and len(packet.payload.AdvData) == len(round.AdvData)
783                for i in range(len(round.AdvData)):
784                    success = success and packet.payload.AdvData[i] == round.AdvData[i]
785
786        # Check that the packets have been sent
787        success = success and packetCount >= 50
788
789        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.DISABLE, [Handle], [0x00], [0x00], trace)
790        if not success:
791            return success
792
793        # Flush events and packets for next round
794        flush_events(transport, upperTester, 100)
795        packets.flush()
796
797    return success
798
799
800"""
801    LL/DDI/ADV/BV-27-C [Extended Advertising, Host Modifying Data and ADI]
802"""
803def ll_ddi_adv_bv_27_c(transport, upperTester, lowerTester, trace, packets):
804    status, MaxAdvDataLen = le_read_maximum_advertising_data_length(transport, upperTester, 200)
805
806    if status != 0 or MaxAdvDataLen < 0x001F or MaxAdvDataLen > 0x0672:
807        return False
808
809    # Input data for each round
810    RoundData = namedtuple('RoundData', ['DataLength'])
811    rounds = [
812        RoundData(MaxAdvDataLen),
813        RoundData(1),
814        RoundData(251),
815    ]
816
817    advInterval = 0xA0 # 160 x 0.625 ms = 100.00 ms
818    Handle          = 0
819    Properties      = 0x0000
820    PrimMinInterval = toArray(advInterval, 3)
821    PrimMaxInterval = toArray(advInterval, 3)
822    PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
823    OwnAddrType     = SimpleAddressType.PUBLIC
824    PeerAddrType    = SimpleAddressType.PUBLIC
825    PeerAddress     = toArray(0x456789ABCDEF, 6)
826    FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
827    TxPower         = 0
828    PrimAdvPhy      = PhysicalChannel.LE_1M
829    SecAdvMaxSkip   = 0
830    SecAdvPhy       = PhysicalChannel.LE_1M
831    Sid             = 0
832    ScanReqNotifyEnable = 0
833
834    success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
835                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
836                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
837    if not success:
838        return success
839
840    advertisingStarted = False
841    prevRoundAdvData = None
842    prevDID = None
843    prevAdvData = None
844
845    for roundNumber in range(len(rounds)):
846        round = rounds[roundNumber]
847        if round.DataLength > MaxAdvDataLen:
848            # Skip unsupported advertising data length
849            continue
850
851        # Set adv data
852        advData = random.randint(1, 255, round.DataLength)
853        if not set_complete_ext_adv_data(transport, upperTester, Handle, 0x00, advData):
854            return False
855
856        flush_events(transport, upperTester, 100)
857        if not advertisingStarted:
858            success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0x00], [0x00], trace)
859            if not success:
860                return success
861            advertisingStarted = True
862
863        # Wait until 10 events have been received
864        transport.wait(math.ceil(10.5*advInterval*0.625))
865
866        # Check ADV_EXT_INDs
867        # AdvMode set to 00b; AuxPtr Extended Header field present. The ADI field shall be present and contain the
868        # Advertising Set ID (SID) used by the Upper Tester in step 3 and an Advertising Data ID.
869        for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
870            success = success and packet.payload['AdvMode'] == 0b00
871            success = success and 'AuxPtr' in packet.payload
872            success = success and 'ADI' in packet.payload
873            success = success and packet.payload['ADI'].SID == Sid
874
875        def isAdvDataSame(advDataA, advDataB):
876            if len(advDataA) != len(advDataB):
877                return False
878            for i in range(len(advDataA)):
879                if advDataA[i] != advDataB[i]:
880                    return False
881            return True
882
883        completeAdvDataFound = 0
884
885        # Check AUX_ADV_INDs
886        # Uses the LE 1M PHY with the AdvMode field set to 00b and an ADI field matching the ADI field of the ADV_EXT_IND
887        # If the AUX_ADV_IND PDU does not contain all the advertising data submitted, it shall include an AuxPtr field
888        # The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
889        for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
890            success = success and packet.phy == '1M'
891            success = success and packet.payload['AdvMode'] == 0b00
892            success = success and 'ADI' in packet.payload
893            success = success and packet.payload['ADI'].SID == Sid
894            for superiorPacket in packet.payload['SuperiorPackets']:
895                success = success and packet.payload['ADI'].DID == superiorPacket.payload['ADI'].DID
896                # Packet air length is: pre-amble + AA + header + payload + CRC
897                packetLength = 1 + 4 + 2 + len(superiorPacket) + 3
898                packetAirtime = 8*packetLength
899                success = success and packet.ts >= superiorPacket.ts + packetAirtime + 300
900            if round.DataLength > len(packet.payload['AD']):
901                success = success and 'AuxPtr' in packet.payload
902            else:
903                # Check advertising data against input (shall match either advData or prevRoundAdvData)
904                success = success and (isAdvDataSame(advData, packet.payload['AD']) or isAdvDataSame(prevRoundAdvData, packet.payload['AD']))
905                if isAdvDataSame(advData, packet.payload['AD']):
906                    completeAdvDataFound += 1
907                if prevAdvData != None:
908                    # If advertising data is not the same as previous event but the DID field has not changed, a Fail Verdict is recorded
909                    if not isAdvDataSame(prevAdvData, packet.payload['AD']):
910                        success = success and prevDID != packet.payload['ADI'].DID
911                prevAdvData = packet.payload['AD']
912                prevDID = packet.payload['ADI'].DID
913
914        def collectChainedAdvData(packet):
915            advData = bytes([])
916            if packet.payload['SuperiorPackets'][0].type.name != 'ADV_EXT_IND':
917                advData = collectChainedAdvData(packet.payload['SuperiorPackets'][0])
918            advData += packet.payload['AD']
919            return advData
920
921        # Check AUX_CHAIN_INDs
922        # AdvMode set to 00b; contains additional advertising data submitted
923        # The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
924        for packet in packets.fetch(packet_filter=('AUX_CHAIN_IND')):
925            success = success and packet.payload['AdvMode'] == 0b00
926            for superiorPacket in packet.payload['SuperiorPackets']:
927                # Packet air length is: pre-amble + AA + header + payload + CRC
928                packetLength = 1 + 4 + 2 + len(superiorPacket) + 3
929                packetAirtime = 8*packetLength
930                success = success and packet.ts >= superiorPacket.ts + packetAirtime + 300
931            if 'AuxPtr' not in packet.payload:
932                # Collect complete advertising data and check advertising data against input (shall match either advData or prevRoundAdvData)
933                collectedAdvData = collectChainedAdvData(packet)
934                success = success and (isAdvDataSame(advData, collectedAdvData) or isAdvDataSame(prevRoundAdvData, collectedAdvData))
935                if isAdvDataSame(advData, collectedAdvData):
936                    completeAdvDataFound += 1
937                if prevAdvData != None:
938                    # If advertising data is not the same as previous event but the DID field has not changed, a Fail Verdict is recorded
939                    if not isAdvDataSame(prevAdvData, collectedAdvData):
940                        success = success and prevDID != packet.payload['ADI'].DID
941                prevAdvData = collectedAdvData
942                prevDID = packet.payload['ADI'].DID
943
944        # Check that we actually got the complete data (ie. that some AUX_CHAIN_INDs/AUX_ADV_INDs do not have an aux ptr)
945        success = success and completeAdvDataFound > 0
946
947        prevRoundAdvData = advData
948
949        # Flush events and packets for next round
950        flush_events(transport, upperTester, 100)
951        packets.flush()
952
953    # Stop advertising
954    success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.DISABLE, [Handle], [0x00], [0x00], trace)
955
956    return success
957
958"""
959    LL/DDI/ADV/BV-28-C [Extended Advertising, Overlapping Extended Advertising Events]
960"""
961def ll_ddi_adv_bv_28_c(transport, upperTester, lowerTester, trace, packets):
962    RoundData = namedtuple('RoundData', ['EventProperties', 'SecondaryAdvertisingMaxSkip', 'RepeatCount'])
963    rounds = [
964        RoundData(0x0000, 0x01, 100),
965        RoundData(0x0000, 0x0F, 50),
966        RoundData(0x0000, 0xFF, 10),
967        RoundData(0x0001, 0x08, 50),
968        RoundData(0x0004, 0x08, 50),
969        RoundData(0x0005, 0x08, 50),
970    ]
971
972    success = True
973
974    for round in rounds:
975
976        advInterval = 0x20 # 32 x 0.625 ms = 20.00 ms
977        Handle          = 0
978        Properties      = round.EventProperties
979        PrimMinInterval = toArray(advInterval, 3)
980        PrimMaxInterval = toArray(advInterval, 3)
981        PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
982        OwnAddrType     = SimpleAddressType.PUBLIC
983        PeerAddrType    = SimpleAddressType.PUBLIC
984        PeerAddress     = toArray(0x456789ABCDEF, 6)
985        FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
986        TxPower         = 0
987        PrimAdvPhy      = PhysicalChannel.LE_1M
988        SecAdvMaxSkip   = round.SecondaryAdvertisingMaxSkip
989        SecAdvPhy       = PhysicalChannel.LE_1M
990        Sid             = 0
991        ScanReqNotifyEnable = 0
992
993        success = success and preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
994                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
995                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
996        if not success:
997            return success
998
999        advData = random.randint(1, 255, 1)
1000        status = le_set_extended_advertising_data(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, 0x00, advData, 100)
1001        if status != 0:
1002            return False
1003
1004        flush_events(transport, upperTester, 100)
1005        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0x00], [0x00], trace)
1006        if not success:
1007            return success
1008
1009        # Wait until we have RepeatCount AUX_ADV_INDs
1010        auxAdvIndCount = 0
1011        while auxAdvIndCount < round.RepeatCount:
1012            waitForMs = math.ceil(advInterval * 0.625 * (round.RepeatCount - auxAdvIndCount))
1013            transport.wait(waitForMs)
1014            auxAdvIndCount = 0
1015            for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
1016                auxAdvIndCount += 1
1017
1018        def getAuxPtrTime(packet):
1019            units = 30 if packet.payload['AuxPtr'].offsetUnits == 0 else 300
1020            return packet.ts + packet.payload['AuxPtr'].auxOffset * units
1021
1022        # Check ADV_EXT_INDs:
1023        # - AuxPtr Extended Header field present and the AdvMode set according to expected properties
1024        # - The AuxPtrs in each ADV_EXT_IND PDU sent in overlapping extended advertising events have
1025        #   Aux Offset and Offset Units values that refer to the same time within one Offset Unit
1026        # Last part requires grouping ADV_EXT_INDs that refer to the same AUX_ADV_IND together
1027        groups = []
1028        currentGroup = []
1029        for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
1030            success = success and packet.payload['AdvMode'] == round.EventProperties & 0x03
1031            success = success and 'AuxPtr' in packet.payload
1032            # Put into current group if channel idx and offset matches (offset is matched if within 1 ms)
1033            if len(currentGroup) == 0 or (currentGroup[0].payload['AuxPtr'].chIdx == packet.payload['AuxPtr'].chIdx and
1034               abs(getAuxPtrTime(packet) - getAuxPtrTime(currentGroup[0])) < 1000):
1035                currentGroup += [packet]
1036            else:
1037                groups += [currentGroup]
1038                currentGroup = [packet]
1039        if len(currentGroup) > 0:
1040            groups += [currentGroup]
1041
1042        for group in groups:
1043            auxPtrMax = None
1044            auxPtrMin = None
1045            offsetUnit = 30
1046            for packet in group:
1047                auxPtrTime = getAuxPtrTime(packet)
1048                if auxPtrMax == None or auxPtrTime > auxPtrMax:
1049                    auxPtrMax = auxPtrTime
1050                if auxPtrMin == None or auxPtrTime < auxPtrMin:
1051                    auxPtrMin = auxPtrTime
1052                if packet.payload['AuxPtr'].offsetUnits == 1:
1053                    offsetUnit = 300
1054            success = success and (auxPtrMin - auxPtrMax) <= offsetUnit
1055
1056        # Check AUX_ADV_INDs
1057        # Uses the LE 1M PHY with the AdvMode field set according to expected properties
1058        # The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
1059        # Check that no more than Secondary_Advertising_Max_Skip+1 extended advertising events overlap
1060        for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
1061            success = success and packet.payload['AdvMode'] == round.EventProperties & 0x03
1062            success = success and packet.phy == '1M'
1063
1064            lastSuperiorPacket = None
1065            currentEventPacketCount = 0
1066            eventCount = 0
1067            for superiorPacket in packet.payload['SuperiorPackets']:
1068                # Packet air length is: pre-amble + AA + header + payload + CRC
1069                packetLength = 1 + 4 + 2 + len(superiorPacket) + 3
1070                packetAirtime = 8*packetLength
1071                success = success and packet.ts >= superiorPacket.ts + packetAirtime + 300
1072
1073                if lastSuperiorPacket == None:
1074                    eventCount = 1
1075                    currentEventPacketCount = 1
1076                else:
1077                    # Assume new advertising event starting if a) there already is 3 ADV_EXT_INDs for the current event or b) there is a gap of more than 5 ms
1078                    if currentEventPacketCount == 3 or lastSuperiorPacket.ts > superiorPacket.ts + 5000:
1079                        currentEventPacketCount = 1
1080                        eventCount += 1
1081                    else:
1082                        currentEventPacketCount += 1
1083                lastSuperiorPacket = superiorPacket
1084
1085            success = success and eventCount <= round.SecondaryAdvertisingMaxSkip + 1
1086
1087        # Disable advertising
1088        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.DISABLE, [Handle], [0x00], [0x00], trace)
1089        if not success:
1090            return success
1091
1092        # Flush events and packets for next round
1093        flush_events(transport, upperTester, 100)
1094        packets.flush()
1095
1096    return success
1097
1098# Implemements LL/DDI/ADV/BV-45-C and LL/DDI/ADV/BV-52-C (only difference is the PHY)
1099def do_ll_ddi_adv_bv_45_52_c(transport, upperTester, lowerTester, trace, packets, phy):
1100
1101    status, MaxAdvDataLen = le_read_maximum_advertising_data_length(transport, upperTester, 200)
1102
1103    if status != 0:
1104        return False
1105
1106    if MaxAdvDataLen < 0x001F or MaxAdvDataLen > 0x0672:
1107        return False
1108
1109    AdvA_IUT = 0x123456789ABC
1110    AdvA_NonIUT = 0xCBA987654321
1111
1112    # Input data for each round
1113    RoundData = namedtuple('RoundData', ['EventProperties', 'ScanRequestNotification', 'AdvDataLen', 'FragmentPref', 'AdvA'])
1114    rounds = [
1115        RoundData(0x0002, 0x00, 1, 0x00, AdvA_IUT),
1116        RoundData(0x0002, 0x00, 31, 0x00, AdvA_IUT),
1117        RoundData(0x0002, 0x00, 474, 0x00, AdvA_IUT),
1118        RoundData(0x0002, 0x00, 711, 0x00, AdvA_IUT),
1119        RoundData(0x0002, 0x00, 948, 0x00, AdvA_IUT),
1120        RoundData(0x0002, 0x00, MaxAdvDataLen, 0x00, AdvA_IUT),
1121        RoundData(0x0002, 0x01, MaxAdvDataLen, 0x01, AdvA_IUT),
1122        RoundData(0x0002, 0x00, 31, 0x00, AdvA_NonIUT),
1123        RoundData(0x0006, 0x00, 1, 0x00, AdvA_IUT),
1124        RoundData(0x0006, 0x00, 251, 0x00, AdvA_IUT),
1125        RoundData(0x0006, 0x00, MaxAdvDataLen, 0x00, AdvA_IUT),
1126        RoundData(0x0006, 0x00, 31, 0x00, AdvA_NonIUT),
1127    ]
1128
1129    success = True
1130
1131    for round in rounds:
1132
1133        if round.AdvDataLen > MaxAdvDataLen:
1134            # Skip unsupported advertising data length
1135            continue
1136
1137        advInterval = 0xA0 # 160 x 0.625 ms = 100.00 ms
1138        Handle          = 0
1139        Properties      = round.EventProperties
1140        PrimMinInterval = toArray(advInterval, 3)
1141        PrimMaxInterval = toArray(advInterval, 3)
1142        PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
1143        OwnAddrType     = SimpleAddressType.PUBLIC
1144        PeerAddrType    = SimpleAddressType.PUBLIC
1145        PeerAddress     = toArray(0x456789ABCDEF, 6)
1146        FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
1147        TxPower         = 0
1148        PrimAdvPhy      = PhysicalChannel.LE_1M
1149        SecAdvMaxSkip   = 0
1150        SecAdvPhy       = phy
1151        Sid             = 0
1152        ScanReqNotifyEnable = round.ScanRequestNotification
1153
1154        success = success and preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
1155                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
1156                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
1157        if not success:
1158            return success
1159
1160        # Set scan response data
1161        advData = random.randint(1, 255, round.AdvDataLen)
1162        if not set_complete_ext_scan_response_data(transport, upperTester, Handle, round.FragmentPref, advData):
1163            return False
1164
1165        flush_events(transport, upperTester, 100)
1166        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0], [0], trace)
1167
1168        if not success:
1169            return success
1170
1171        auxAdvIndPacket = wait_for_AUX_ADV_IND_end(transport, packets)
1172
1173        # Transmit an AUX_SCAN_REQ
1174        packetData = (0b0011 + (12 << 8)).to_bytes(2, 'little', signed=False) # header - PDU Type 0b0011, ChSel, TxAdd and RxAdd all 0, length 12
1175        packetData = b''.join([packetData, 0x456789ABCDEF.to_bytes(6, 'little', signed=False)]) # ScanA
1176        packetData = b''.join([packetData, round.AdvA.to_bytes(6, 'little', signed=False)]) # AdvA
1177        CRC = calcBLECRC(0x555555, packetData)
1178        packetData = b''.join([packetData, CRC.to_bytes(3, 'little', signed=False)])
1179
1180        # Calculate transmit timestamp (T_IFS from end of AUX_ADV_IND)
1181        reqTransmitTime = auxAdvIndPacket.ts + get_packet_air_time(auxAdvIndPacket) + 150
1182        # Note: Packet air length is: pre-amble + AA + packetData (which includes header and CRC)
1183        reqAirTime = math.ceil(((2 if auxAdvIndPacket.phy == '2M' else 1) + 4 + len(packetData))*8/(2 if auxAdvIndPacket.phy == '2M' else 1))
1184
1185        transport.low_level_device.tx(channel_num_to_index(auxAdvIndPacket.channel_num), auxAdvIndPacket.phy, auxAdvIndPacket.aa, reqTransmitTime, packetData)
1186
1187        def check_ADV_EXT_INDs():
1188            # Check ADV_EXT_INDs
1189            # AdvMode set to 10b with the AuxPtr Extended Header field present. The ADV_EXT_IND PDU shall include the ADI field
1190            # with the SID set to the value used in step 3. The ADV_EXT_IND PDU shall not include the CTEInfo, SyncInfo, ACAD, or TxPower fields
1191            success = True
1192            for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
1193                success = success and packet.payload['AdvMode'] == 0b10
1194                success = success and 'AuxPtr' in packet.payload
1195                success = success and 'ADI' in packet.payload
1196                success = success and packet.payload['ADI'].SID == Sid
1197                success = success and 'CTEInfo' not in packet.payload
1198                success = success and 'SyncInfo' not in packet.payload
1199                success = success and 'ACAD' not in packet.payload
1200                success = success and 'TxPower' not in packet.payload
1201            return success
1202
1203        def check_AUX_ADV_INDs():
1204            # Check AUX_ADV_IND(s)
1205            # AdvMode field set to 10b. The AUX_ADV_IND PDU shall include the ADI field matching the ADI field from earlier. The AUX_ADV_IND PDU shall not include the
1206            # CTEInfo, AuxPtr, SyncInfo, TxPower, or AdvData fields
1207            # The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
1208            success = True
1209            for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
1210                success = success and packet.payload['AdvMode'] == 0b10
1211                success = success and 'ADI' in packet.payload
1212                success = success and packet.payload['ADI'].SID == Sid
1213                success = success and 'CTEInfo' not in packet.payload
1214                success = success and 'AuxPtr' not in packet.payload
1215                success = success and 'SyncInfo' not in packet.payload
1216                success = success and 'TxPower' not in packet.payload
1217                success = success and 'AD' not in packet.payload
1218                for superiorPacket in packet.payload['SuperiorPackets']:
1219                    success = success and packet.payload['ADI'].DID == superiorPacket.payload['ADI'].DID
1220                    success = success and packet.ts >= superiorPacket.ts + get_packet_air_time(superiorPacket) + 300
1221            return success
1222
1223        if round.AdvA != AdvA_IUT:
1224            # Wait for 10 ms and check that there was no reply
1225            transport.wait(10)
1226            success = success and check_ADV_EXT_INDs()
1227            success = success and check_AUX_ADV_INDs()
1228
1229            # No AUX_SCAN_RSP packet should have been sent from the IUT
1230            success = success and not packets.findLast(packet_filter='AUX_SCAN_RSP')
1231
1232        else:
1233            # Wait for complete reply
1234            transport.wait(10)
1235            prevPacket = None
1236            lastPacket = packets.findLast(packet_filter='AUX_SCAN_RSP')
1237            if not lastPacket:
1238                success = False
1239            elif 'AuxPtr' in lastPacket.payload:
1240                # Wait for all chained PDUs
1241                while ('AuxPtr' in lastPacket.payload and prevPacket != lastPacket):
1242                    prevPacket = lastPacket
1243                    # Wait for aux ptr offset + 10 ms (to be on the safe side) and check for the chained PDU
1244                    offsetEnd = (lastPacket.payload['AuxPtr'].auxOffset + 1) * (30 if lastPacket.payload['AuxPtr'].offsetUnits == 0 else 300)
1245                    transport.wait(math.ceil(offsetEnd/1000) + 10)
1246                    lastPacket = packets.findLast(packet_filter='AUX_CHAIN_IND')
1247
1248            success = success and check_ADV_EXT_INDs()
1249            success = success and check_AUX_ADV_INDs()
1250
1251            completeAdvDataFound = False
1252
1253            # Check AUX_SCAN_RSP
1254            # T_IFS after the end of the AUX_SCAN_REQ PDU with AdvMode set to 00b, AdvA set to the IUT’s advertising address,
1255            # TargetA and CTEInfo not present, and ADI field either not present or matches the AUX_ADV_IND. If the AUX_SCAN_RSP PDU does not contain all
1256            # the data submitted, it shall include an AuxPtr field
1257            packet = packets.findLast(packet_filter='AUX_SCAN_RSP')
1258            # Check transmission time (note: 2 microseconds jitter is accepted)
1259            success = success and packet.ts >= reqTransmitTime + reqAirTime + 150 - 2
1260            success = success and packet.ts <= reqTransmitTime + reqAirTime + 150 + 2
1261            success = success and packet.payload['AdvMode'] == 0b00
1262            success = success and packet.payload['AdvA'] == AdvA_IUT
1263            success = success and 'TargetA' not in packet.payload
1264            success = success and 'CTEInfo' not in packet.payload
1265            if 'ADI' in packet.payload:
1266                success = success and packet.payload['ADI'].SID == auxAdvIndPacket.payload['ADI'].SID
1267                success = success and packet.payload['ADI'].DID == auxAdvIndPacket.payload['ADI'].DID
1268            if len(packet.payload['AD']) < round.AdvDataLen:
1269                success = success and 'AuxPtr' in packet.payload
1270            else:
1271                completeAdvDataFound = True
1272                # check advertising data against input
1273                for i in range(round.AdvDataLen):
1274                    success = success and packet.payload['AD'][i] == advData[i]
1275
1276            def collectChainedAdvData(packet):
1277                advData = bytes([])
1278                if packet.type.name != 'AUX_SCAN_RSP':
1279                    advData = collectChainedAdvData(packet.payload['SuperiorPackets'][0])
1280                advData += packet.payload['AD']
1281                return advData
1282
1283            # Check AUX_CHAIN_INDs
1284            # Shall include the AdvData field containing additional data submitted. The AUX_CHAIN_IND
1285            # PDU shall not include the AdvA, TargetA, CTEInfo, TxPower, or SyncInfo fields
1286            # The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
1287            for packet in packets.fetch(packet_filter=('AUX_CHAIN_IND')):
1288                success = success and 'AdvA' not in packet.payload
1289                success = success and 'TargetA' not in packet.payload
1290                success = success and 'CTEInfo' not in packet.payload
1291                success = success and 'TxPower' not in packet.payload
1292                success = success and 'SyncInfo' not in packet.payload
1293                for superiorPacket in packet.payload['SuperiorPackets']:
1294                    success = success and packet.ts >= superiorPacket.ts + get_packet_air_time(superiorPacket) + 300
1295                if 'AuxPtr' not in packet.payload:
1296                    # Collect complete advertising data and check advertising data against input
1297                    completeAdvDataFound = True
1298                    collectedAdvData = collectChainedAdvData(packet)
1299                    success = success and len(collectedAdvData) == round.AdvDataLen
1300                    for i in range(round.AdvDataLen):
1301                        success = success and collectedAdvData[i] == advData[i]
1302
1303            # Check that the full advertising data was sent
1304            success = success and completeAdvDataFound
1305
1306            # If scan request notifications are enabled,  Upper Tester receives an HCI_LE_Scan_Request_Received event
1307            # from the IUT with the advertising handle used and the Lower Tester’s address
1308            if round.ScanRequestNotification == 0x01:
1309                if has_event(transport, upperTester, 200)[0]:
1310                    event = get_event(transport, upperTester, 100)
1311                    eventHandle, eventAddress = event.decode()
1312                    success = success and eventHandle == Handle
1313                    success = success and eventAddress == Address(ExtendedAddressType.PUBLIC, 0x456789ABCDEF)
1314                else:
1315                    success = False
1316
1317        flush_events(transport, upperTester, 100)
1318        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.DISABLE, [Handle], [0], [0], trace)
1319        if not success:
1320            return success
1321
1322        # Flush events and packets for next round
1323        flush_events(transport, upperTester, 100)
1324        packets.flush()
1325
1326    return success
1327
1328"""
1329    LL/DDI/ADV/BV-45-C [Extended Advertising, Scannable - ADI allowed in scan response]
1330"""
1331def ll_ddi_adv_bv_45_c(transport, upperTester, lowerTester, trace, packets):
1332    return do_ll_ddi_adv_bv_45_52_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_1M)
1333
1334# Implements LL/DDI/ADV/BV-47-C and LL/DDI/ADV/BV-49-C (only difference is the PHY)
1335def do_ll_ddi_adv_bv_47_49_c(transport, upperTester, lowerTester, trace, packets, phy):
1336
1337    status, MaxAdvDataLen = le_read_maximum_advertising_data_length(transport, upperTester, 200)
1338
1339    if status != 0:
1340        return False
1341
1342    # Input data for each round
1343    RoundData = namedtuple('RoundData', ['EventProperties', 'DataLength', 'FragmentPref', 'Duration', 'MaxEvents'])
1344    rounds = [
1345        RoundData(0x0000, 0, 0x00, 0x0000, 0x00),
1346        RoundData(0x0000, 31, 0x00, 0x0000, 0x00),
1347        RoundData(0x0000, 474, 0x00, 0x0000, 0x00),
1348        RoundData(0x0000, 711, 0x00, 0x0000, 0x00),
1349        RoundData(0x0000, 948, 0x00, 0x0000, 0x00),
1350        RoundData(0x0000, MaxAdvDataLen, 0x00, 0x0000, 0x00),
1351        RoundData(0x0000, MaxAdvDataLen, 0x01, 0x0000, 0x00),
1352        RoundData(0x0004, 0, 0x00, 0x0000, 0x00),
1353        RoundData(0x0004, 251, 0x00, 0x0000, 0x00),
1354        RoundData(0x0004, MaxAdvDataLen, 0x00, 0x0000, 0x00),
1355        RoundData(0x0000, 0, 0x00, 0x01F4, 0x00),
1356        RoundData(0x0004, 0, 0x00, 0x01F4, 0x00),
1357        RoundData(0x0000, 0, 0x00, 0x0000, 0x32),
1358        RoundData(0x0004, 0, 0x00, 0x0000, 0x32),
1359    ]
1360
1361    success = True
1362
1363    for round in rounds:
1364
1365        if round.DataLength > MaxAdvDataLen:
1366            # Skip unsupported advertising data length
1367            continue
1368
1369        advInterval = 0xA0 # 160 x 0.625 ms = 100.00 ms
1370        Handle          = 0
1371        Properties      = round.EventProperties
1372        PrimMinInterval = toArray(advInterval, 3)
1373        PrimMaxInterval = toArray(advInterval, 3)
1374        PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
1375        OwnAddrType     = SimpleAddressType.PUBLIC
1376        PeerAddrType    = SimpleAddressType.PUBLIC
1377        PeerAddress     = toArray(0x456789ABCDEF, 6)
1378        FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
1379        TxPower         = 0
1380        PrimAdvPhy      = PhysicalChannel.LE_1M
1381        SecAdvMaxSkip   = 0
1382        SecAdvPhy       = phy
1383        Sid             = 0
1384        ScanReqNotifyEnable = 0
1385
1386        success = success and preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
1387                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
1388                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
1389        if not success:
1390            return success
1391
1392        if round.DataLength > 0:
1393            # Set adv data
1394            advData = random.randint(1, 255, round.DataLength)
1395            if not set_complete_ext_adv_data(transport, upperTester, Handle, round.FragmentPref, advData):
1396                return False
1397        else:
1398            advData = []
1399            status = le_set_extended_advertising_data(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, round.FragmentPref, advData, 100)
1400            if status != 0:
1401                return False
1402
1403        flush_events(transport, upperTester, 100)
1404        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [round.Duration], [round.MaxEvents], trace)
1405
1406        if not success:
1407            return success
1408
1409        if round.Duration != 0:
1410            # Wait until end of duration + 500ms (to make sure advertising has stopped)
1411            transport.wait(round.Duration*10 + 500)
1412        elif round.MaxEvents != 0:
1413            # Wait for max_events*adv_interval + 500 ms (to make sure advertising has stopped)
1414            transport.wait(math.ceil(round.MaxEvents*advInterval*0.625 + 500))
1415        else:
1416            # Wait until ~10 events have been received
1417            transport.wait(math.ceil(10.5*advInterval*0.625))
1418
1419        if round.Duration == 0 and round.MaxEvents == 0:
1420            # Disable advertising now
1421            success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.DISABLE, [Handle], [round.Duration], [round.MaxEvents], trace)
1422        else:
1423            # LE Advertising Set Terminated event shall be received with correct error code
1424            event = get_event(transport, upperTester, 200)
1425            success = success and event
1426            if event:
1427                status, advertiseHandle, connectionHandle, completedEvents = event.decode()
1428                success = success and advertiseHandle == Handle
1429                if round.Duration != 0:
1430                    success = success and status == 0x3C # Advertising Timeout
1431                else:
1432                    success = success and status == 0x43 # Limit Reached
1433
1434        # Check ADV_EXT_INDs
1435        # AdvMode set to 00b; The ADV_EXT_IND PDU shall not include the SyncInfo, TxPower, ACAD, or AdvData
1436        # fields. If advertising data was set, the ADV_EXT_IND PDU shall include the AuxPtr field;
1437        # otherwise, the ADV_EXT_IND PDU *may* include the AuxPtr field. If the AuxPtr field is included,
1438        # the ADV_EXT_IND PDU shall also include the ADI field with the SID set to the value used; otherwise that field shall not be included
1439        for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
1440            success = success and packet.payload['AdvMode'] == 0b00
1441            success = success and 'SyncInfo' not in packet.payload
1442            success = success and 'TxPower' not in packet.payload
1443            success = success and 'ACAD' not in packet.payload
1444            success = success and 'AD' not in packet.payload
1445            if round.DataLength > 0:
1446                success = success and 'AuxPtr' in packet.payload
1447            if 'AuxPtr' in packet.payload:
1448                success = success and 'ADI' in packet.payload
1449                if 'ADI' in packet.payload:
1450                    success = success and packet.payload['ADI'].SID == Sid
1451
1452        completeAdvDataFound = 0
1453        # Check AUX_ADV_INDs
1454        # AdvMode set to 00b; The AUX_ADV_IND PDU shall not include
1455        # the SyncInfo, or TxPower fields. The AUX_ADV_IND PDU shall include the ADI field
1456        # matching the ADI field from the ADV_EXT_IND. If the AUX_ADV_IND PDU does not contain all advertising data
1457        # it shall include an AuxPtr field.
1458        # The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
1459        for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
1460            success = success and packet.payload['AdvMode'] == 0b00
1461            success = success and 'SyncInfo' not in packet.payload
1462            success = success and 'TxPower' not in packet.payload
1463            success = success and 'ADI' in packet.payload
1464            success = success and packet.payload['ADI'].SID == Sid
1465            for superiorPacket in packet.payload['SuperiorPackets']:
1466                success = success and packet.payload['ADI'].DID == superiorPacket.payload['ADI'].DID
1467                success = success and packet.ts >= superiorPacket.ts + 300
1468            if round.DataLength > 0:
1469                if round.DataLength > len(packet.payload['AD']):
1470                    success = success and 'AuxPtr' in packet.payload
1471                else:
1472                    # Check advertising data against input
1473                    completeAdvDataFound += 1
1474                    success = success and len(packet.payload['AD']) == round.DataLength
1475                    for i in range(round.DataLength):
1476                        success = success and packet.payload['AD'][i] == advData[i]
1477            else:
1478                success = 'AD' not in packet.payload
1479
1480        def collectChainedAdvData(packet):
1481            advData = bytes([])
1482            if packet.payload['SuperiorPackets'][0].type.name != 'ADV_EXT_IND':
1483                advData = collectChainedAdvData(packet.payload['SuperiorPackets'][0])
1484            advData += packet.payload['AD']
1485            return advData
1486
1487        # Check AUX_CHAIN_INDs
1488        # AdvMode set to 00b; The AUX_CHAIN_IND PDU shall include the ADI field matching the ADI field from AUX_ADV_IND
1489        # and the AdvData field containing additional data. The AUX_CHAIN_IND PDU shall not include the AdvA,
1490        # TargetA, TxPower, or SyncInfo fields
1491        # The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
1492        for packet in packets.fetch(packet_filter=('AUX_CHAIN_IND')):
1493            success = success and packet.payload['AdvMode'] == 0b00
1494            success = success and 'AdvA' not in packet.payload
1495            success = success and 'TargetA' not in packet.payload
1496            success = success and 'TxPower' not in packet.payload
1497            success = success and 'SyncInfo' not in packet.payload
1498            success = success and 'ADI' in packet.payload
1499            success = success and packet.payload['ADI'].SID == Sid
1500            for superiorPacket in packet.payload['SuperiorPackets']:
1501                success = success and packet.payload['ADI'].DID == superiorPacket.payload['ADI'].DID
1502                success = success and packet.ts >= superiorPacket.ts + 300
1503            if 'AuxPtr' not in packet.payload:
1504                # Collect complete advertising data and check advertising data against input
1505                completeAdvDataFound += 1
1506                collectedAdvData = collectChainedAdvData(packet)
1507                success = success and len(collectedAdvData) == round.DataLength
1508                for i in range(round.DataLength):
1509                    success = success and collectedAdvData[i] == advData[i]
1510
1511        if round.DataLength > 0:
1512            # Check that we actually got the complete data (ie. that some AUX_CHAIN_INDs/AUX_ADV_INDs do not have an aux ptr)
1513            success = success and completeAdvDataFound > 0
1514
1515        if round.MaxEvents != 0:
1516            # Calculate number of advertising events by grouping ADV_EXT_INDs (a delay of more than 10 ms, 3 packets already in the group or a duplicate channel number means a new group)
1517            numEvents = 0
1518            group = []
1519            lastTs = -10000
1520            for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
1521                if lastTs < packet.ts - 10000 or len(group) >= 3:
1522                    group = [packet]
1523                    numEvents += 1
1524                else:
1525                    # Check if this packets channel is already part of the current group
1526                    duplicateChannel = False
1527                    for groupPacket in group:
1528                        if groupPacket.channel_num == packet.channel_num:
1529                            duplicateChannel = True
1530                            break
1531                    if duplicateChannel:
1532                        group = [packet]
1533                        numEvents += 1
1534                    else:
1535                        group += [packet]
1536                lastTs = packet.ts
1537            # Verify that the IUT did not send more than Max_Extended_Advertising_Events advertising events
1538            success = success and numEvents <= round.MaxEvents
1539        elif round.Duration != 0:
1540            # Check that advertising is stopped after duration has elapsed
1541            maxDurationMs = (10 * round.Duration + 10.000) * (1 + 500.0/1000000.0) + 0.016
1542
1543            firstAdv = None
1544            lastAdv = None
1545            for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
1546                if not firstAdv:
1547                    firstAdv = packet
1548                lastAdv = packet
1549
1550            actualDurationMs = (lastAdv.ts - firstAdv.ts) / 1000
1551            success = success and actualDurationMs <= maxDurationMs
1552
1553        if round.EventProperties == 0x0004:
1554            # TargetA field containing the Lower Tester’s address specified in the HCI_LE_Set_Extended_Advertising_Parameters command
1555            # is included in either the ADV_EXT_IND PDU or the AUX_ADV_IND PDU, but not both
1556            advExtIndHasTargetA = False
1557            auxAdvIndHasTargetA = False
1558            for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
1559                advExtIndHasTargetA = 'TargetA' in packet.payload
1560                if 'TargetA' in packet.payload:
1561                    success = success and packet.payload['TargetA'] == 0x456789ABCDEF
1562            for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
1563                auxAdvIndHasTargetA = 'TargetA' in packet.payload
1564                if 'TargetA' in packet.payload:
1565                    success = success and packet.payload['TargetA'] == 0x456789ABCDEF
1566            success = success and advExtIndHasTargetA != auxAdvIndHasTargetA
1567
1568        if not success:
1569            return success
1570
1571        # Flush events and packets for next round
1572        flush_events(transport, upperTester, 100)
1573        packets.flush()
1574
1575    return success
1576
1577"""
1578    LL/DDI/ADV/BV-47-C [Extended Advertising, Non-Connectable - LE 1M PHY]
1579"""
1580def ll_ddi_adv_bv_47_c(transport, upperTester, lowerTester, trace, packets):
1581    return do_ll_ddi_adv_bv_47_49_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_1M)
1582
1583"""
1584    LL/DDI/ADV/BV-49-C [Extended Advertising, Non-Connectable - LE 2M PHY]
1585"""
1586def ll_ddi_adv_bv_49_c(transport, upperTester, lowerTester, trace, packets):
1587    return do_ll_ddi_adv_bv_47_49_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_2M)
1588
1589"""
1590    LL/DDI/ADV/BV-52-C [Extended Advertising, Scannable - ADI allowed in scan response - LE 2M PHY]
1591"""
1592def ll_ddi_adv_bv_52_c(transport, upperTester, lowerTester, trace, packets):
1593    return do_ll_ddi_adv_bv_45_52_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_2M)
1594
1595
1596# Implements LL/DDI/ADV/BI-05-C and LL/DDI/ADV/BI-06-C test cases (only difference is the event properties)
1597def do_ll_ddi_adv_bi_05_06_c(transport, upperTester, lowerTester, trace, eventProperties):
1598
1599    advInterval = 0x20 # 32 x 0.625 ms = 20.00 ms
1600    Handle          = 0
1601    Properties      = eventProperties
1602    PrimMinInterval = toArray(advInterval, 3)
1603    PrimMaxInterval = toArray(advInterval, 3)
1604    PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
1605    OwnAddrType     = SimpleAddressType.PUBLIC
1606    PeerAddrType    = SimpleAddressType.PUBLIC
1607    PeerAddress     = toArray(0, 6)
1608    FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
1609    TxPower         = 0
1610    PrimAdvPhy      = PhysicalChannel.LE_1M
1611    SecAdvMaxSkip   = 0
1612    SecAdvPhy       = 0x01
1613    Sid             = 0
1614    ScanReqNotifyEnable = 0
1615
1616    success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
1617                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
1618                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
1619
1620    advData = random.randint(0, 256, 31)
1621    if eventProperties & 0x02:
1622        success = success and preamble_ext_scan_response_data_set(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, 0, advData, trace)
1623    else:
1624        success = success and preamble_ext_advertising_data_set(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, 0, advData, trace)
1625
1626    success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0], [0], trace)
1627
1628    if not success:
1629        return False
1630
1631    advData = random.randint(0, 256, 32)
1632    if eventProperties & 0x02:
1633        status = le_set_extended_scan_response_data(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, 0, advData, 200)
1634    else:
1635        status = le_set_extended_advertising_data(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, 0, advData, 200)
1636
1637    # Command should fail with error 0x12 (Invalid HCI Command Parameters)
1638    success = success and status == 0x12
1639    event = get_event(transport, upperTester, 200)
1640    success = success and event.event == Events.BT_HCI_EVT_CMD_COMPLETE
1641    if success:
1642        expectedOpCode = CmdOpcodes.BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA if (eventProperties & 0x02) else CmdOpcodes.BT_HCI_OP_LE_SET_EXT_ADV_DATA
1643        numPackets, opCode, status = event.decode()
1644        success = success and opCode == expectedOpCode and status == 0x12
1645
1646    return success
1647
1648"""
1649    LL/DDI/ADV/BI-05-C [ Disallow Extended Advertising PDU sizes for Legacy Advertising when advertising enabled ]
1650"""
1651def ll_ddi_adv_bi_05_c(transport, upperTester, lowerTester, trace):
1652    # Advertising_Event_Properties set to “Use legacy advertising PDUs” -> bit 4 set
1653    return do_ll_ddi_adv_bi_05_06_c(transport, upperTester, lowerTester, trace, 0b00010000)
1654
1655"""
1656    LL/DDI/ADV/BI-06-C [ Disallow Extended Advertising PDU sizes for Scannable Legacy Advertising when advertising enabled ]
1657"""
1658def ll_ddi_adv_bi_06_c(transport, upperTester, lowerTester, trace):
1659    # Advertising_Event_Properties set to “Scannable Legacy advertising” and “Use legacy advertising PDUs” -> bits 1 and 4 set
1660    return do_ll_ddi_adv_bi_05_06_c(transport, upperTester, lowerTester, trace, 0b00010010)
1661
1662"""
1663    LL/DDI/SCN/BV-01-C [Passive Scanning of Non-Connectable Advertising Packets]
1664
1665    Last modified: 31-07-2019
1666    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1667"""
1668def ll_ddi_scn_bv_01_c(transport, upperTester, lowerTester, trace):
1669
1670    advertiser, scanner = setPassiveScanning(transport, upperTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 20);
1671
1672    success = scanner.enable();
1673
1674    for i, channel in enumerate([ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ]):
1675        if   i == 0:
1676            advertiser.ownAddress = publicIdentityAddress(lowerTester);
1677        elif i == 1:
1678            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1679        elif i == 2:
1680            advertiser.ownAddress = Address( ExtendedAddressType.RANDOM, address_scramble_OUI(0x456789ABCDEF) | 0xC00000000000);
1681
1682        if advertiser.ownAddress.type == ExtendedAddressType.PUBLIC:
1683            success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1684        else:
1685            success = success and preamble_set_random_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1686
1687        advertiser.channels = channel;
1688        advertiser.advertiseData = [ i + 1 ];
1689
1690        success = advertiser.enable() and success;
1691        scanner.monitor();
1692        success = advertiser.disable() and success;
1693        success = success and scanner.qualifyReports( 20, advertiser.ownAddress, advertiser.advertiseData );
1694
1695    success = scanner.disable() and success;
1696
1697    return success;
1698
1699"""
1700    LL/DDI/SCN/BV-02-C [Filtered Passive Scanning of Non-Connectable Advertising Packets]
1701
1702    Last modified: 31-07-2019
1703    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1704"""
1705def ll_ddi_scn_bv_02_c(transport, upperTester, lowerTester, trace):
1706
1707    advertiser, scanner = setPassiveScanning(transport, upperTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 20, \
1708                                             AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.CHANNEL_37, ScanningFilterPolicy.FILTER_ACCEPT_LIST);
1709    """
1710        Place Public address of lowerTester in the Filter Accept List
1711    """
1712    peerAddress = publicIdentityAddress(lowerTester);
1713    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
1714
1715    success = scanner.enable() and success;
1716
1717    for i in range(4):
1718        if   i == 0:
1719            advertiser.ownAddress = publicIdentityAddress(lowerTester);
1720        elif i == 1:
1721            advertiser.ownAddress = Address( ExtendedAddressType.RANDOM, 0x456789ABCDEF | 0xC00000000000);
1722        elif i == 2:
1723            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1724        elif i == 3:
1725            advertiser.ownAddress = Address( ExtendedAddressType.RANDOM, address_exchange_OUI_LAP(0x456789ABCDEF) | 0xC00000000000);
1726
1727        if advertiser.ownAddress.type == ExtendedAddressType.PUBLIC:
1728            success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1729        else:
1730            success = success and preamble_set_random_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1731
1732        advertiser.advertiseData = [ i + 1 ];
1733
1734        success = advertiser.enable() and success;
1735        scanner.monitor();
1736        success = advertiser.disable() and success;
1737        if i == 0:
1738            success = success and scanner.qualifyReports( 20, advertiser.ownAddress, advertiser.advertiseData );
1739        else:
1740            success = success and scanner.qualifyReports( 0 );
1741
1742    success = scanner.disable() and success;
1743
1744    return success;
1745
1746"""
1747    LL/DDI/SCN/BV-03-C [Active Scanning of Connectable Undirected Advertising Packets]
1748
1749    Last modified: 31-07-2019
1750    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1751"""
1752def ll_ddi_scn_bv_03_c(transport, upperTester, lowerTester, trace):
1753
1754    advertiser, scanner = setActiveScanning(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 20, 1);
1755
1756    adData = ADData();
1757    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IX' );
1758    success = scanner.enable();
1759
1760    for channel in [ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ]:
1761        for i in range(4):
1762            if   i == 0:
1763                advertiser.ownAddress = publicIdentityAddress(lowerTester);
1764            elif i == 1:
1765                advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_OUI(0x456789ABCDEF) );
1766            elif i == 2:
1767                advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1768            else:
1769                advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_exchange_OUI_LAP(0x456789ABCDEF) );
1770
1771            success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1772            advertiser.channels = channel;
1773            advertiser.advertiseData = [ i + 1 ];
1774
1775            success = advertiser.enable() and success;
1776            scanner.monitor();
1777            success = advertiser.disable() and success;
1778            success = success and scanner.qualifyReports( 20, advertiser.ownAddress, advertiser.advertiseData );
1779            success = success and scanner.qualifyResponses( 1, advertiser.responseData );
1780
1781    success = scanner.disable() and success;
1782
1783    return success;
1784
1785"""
1786    LL/DDI/SCN/BV-04-C [Filtered Active Scanning of Connectable Undirected Advertising Packets]
1787
1788    Last modified: 31-07-2019
1789    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1790"""
1791def ll_ddi_scn_bv_04_c(transport, upperTester, lowerTester, trace):
1792
1793    advertiser, scanner = setActiveScanning(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 20, 1, \
1794                                            AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.ALL_CHANNELS, ScanningFilterPolicy.FILTER_ACCEPT_LIST);
1795    """
1796        Place Public address of lowerTester in the Filter Accept List
1797    """
1798    peerAddress = publicIdentityAddress(lowerTester);
1799    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
1800
1801    adData = ADData();
1802    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IX' );
1803    success = scanner.enable();
1804
1805    for channel in [ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ]:
1806        for i in range(3):
1807            if   i == 0:
1808                advertiser.ownAddress = publicIdentityAddress(lowerTester);
1809            elif i == 1:
1810                advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1811            else:
1812                advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_exchange_OUI_LAP(0x456789ABCDEF) );
1813
1814            success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1815            advertiser.channels = channel;
1816            advertiser.advertiseData = [ i + 1 ];
1817
1818            success = advertiser.enable() and success;
1819            scanner.monitor();
1820            success = advertiser.disable() and success;
1821            if i == 0:
1822                success = success and scanner.qualifyReports( 20, advertiser.ownAddress, advertiser.advertiseData );
1823                success = success and scanner.qualifyResponses( 1, advertiser.responseData );
1824            else:
1825                success = success and scanner.qualifyReports( 0 );
1826                success = success and scanner.qualifyResponses( 0 );
1827
1828    success = scanner.disable() and success;
1829
1830    return success;
1831
1832"""
1833    LL/DDI/SCN/BV-05-C [Scanning for different Advertiser types with and without Data]
1834
1835    Last modified: 31-07-2019
1836    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1837"""
1838def ll_ddi_scn_bv_05_c(transport, upperTester, lowerTester, trace):
1839
1840    advertiser, scanner = setActiveScanning(transport, upperTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 20, 1);
1841
1842    adData = ADData();
1843    advertiser.advertiseData = adData.encode( ADType.FLAGS, ADFlag.BR_EDR_NOT_SUPPORTED );
1844    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IX' );
1845    success = scanner.enable();
1846
1847    for i, (channel, advertiseType, reports) in enumerate(zip( \
1848                             [ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ], \
1849                             [ Advertising.NON_CONNECTABLE_UNDIRECTED, Advertising.SCANNABLE_UNDIRECTED, Advertising.CONNECTABLE_HDC_DIRECTED ], \
1850                             [ 20, 30, 15 ] )):
1851        if   i == 0:
1852            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_OUI(0x456789ABCDEF) );
1853        elif i == 1:
1854            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1855        else:
1856            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_exchange_OUI_LAP(0x456789ABCDEF) );
1857
1858        success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1859        advertiser.channels = channel;
1860        advertiser.advertiseType = advertiseType;
1861        advertiser.advertiseData = [ i + 1 ] if i < 2 else [ ];
1862
1863        scanner.expectedReports = reports;
1864        scanner.reportType = matchingReportType(advertiseType);
1865
1866        success = advertiser.enable() and success;
1867        scanner.monitor();
1868        success = advertiser.disable() and success;
1869        success = success and scanner.qualifyReports( reports, advertiser.ownAddress, advertiser.advertiseData );
1870        if i == 1:
1871            success = success and scanner.qualifyResponses( 1, advertiser.responseData );
1872        else:
1873            success = success and scanner.qualifyResponses( 0 );
1874
1875    success = scanner.disable() and success;
1876
1877    return success;
1878
1879"""
1880    LL/DDI/SCN/BV-10-C [Passive Scanning for Undirected Advertising Packets with Data]
1881
1882    Last modified: 31-07-2019
1883    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1884"""
1885def ll_ddi_scn_bv_10_c(transport, upperTester, lowerTester, trace):
1886
1887    advertiser, scanner = setPassiveScanning(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 20);
1888
1889    success = True;
1890
1891    for i, channel in enumerate([ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ]):
1892        if   i == 0:
1893            advertiser.ownAddress = publicIdentityAddress(lowerTester);
1894        elif i == 1:
1895            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1896        elif i == 2:
1897            advertiser.ownAddress = Address( ExtendedAddressType.RANDOM, address_scramble_OUI(0x456789ABCDEF) | 0xC00000000000);
1898
1899        if (advertiser.ownAddress.type == ExtendedAddressType.PUBLIC):
1900            success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1901        else:
1902            success = success and preamble_set_random_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1903
1904        advertiser.channels = channel;
1905        advertiser.advertiseData = [ i + 1 ];
1906
1907        success = advertiser.enable() and success;
1908        success = scanner.enable() and success;
1909        scanner.monitor();
1910        success = scanner.disable() and success;
1911        success = advertiser.disable() and success;
1912        success = success and scanner.qualifyReports( 20, advertiser.ownAddress, advertiser.advertiseData );
1913
1914    return success;
1915
1916"""
1917    LL/DDI/SCN/BV-11-C [Passive Scanning for Directed Advertising Packets]
1918
1919    Last modified: 31-07-2019
1920    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1921"""
1922def ll_ddi_scn_bv_11_c(transport, upperTester, lowerTester, trace):
1923
1924    advertiser, scanner = setPassiveScanning(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED, 20, \
1925                                             AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.ALL_CHANNELS, ScanningFilterPolicy.FILTER_ACCEPT_LIST);
1926    """
1927        Place Public address of lowerTester in the Filter Accept List
1928    """
1929    peerAddress = publicIdentityAddress(lowerTester);
1930    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
1931
1932    for i, channel in enumerate([ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ]):
1933        if   i == 0:
1934            advertiser.ownAddress = publicIdentityAddress(lowerTester);
1935        elif i == 1:
1936            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1937        elif i == 2:
1938            advertiser.ownAddress = Address( ExtendedAddressType.RANDOM, 0x456789ABCDEF | 0xC00000000000 );
1939
1940        if (advertiser.ownAddress.type == ExtendedAddressType.PUBLIC):
1941            success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1942        else:
1943            success = success and preamble_set_random_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1944
1945        advertiser.channels = channel;
1946
1947        success = advertiser.enable() and success;
1948        success = scanner.enable() and success;
1949        scanner.monitor();
1950        success = scanner.disable() and success;
1951        success = advertiser.disable() and success;
1952        if i == 0:
1953            success = success and scanner.qualifyReports( 20, advertiser.ownAddress, advertiser.advertiseData );
1954        else:
1955            success = success and scanner.qualifyReports( 0 );
1956
1957    return success;
1958
1959"""
1960    LL/DDI/SCN/BV-12-C [Passive Scanning for Discoverable Undirected Advertising Packets]
1961
1962    Last modified: 31-07-2019
1963    Reviewed and verified: 31-07-2019 Henrik Eriksen (NOTE: Advertise data not modified for each advertise event)
1964"""
1965def ll_ddi_scn_bv_12_c(transport, upperTester, lowerTester, trace):
1966
1967    advertiser, scanner = setPassiveScanning(transport, upperTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20, \
1968                                             AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.ALL_CHANNELS, ScanningFilterPolicy.FILTER_ACCEPT_LIST);
1969    """
1970        Place Public address of lowerTester in the Filter Accept List
1971    """
1972    peerAddress = publicIdentityAddress(lowerTester);
1973    success = addAddressesToFilterAcceptList(transport, upperTester, [ peerAddress ], trace);
1974
1975    for i, channel in enumerate([ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ]):
1976        if   i == 0:
1977            advertiser.ownAddress = publicIdentityAddress(lowerTester);
1978        elif i == 1:
1979            advertiser.ownAddress = Address( ExtendedAddressType.PUBLIC, address_scramble_LAP(0x456789ABCDEF) );
1980        elif i == 2:
1981            advertiser.ownAddress = Address( ExtendedAddressType.RANDOM, address_scramble_OUI(0x456789ABCDEF) | 0xC00000000000);
1982
1983        if (advertiser.ownAddress.type == ExtendedAddressType.PUBLIC):
1984            success = success and preamble_set_public_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1985        else:
1986            success = success and preamble_set_random_address(transport, lowerTester, toNumber(advertiser.ownAddress.address), trace);
1987
1988        advertiser.channels = channel;
1989        advertiser.advertiseData = [ i + 1 ];
1990
1991        success = advertiser.enable() and success;
1992        success = scanner.enable() and success;
1993        scanner.monitor();
1994        success = scanner.disable() and success;
1995        success = advertiser.disable() and success;
1996        if i == 0:
1997            success = success and scanner.qualifyReports( 20, advertiser.ownAddress, advertiser.advertiseData );
1998        else:
1999            success = success and scanner.qualifyReports( 0 );
2000
2001    return success;
2002
2003"""
2004    LL/DDI/SCN/BV-13-C [Passive Scanning for Non-Connectable Advertising Packets using Network Privacy]
2005
2006    Last modified: 31-07-2019
2007    Reviewed and verified: 31-07-2019 Henrik Eriksen
2008"""
2009def ll_ddi_scn_bv_13_c(transport, upperTester, lowerTester, trace):
2010
2011    advertiser, scanner = setPrivatePassiveScanning(transport, upperTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 20);
2012    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2013    """
2014        Add Public address of lowerTester to upperTesters Resolving List
2015        Add Public address of upperTester to lowerTesters Resolving List (to allow the Controller to generate a Private Resolvable Address)
2016    """
2017    RPAs = [ ResolvableAddresses( transport, upperTester, trace ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
2018    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
2019    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
2020    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
2021    """
2022        Set Resolvable Private Address timeout in seconds ( sixty seconds )
2023    """
2024    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
2025    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
2026
2027    success = advertiser.enable() and success;
2028    success = scanner.enable() and success;
2029    scanner.monitor();
2030    success = scanner.disable() and success;
2031    success = advertiser.disable() and success;
2032    """
2033        Verify that the Advertise address of the lowerTester has been correctly resolved
2034    """
2035    success = success and scanner.qualifyReports( 20, Address( ExtendedAddressType.RESOLVABLE_OR_PUBLIC, 0x456789ABCDEF ) );
2036
2037    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
2038
2039    return success;
2040
2041"""
2042    LL/DDI/SCN/BV-14-C [Passive Scanning for Connectable Directed Advertising Packets using Network Privacy]
2043
2044    Last modified: 01-08-2019
2045    Reviewed and verified: 01-08-2019 Henrik Eriksen
2046"""
2047def ll_ddi_scn_bv_14_c(transport, upperTester, lowerTester, trace):
2048
2049    advertiser, scanner = setPrivatePassiveScanning(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED, 20, \
2050                                                    ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
2051                                                    AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.CHANNEL_37, ScanningFilterPolicy.FILTER_ID_DIRECTED);
2052    """
2053        Add Public address of lowerTester to upperTesters Resolving List
2054        Add Public address of upperTester to lowerTesters Resolving List (to allow the Controller to generate a Private Resolvable Address)
2055    """
2056    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
2057    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
2058    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
2059    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester) ) and success;
2060    """
2061        Set resolvable private address timeout in seconds ( sixty seconds )
2062    """
2063    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
2064    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
2065
2066    success = advertiser.enable() and success;
2067    success = scanner.enable() and success;
2068    scanner.monitor();
2069    success = scanner.disable() and success;
2070    success = advertiser.disable() and success;
2071    success = success and scanner.qualifyDirectedReports( 20 );
2072
2073    ok, address = readLocalResolvableAddress(transport, upperTester, publicIdentityAddress(upperTester), trace);
2074    trace.trace(8, "Address used by Scanner: %s" % str(Address( ExtendedAddressType.RESOLVABLE_OR_PUBLIC, address )));
2075
2076    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
2077
2078    return success;
2079
2080"""
2081    LL/DDI/SCN/BV-15-C [Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with no Local or Peer IRK]
2082
2083    Last modified: 01-08-2019
2084    Reviewed and verified: 01-08-2019 Henrik Eriksen
2085"""
2086def ll_ddi_scn_bv_15_c(transport, upperTester, lowerTester, trace):
2087
2088    advertiser, scanner = setPrivateActiveScanning(transport, upperTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20, 1, \
2089                                                   ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_RANDOM);
2090
2091    adData = ADData();
2092    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2093    advertiser.advertiseData = [ 0x00 ];
2094    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IX' );
2095    """
2096        Add Public address of lowerTester to the Resolving List
2097    """
2098    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
2099    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
2100    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
2101    success = RPAs[upperTester].add( Address( SimpleAddressType.RANDOM, tests.test_utils.lowerRandomAddress ) ) and success;
2102    """
2103        Set resolvable private address timeout in seconds ( sixty seconds )
2104    """
2105    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
2106    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
2107
2108    success = advertiser.enable() and success;
2109    success = scanner.enable() and success;
2110    scanner.monitor();
2111    success = scanner.disable() and success;
2112    success = advertiser.disable() and success;
2113    success = success and scanner.qualifyReports( 5, None, advertiser.advertiseData );
2114    success = success and scanner.qualifyResponses( 5, advertiser.responseData );
2115
2116    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
2117
2118    return success;
2119
2120"""
2121    LL/DDI/SCN/BV-16-C [Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with Local and no Peer IRK]
2122
2123    Last modified: 01-08-2019
2124    Reviewed and verified: 01-08-2019 Henrik Eriksen (Peer address type not set to 0x01 in entry added to RPA List)
2125"""
2126def ll_ddi_scn_bv_16_c(transport, upperTester, lowerTester, trace):
2127
2128    advertiser, scanner = setPrivateActiveScanning(transport, upperTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20, 1);
2129
2130    adData = ADData();
2131    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2132    advertiser.advertiseData = [ 0x00 ];
2133    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IX' );
2134
2135    lowerIdentityAddress = publicIdentityAddress(lowerTester);
2136    """
2137        Add Public address of lowerTester to the Resolving List
2138    """
2139    RPA = ResolvableAddresses( transport, upperTester, trace, upperIRK );
2140    success = RPA.clear();
2141    success = RPA.add( lowerIdentityAddress ) and success;
2142    """
2143        Set resolvable private address timeout in seconds ( two seconds )
2144    """
2145    success = RPA.timeout( 2 ) and success;
2146    success = RPA.enable() and success;
2147
2148    success = advertiser.enable() and success;
2149
2150    resolvableAddresses = [ 0, 0 ];
2151
2152    for i in range(2):
2153        if i == 1:
2154            """
2155                Wait for Resolvable Private Address timeout to expire...
2156            """
2157            transport.wait(2000);
2158        success = scanner.enable() and success;
2159        scanner.monitor();
2160        success = scanner.disable() and success;
2161        success = success and scanner.qualifyReports( 5, lowerIdentityAddress, advertiser.advertiseData );
2162        success = success and scanner.qualifyResponses( 5, advertiser.responseData );
2163
2164        addressRead, resolvableAddresses[i] = readLocalResolvableAddress(transport, upperTester, lowerIdentityAddress, trace);
2165        trace.trace(6, "Local Resolvable Address: %s" % formatAddress(resolvableAddresses[i]));
2166
2167    success = advertiser.disable() and success;
2168    success = success and toNumber(resolvableAddresses[0]) != toNumber(resolvableAddresses[1]);
2169    success = RPA.disable() and success;
2170
2171    return success;
2172
2173"""
2174    LL/DDI/SCN/BV-17-C [Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with no Local and a Peer IRK]
2175
2176    Last modified: 01-08-2019
2177    Reviewed and verified: 01-08-2019 Henrik Eriksen
2178"""
2179def ll_ddi_scn_bv_17_c(transport, upperTester, lowerTester, trace):
2180
2181    advertiser, scanner = setPrivateActiveScanning(transport, upperTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20, 1, \
2182                                                   ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_RANDOM);
2183    adData = ADData();
2184    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2185    advertiser.advertiseData = [ 0x00 ];
2186    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IX' );
2187    """
2188        Add Public address of lowerTester to the Resolving List
2189    """
2190    RPAs = [ ResolvableAddresses( transport, upperTester, trace ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
2191    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
2192    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
2193    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
2194    """
2195        Set resolvable private address timeout in seconds ( sixty seconds )
2196    """
2197    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
2198    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
2199
2200    success = advertiser.enable() and success;
2201    success = scanner.enable() and success;
2202    scanner.monitor();
2203    success = scanner.disable() and success;
2204    success = advertiser.disable() and success;
2205    success = success and scanner.qualifyReports( 5, None, advertiser.advertiseData );
2206    success = success and scanner.qualifyResponses( 5, advertiser.responseData );
2207
2208    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
2209
2210    return success;
2211
2212"""
2213    LL/DDI/SCN/BV-18-C [Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with both Local and Peer IRKs]
2214
2215    Last modified: 02-08-2019
2216    Reviewed and verified: 02-08-2019 Henrik Eriksen
2217"""
2218def ll_ddi_scn_bv_18_c(transport, upperTester, lowerTester, trace):
2219
2220    advertiser, scanner = setPrivateActiveScanning(transport, upperTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20);
2221
2222    adData = ADData();
2223    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2224    advertiser.advertiseData = [ 0x00 ];
2225    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IX' );
2226    """
2227        Add Public address of lowerTester to the Resolving List
2228    """
2229    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
2230    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
2231    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
2232    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
2233    """
2234        Set resolvable private address timeout in seconds ( sixty seconds )
2235    """
2236    success = RPAs[upperTester].timeout( 60 ) and RPAs[upperTester].timeout( 60 ) and success;
2237    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
2238
2239    success = advertiser.enable() and success;
2240    success = scanner.enable() and success;
2241    scanner.monitor();
2242    success = scanner.disable() and success;
2243    success = advertiser.disable() and success;
2244    success = success and scanner.qualifyReports( 5, None, advertiser.advertiseData );
2245    success = success and scanner.qualifyResponses( 5, advertiser.responseData );
2246
2247    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
2248
2249    return success;
2250
2251"""
2252    LL/DDI/SCN/BV-26-C [Passive Scanning for Non-Connectable Advertising Packets using Network Privacy]
2253
2254    Last modified: 02-08-2019
2255    Reviewed and verified: 02-08-2019 Henrik Eriksen
2256"""
2257def ll_ddi_scn_bv_26_c(transport, upperTester, lowerTester, trace):
2258
2259    advertiser, scanner = setPrivatePassiveScanning(transport, upperTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 20);
2260    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2261    """
2262        Add Public address of lowerTester to the Resolving List
2263    """
2264    RPA = ResolvableAddresses( transport, upperTester, trace );
2265    success = RPA.clear();
2266    success = RPA.add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
2267    """
2268        Set resolvable private address timeout in seconds ( sixty seconds )
2269    """
2270    success = RPA.timeout( 60 ) and success;
2271    success = RPA.enable() and success;
2272
2273    success = advertiser.enable() and success;
2274    success = scanner.enable() and success;
2275    scanner.monitor();
2276    success = scanner.disable() and success;
2277    success = advertiser.disable() and success;
2278    success = success and scanner.qualifyReports( 0 );
2279
2280    success = RPA.disable() and success;
2281
2282    return success;
2283
2284"""
2285    LL/DDI/SCN/BV-28-C [Passive Scanning for Non-Connectable Advertising Packets using Device Privacy]
2286
2287    Last modified: 02-08-2019
2288    Reviewed and verified: 02-08-2019 Henrik Eriksen
2289"""
2290def ll_ddi_scn_bv_28_c(transport, upperTester, lowerTester, trace):
2291
2292    advertiser, scanner = setPrivatePassiveScanning(transport, upperTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 20);
2293    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2294
2295    """
2296        Add Public address of lowerTester to the Resolving List
2297    """
2298    lowerIdentityAddress = publicIdentityAddress(lowerTester);
2299    RPA = ResolvableAddresses( transport, upperTester, trace );
2300    success = RPA.clear();
2301    success = RPA.add( lowerIdentityAddress, lowerIRK ) and success;
2302    """
2303        Set Device Privacy Mode
2304    """
2305    success = setPrivacyMode(transport, upperTester, lowerIdentityAddress, PrivacyMode.DEVICE_PRIVACY, trace) and success;
2306    """
2307        Set resolvable private address timeout in seconds ( sixty seconds )
2308    """
2309    success = RPA.timeout( 60 ) and success;
2310    success = RPA.enable() and success;
2311
2312    success = advertiser.enable() and success;
2313    success = scanner.enable() and success;
2314    scanner.monitor();
2315    success = scanner.disable() and success;
2316    success = advertiser.disable() and success;
2317    success = success and scanner.qualifyReports( 20, lowerIdentityAddress );
2318
2319    success = RPA.disable() and success;
2320
2321    return success;
2322
2323"""
2324    LL/CON/ADV/BV-01-C [Accepting Connection Request]
2325
2326    Last modified: 02-08-2019
2327    Reviewed and verified: 02-08-2019 Henrik Eriksen
2328"""
2329def ll_con_adv_bv_01_c(transport, upperTester, lowerTester, trace):
2330
2331    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 5);
2332    advertiser.channels = AdvertiseChannel.CHANNEL_37;
2333
2334    initiatorAddress = Address( ExtendedAddressType.PUBLIC );
2335    initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, publicIdentityAddress(upperTester));
2336
2337    success = advertiser.enable();
2338    connected = initiator.connect();
2339    success = success and connected;
2340    """
2341        If a connection was established Advertising should have seized...
2342    """
2343    if connected:
2344        success = scanner.enable() and success;
2345        scanner.monitor();
2346        success = scanner.disable() and success;
2347        success = success and not scanner.qualifyReports( 1 );
2348
2349        transport.wait(24820);
2350
2351        success = initiator.disconnect(0x13) and success;
2352    else:
2353        success = advertiser.disable() and success;
2354
2355    return success;
2356
2357"""
2358    LL/CON/ADV/BV-04-C [Accepting Connection Request after Directed Advertising]
2359
2360    Last modified: 02-08-2019
2361    Reviewed and verified: 02-08-2019 Henrik Eriksen
2362"""
2363def ll_con_adv_bv_04_c(transport, upperTester, lowerTester, trace):
2364
2365    advertiser, scanner = setPassiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED);
2366
2367    initiatorAddress = Address( ExtendedAddressType.PUBLIC );
2368    initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, Address( ExtendedAddressType.PUBLIC, address_scramble_OUI(0x123456789ABC) ));
2369    """
2370        Verify that connection is not established to wrong Init Address
2371    """
2372    success = advertiser.enable();
2373    connected = initiator.connect();
2374    success = success and not connected;
2375    if connected:
2376        success = initiator.disconnect(0x13) and success;
2377    else:
2378        """
2379            Need to stop connection attempt - otherwise following commands will fail with not allowed...
2380        """
2381        success = advertiser.disable() and success;
2382        success = initiator.cancelConnect() and success;
2383    """
2384        Verify that the upper Tester continues to Advertise for 1280 ms.
2385    """
2386    transport.wait(200);
2387    success = scanner.enable() and success;
2388    success = advertiser.enable() and success;
2389    scanner.monitor(True);
2390    success = advertiser.timeout() and success;
2391    success = scanner.disable() and success;
2392    success = success and not scanner.qualifyReportTime( 100, 1200 );
2393
2394    initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, publicIdentityAddress(upperTester));
2395    """
2396        Verify that connection is established to correct Init Address
2397    """
2398    success = advertiser.enable() and success;
2399    connected = initiator.connect();
2400    success = success and connected;
2401
2402    if connected:
2403        transport.wait(2660);
2404
2405        success = initiator.disconnect(0x13) and success;
2406    else:
2407        success = advertiser.disable() and success;
2408
2409    return success;
2410
2411# Implements LL/CON/ADV/BV-05-C and LL/CON/ADV/BV-12-C test cases (only difference is the PHY)
2412# Note: These tests requires a low level device to be available
2413def do_ll_con_adv_bv_05_12_c(transport, upperTester, lowerTester, trace, packets, phy):
2414
2415    advEventProperties = [
2416        0x0001, # Connectable advertising
2417        0x0001, # Connectable advertising
2418        0x0005, # Connectable and directed advertising
2419        0x0005, # Connectable and directed advertising
2420    ]
2421
2422    connectReqAdvA = [
2423        0x123456789ABC, # IUT
2424        0xCBA987654321, # not IUT
2425        0x123456789ABC, # IUT
2426        0xCBA987654321, # not IUT
2427    ]
2428
2429    success = True
2430
2431    for round in range(len(advEventProperties)):
2432
2433        advInterval = 0x20 # 32 x 0.625 ms = 20.00 ms
2434        Handle          = 0
2435        Properties      = advEventProperties[round]
2436        PrimMinInterval = toArray(advInterval, 3)
2437        PrimMaxInterval = toArray(advInterval, 3)
2438        PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
2439        OwnAddrType     = SimpleAddressType.PUBLIC
2440        PeerAddrType    = SimpleAddressType.PUBLIC
2441        PeerAddress     = toArray(0x456789ABCDEF, 6)
2442        FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
2443        TxPower         = 0
2444        PrimAdvPhy      = PhysicalChannel.LE_1M
2445        SecAdvMaxSkip   = 0     # AUX_ADV_IND shall be sent prior to the next advertising event
2446        SecAdvPhy       = phy
2447        Sid             = 0
2448        ScanReqNotifyEnable = 0; # Scan request notifications disabled
2449
2450        success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
2451                                                          PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
2452                                                          PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
2453
2454        if not success:
2455            return False
2456
2457        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0], [0], trace)
2458
2459        if not success:
2460            return False
2461
2462        # Enable LE Channel Selection Algorithm in event mask (it is disabled by default for some reason)
2463        events = [0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00]
2464        status = le_set_event_mask(transport, upperTester, events, 100)
2465        if status != 0:
2466            return False
2467        get_event(transport, upperTester, 200) # Read out command complete event for le_set_event_mask
2468
2469        advA = publicIdentityAddress(upperTester)
2470
2471        if not success:
2472            return False
2473
2474        def checkAdvPackets():
2475            success = True
2476
2477            # Test: The Lower Tester receives an ADV_EXT_IND packet from the IUT with AdvMode set to 01b with only the AuxPtr Extended Header field (and ADI);
2478            #       The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
2479            for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
2480                success = success and packet.payload['AdvMode'] == 0b01
2481                success = success and 'AdvA' not in packet.payload
2482                success = success and 'TargetA' not in packet.payload
2483                success = success and 'CTEInfo' not in packet.payload
2484                success = success and 'ADI' in packet.payload
2485                success = success and 'AuxPtr' in packet.payload
2486                success = success and 'SyncInfo' not in packet.payload
2487                success = success and 'TxPower' not in packet.payload
2488                success = success and 'ACAD' not in packet.payload
2489                success = success and 'AD' not in packet.payload
2490                success = success and packet.phy == '1M'
2491
2492                offset = packet.payload['AuxPtr'].auxOffset * (30 if packet.payload['AuxPtr'].offsetUnits == 0 else 300)
2493                # Packet air length is: pre-amble + AA + header + payload + CRC
2494                packetLength = 1 + 4 + 2 + len(packet) + 3
2495                packetAirtime = 8*packetLength
2496                success = success and offset >= 300 + packetAirtime
2497
2498            # Test AUX_ADV_IND:
2499            # - AdvMode field set to 01b
2500            # - The AdvA field shall contain the IUT’s Advertising Address
2501            # - If this round used directed advertising, AUX_ADV_IND PDU shall also include the TargetA Extended Header field set to the Lower Tester’s Public Device Address
2502            # - The IUT sends and receives data on the expected PHY selected in step 1
2503            for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
2504                success = success and packet.payload['AdvMode'] == 0b01
2505                success = success and packet.header.TxAdd == 0x00 # AdvA is public
2506                success = success and Address(SimpleAddressType.PUBLIC, packet.payload['AdvA']) == advA
2507                if advEventProperties[round] & 0x04:
2508                    success = success and 'TargetA' in packet.payload and packet.payload['TargetA'] == 0x456789ABCDEF
2509                else:
2510                    success = success and 'TargetA' not in packet.payload
2511                success = success and packet.phy == ('2M' if phy == PhysicalChannel.LE_2M else '1M')
2512
2513            return success
2514
2515        if connectReqAdvA[round] == 0x123456789ABC:
2516            # Round is using AUX_CONNECT_REQ with a matching AdvA
2517
2518            initiator = Initiator(transport, lowerTester, None, trace, Address(ExtendedAddressType.PUBLIC), advA, InitiatorFilterPolicy.FILTER_NONE,
2519                              True, 0x01 if phy == PhysicalChannel.LE_1M else 0x03)
2520            initiator.checkPrematureDisconnect = False
2521            success = initiator.connect()
2522
2523            if not success:
2524                return False
2525
2526            success = success and checkAdvPackets()
2527
2528            if not success:
2529                return False
2530
2531            # Test AUX_CONNECT_RSP: The IUT responds to the AUX_CONNECT_REQ within the 2 μs range around T_IFS
2532            auxConnectReqEndTS = 0
2533            for packet in packets.fetch(packet_filter=('AUX_CONNECT_RSP', 'AUX_CONNECT_REQ')):
2534                if packet.type == PacketType.AUX_CONNECT_REQ:
2535                    # Packet air length is: pre-amble + AA + header + payload + CRC
2536                    packetLength = (2 if packet.phy == '2M' else 1) + 4 + 2 + len(packet) + 3
2537                    auxConnectReqEndTS = packet.ts + 8*packetLength/(2 if packet.phy == '2M' else 1)
2538                else:
2539                    success = success and packet.header.TxAdd == 0x00 # AdvA is public
2540                    success = success and Address(SimpleAddressType.PUBLIC, packet.payload['AdvA']) == advA
2541                    airTimeDiff = packet.ts - auxConnectReqEndTS
2542                    success = success and airTimeDiff >= 150 - 2 and airTimeDiff <= 150 + 2
2543
2544            # Only 20 tries with AUX_CONNECT_REQ allowed, check that we didn't exceed that
2545            connectReqCount = 0
2546            for packet in packets.fetch(packet_filter=('AUX_CONNECT_REQ')):
2547                connectReqCount += 1
2548            success = success and connectReqCount <= 20
2549
2550            # Expect to receive an HCI_LE_Enhanced_Connection_Complete event followed by a HCI_LE_Channel_Selection_Algorithm and a HCI_LE_Advertising_Set_Terminated event
2551            connectionHandle = None
2552            eventsWaiting = has_event(transport, upperTester, 200)[1]
2553            success = success and eventsWaiting >= 2
2554
2555            if not success:
2556                return False
2557
2558            # Consume all outstanding HCI events
2559            for i in range(eventsWaiting):
2560                event = get_event(transport, upperTester, 200)
2561                if i == 0 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_ENH_CONN_COMPLETE:
2562                    status, handle, role, peerAddress, localResolvableAddress, peerResolvableAddress, interval, latency, timeout, accuracy = event.decode()
2563                    success = success and status == 0x00
2564                    success = success and role == 0x01 # Peripheral
2565                    connectionHandle = handle
2566                elif i == 1 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_CHAN_SEL_ALGO:
2567                    handle, algorithm = event.decode()
2568                    success = success and algorithm == 0x01 # LE Channel Selection Algorithm #2
2569                elif i == 2 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_ADV_SET_TERMINATED:
2570                    # The Upper Tester receives an HCI_LE_Advertising_Set_Terminated event from the IUT with the
2571                    # Status set to 0x00, the Advertising_Handle from step 1, and the Connection_Handle from step 8.
2572                    status, advertiseHandle, advConnectionHandle, completedEvents = event.decode()
2573                    success = success and status == 0x00
2574                    success = success and advertiseHandle == Handle
2575                    success = success and advConnectionHandle == connectionHandle
2576                elif i < 3:
2577                    # Unexpected/wrong event received
2578                    success = False
2579
2580            # Keep connection open until we have (at least) 100 LL data PDUs
2581            while True:
2582                LLDataCount = 0
2583                for packet in packets.fetch('LL_DATA_PDU'):
2584                    if packet.idx == upperTester:
2585                        LLDataCount += 1
2586
2587                if LLDataCount >= 100:
2588                    break
2589
2590                # Wait for the expected time to get the remaining packets based on the connection interval
2591                transport.wait(math.ceil((100 - LLDataCount)*(initiator.intervalMax*1.25)))
2592
2593            # Test: The Lower Tester receives no further ADV_EXT_IND PDUs after the advertising interval from the IUT
2594            cutOffTime = packets.find('AUX_CONNECT_RSP').ts + (advInterval * 0.625) * 1000
2595            for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
2596                success = success and packet.ts <= cutOffTime
2597
2598            # Test: The Lower Tester receives a correctly formatted LL Data Channel PDU using the acknowledgement scheme, from the IUT on the same data channel and on the expected PHY
2599            lowerTesterLLData = None
2600            for packet in packets.fetch(packet_filter=('LL_DATA_PDU')):
2601                if packet.direction == 'Tx' and packet.idx == lowerTester:
2602                    lowerTesterLLData = packet
2603                elif packet.direction == 'Tx' and packet.idx == upperTester:
2604                    # LLID should be either 1 (for an empty packet) or 2 (for a non-empty packet)
2605                    if packet.header.Length > 0:
2606                        success = success and packet.header.LLID == 0b10
2607                    else:
2608                        success = success and packet.header.LLID == 0b01
2609                    # Channel should match the lowerTesters packet
2610                    success = success and packet.channel_num == lowerTesterLLData.channel_num
2611                    # SN and NESN should be correct (note: we should never see re-transmissions in this case, since there is no other traffic to collide with)
2612                    success = success and packet.header.SN == lowerTesterLLData.header.SN and packet.header.NESN == (1 if lowerTesterLLData.header.SN == 0 else 0)
2613                    success = success and packet.phy == ('2M' if phy == PhysicalChannel.LE_2M else '1M')
2614
2615            # Disconnect with "Remote User Terminated Connection"
2616            status = disconnect(transport, upperTester, connectionHandle, 0x13, 200)
2617            success = success and (status == 0)
2618
2619            if not success:
2620                return False
2621
2622            # Make sure the disconnect gets handled before starting next round
2623            transport.wait(500)
2624
2625        else:
2626            # Round is using AUX_CONNECT_REQ with a non-matching AdvA - cannot use standard HCI commands for this, use low_level_device instead
2627            auxAdvIndPacket = wait_for_AUX_ADV_IND_end(transport, packets)
2628
2629            # Transmit a AUX_CONNECT_REQ
2630            packetData = (0b0101 + (34 << 8)).to_bytes(2, 'little', signed=False) # header - PDU Type 0b0101, ChSel, TxAdd and RxAdd all 0, length 34
2631            packetData = b''.join([packetData, 0x456789ABCDEF.to_bytes(6, 'little', signed=False)]) # InitA
2632            packetData = b''.join([packetData, connectReqAdvA[round].to_bytes(6, 'little', signed=False)]) # AdvA
2633            packetData = b''.join([packetData, 0xEF11D7A8.to_bytes(4, 'little', signed=False)]) # LLData: AA
2634            packetData = b''.join([packetData, 0xE4C5A3.to_bytes(3, 'little', signed=False)]) # LLData: CRCInit
2635            packetData = b''.join([packetData, 0x01.to_bytes(1, 'little', signed=False)]) # LLData: WinSize
2636            packetData = b''.join([packetData, 0x0000.to_bytes(2, 'little', signed=False)]) # LLData: WinOffset
2637            packetData = b''.join([packetData, 0x0018.to_bytes(2, 'little', signed=False)]) # LLData: Interval
2638            packetData = b''.join([packetData, 0x0000.to_bytes(2, 'little', signed=False)]) # LLData: Latency
2639            packetData = b''.join([packetData, 0x0019.to_bytes(2, 'little', signed=False)]) # LLData: Timeout
2640            packetData = b''.join([packetData, 0x1FFFFFFFFF.to_bytes(5, 'little', signed=False)]) # LLData: ChM
2641            packetData = b''.join([packetData, (0x07 + (0x05 << 5)).to_bytes(1, 'little', signed=False)]) # LLData: Hop and SCA (Hop: 7 and SCA: 5)
2642            CRC = calcBLECRC(0x555555, packetData)
2643            packetData = b''.join([packetData, CRC.to_bytes(3, 'little', signed=False)])
2644
2645            # Calculate transmit timestamp (T_IFS from end of AUX_ADV_IND)
2646            transmitTime = auxAdvIndPacket.ts + get_packet_air_time(auxAdvIndPacket) + 150
2647
2648            transport.low_level_device.tx(channel_num_to_index(auxAdvIndPacket.channel_num), auxAdvIndPacket.phy, auxAdvIndPacket.aa, transmitTime, packetData)
2649
2650            # Wait and check that no AUX_CONNECT_RSP is sent in response
2651            transport.wait(10)
2652
2653            success = success and not packets.find('AUX_CONNECT_RSP')
2654
2655            success = success and checkAdvPackets()
2656
2657            # Stop advertising
2658            success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.DISABLE, [Handle], [0], [0], trace)
2659
2660            if not success:
2661                return False
2662
2663        # Flush any outstanding HCI events
2664        get_event(transport, upperTester, 200, True)
2665        get_event(transport, lowerTester, 200, True)
2666
2667        # Flush packets
2668        packets.flush()
2669
2670    return success
2671
2672"""
2673    LL/CON/ADV/BV-05-C [Extended Advertising, Accepting Connections; LE 1M PHY]
2674"""
2675def ll_con_adv_bv_05_c(transport, upperTester, lowerTester, trace, packets):
2676    return do_ll_con_adv_bv_05_12_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_1M)
2677
2678"""
2679    LL/CON/ADV/BV-06-C [Extended Advertising, Legacy PDUs, Accepting Connections]
2680"""
2681def ll_con_adv_bv_06_c(transport, upperTester, lowerTester, trace, packets):
2682
2683    advInterval = 0x20 # 32 x 0.625 ms = 20.00 ms
2684    Handle          = 0
2685    Properties      = 0b00010011 # ADV_IND legacy PDU
2686    PrimMinInterval = toArray(advInterval, 3)
2687    PrimMaxInterval = toArray(advInterval, 3)
2688    PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
2689    OwnAddrType     = SimpleAddressType.PUBLIC
2690    PeerAddrType    = SimpleAddressType.PUBLIC
2691    PeerAddress     = toArray(0x456789ABCDEF, 6)
2692    FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
2693    TxPower         = 0
2694    PrimAdvPhy      = PhysicalChannel.LE_1M
2695    SecAdvMaxSkip   = 0
2696    SecAdvPhy       = 0
2697    Sid             = 0
2698    ScanReqNotifyEnable = 0
2699
2700    success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
2701                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
2702                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
2703
2704    if not success:
2705        return False
2706
2707    success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0], [0], trace)
2708    if not success:
2709        return False
2710
2711    # Enable LE Channel Selection Algorithm in event mask (it is disabled by default for some reason)
2712    events = [0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00]
2713    status = le_set_event_mask(transport, upperTester, events, 100)
2714    if status != 0:
2715        return False
2716    get_event(transport, upperTester, 200) # Read out command complete event for le_set_event_mask
2717
2718    initiator = Initiator(transport, lowerTester, None, trace, Address(ExtendedAddressType.PUBLIC), publicIdentityAddress(upperTester),
2719                          InitiatorFilterPolicy.FILTER_NONE, True, 0x01)
2720    initiator.checkPrematureDisconnect = False
2721    success = initiator.connect()
2722
2723    if not success:
2724        return False
2725
2726    # Check ADV_INDs
2727    # ChSel set to 1 (Channel Selection Algorithm #2). The AdvA field shall contain the IUT’s Advertising Address
2728    # On the primary advertising channel(s) using the LE 1M PHY
2729    for packet in packets.fetch(packet_filter=('ADV_IND')):
2730        success = success and packet.header.ChSel == 1
2731        success = success and int.from_bytes(packet.payload.AdvA, 'little', signed=False) == 0x123456789ABC
2732        success = success and (packet.channel_num == 0 or packet.channel_num == 12 or packet.channel_num == 39)
2733        success = success and packet.phy == '1M'
2734
2735    if not success:
2736        return False
2737
2738    # Only 20 tries with CONNECT_IND allowed, check that we didn't exceed that
2739    connectIndCount = 0
2740    for packet in packets.fetch(packet_filter=('ADV_IND')):
2741        connectIndCount += 1
2742    success = success and connectIndCount <= 20
2743
2744    # Expect to receive an HCI_LE_Enhanced_Connection_Complete event followed by a HCI_LE_Channel_Selection_Algorithm and a HCI_LE_Advertising_Set_Terminated event
2745    connectionHandle = None
2746    eventsWaiting = has_event(transport, upperTester, 200)[1]
2747    success = success and eventsWaiting >= 2
2748
2749    if not success:
2750        return False
2751
2752    # Consume all outstanding HCI events
2753    for i in range(eventsWaiting):
2754        event = get_event(transport, upperTester, 200)
2755        if i == 0 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_ENH_CONN_COMPLETE:
2756            status, handle, role, peerAddress, localResolvableAddress, peerResolvableAddress, interval, latency, timeout, accuracy = event.decode()
2757            success = success and status == 0x00
2758            success = success and role == 0x01 # Peripheral
2759            connectionHandle = handle
2760        elif i == 1 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_CHAN_SEL_ALGO:
2761            handle, algorithm = event.decode()
2762            success = success and algorithm == 0x01 # LE Channel Selection Algorithm #2
2763        elif i == 2 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_ADV_SET_TERMINATED:
2764            # Status set to 0x00, the Advertising_Handle used, and the Connection_Handle received in HCI_LE_Enhanced_Connection_Complete
2765            status, advertiseHandle, advConnectionHandle, completedEvents = event.decode()
2766            success = success and status == 0x00
2767            success = success and advertiseHandle == Handle
2768            success = success and advConnectionHandle == connectionHandle
2769        elif i < 3:
2770            # Unexpected/wrong event received
2771            success = False
2772
2773    # Keep connection open until we have (at least) 100 LL data PDUs from Lower Tester
2774    while True:
2775        LLDataCount = 0
2776        for packet in packets.fetch('LL_DATA_PDU'):
2777            if packet.idx == lowerTester:
2778                LLDataCount += 1
2779        if LLDataCount >= 100:
2780            break
2781
2782        # Wait for the expected time to get the remaining packets based on the connection interval
2783        transport.wait(math.ceil((100 - LLDataCount)*(initiator.intervalMax*1.25)))
2784
2785    # Check LL_DATA_PDUs
2786    # The IUT sends and receives data using the LE 1M PHY
2787    for packet in packets.fetch(packet_filter=('LL_DATA_PDU')):
2788        success = success and packet.phy == '1M'
2789
2790    # The Lower Tester receives no further advertising packets while maintaining the connection
2791    firstLLDataPDUTs = packets.find('LL_DATA_PDU').ts
2792    lastAdvIndTs = packets.findLast('ADV_IND').ts
2793    success = success and lastAdvIndTs <= firstLLDataPDUTs
2794
2795    # Disconnect with "Remote User Terminated Connection"
2796    status = disconnect(transport, upperTester, connectionHandle, 0x13, 200)
2797    success = success and (status == 0)
2798
2799    # Wait for disconnect to fully complete
2800    transport.wait(500)
2801
2802    # Flush system before the next test steps
2803    packets.flush()
2804    flush_events(transport, lowerTester, 100)
2805    flush_events(transport, upperTester, 100)
2806
2807    # Set advertising parameters and start advertising again
2808    success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
2809                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
2810                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
2811
2812    if not success:
2813        return False
2814
2815    success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0], [0], trace)
2816    if not success:
2817        return False
2818
2819    # Send CONNECT_INDs with the AdvA field set to an address other than the IUT's address 5 times; Advertising should continue
2820    for i in range(5):
2821        advIndPacket = wait_for_ADV_IND_end(transport, packets, math.ceil(advInterval*0.625+10))
2822        if not advIndPacket:
2823            return False
2824
2825        # Transmit a CONNECT_IND
2826        packetData = (0b00100101 + (34 << 8)).to_bytes(2, 'little', signed=False) # header - PDU Type 0b0101, ChSel 1, TxAdd and RxAdd 0, length 34
2827        packetData = b''.join([packetData, 0x456789ABCDEF.to_bytes(6, 'little', signed=False)]) # InitA
2828        packetData = b''.join([packetData, 0xCBA987654321.to_bytes(6, 'little', signed=False)]) # AdvA (not matching IUT)
2829        packetData = b''.join([packetData, 0xEF11D7A8.to_bytes(4, 'little', signed=False)]) # LLData: AA
2830        packetData = b''.join([packetData, 0xE4C5A3.to_bytes(3, 'little', signed=False)]) # LLData: CRCInit
2831        packetData = b''.join([packetData, 0x01.to_bytes(1, 'little', signed=False)]) # LLData: WinSize
2832        packetData = b''.join([packetData, 0x0000.to_bytes(2, 'little', signed=False)]) # LLData: WinOffset
2833        packetData = b''.join([packetData, 0x0018.to_bytes(2, 'little', signed=False)]) # LLData: Interval
2834        packetData = b''.join([packetData, 0x0000.to_bytes(2, 'little', signed=False)]) # LLData: Latency
2835        packetData = b''.join([packetData, 0x0019.to_bytes(2, 'little', signed=False)]) # LLData: Timeout
2836        packetData = b''.join([packetData, 0x1FFFFFFFFF.to_bytes(5, 'little', signed=False)]) # LLData: ChM
2837        packetData = b''.join([packetData, (0x07 + (0x05 << 5)).to_bytes(1, 'little', signed=False)]) # LLData: Hop and SCA (Hop: 7 and SCA: 5)
2838        CRC = calcBLECRC(0x555555, packetData)
2839        packetData = b''.join([packetData, CRC.to_bytes(3, 'little', signed=False)])
2840
2841        # Calculate transmit timestamp (T_IFS from end of ADV_IND)
2842        transmitTime = advIndPacket.ts + get_packet_air_time(advIndPacket) + 150
2843
2844        transport.low_level_device.tx(channel_num_to_index(advIndPacket.channel_num), advIndPacket.phy, advIndPacket.aa, transmitTime, packetData)
2845
2846        # Wait for transmit to happen
2847        transport.wait(10)
2848
2849    # Wait an advertising interval and ensure that advertising is still active
2850    transport.wait(math.ceil(advInterval*0.625+10))
2851
2852    success = success and packets.findLast(packet_filter=('ADV_IND')).ts > transmitTime
2853
2854    return success
2855
2856"""
2857    LL/CON/ADV/BV-09-C [Accepting Connection Request using Channel Selection Algorithm #2]
2858
2859    Last modified: 02-08-2019
2860    Reviewed and verified: 02-08-2019 Henrik Eriksen
2861"""
2862def ll_con_adv_bv_09_c(transport, upperTester, lowerTester, trace):
2863
2864    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
2865    """
2866       Enable the LE Channel Selection Algorithm Event
2867    """
2868    events = [0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00];
2869
2870    success = setLEEventMask(transport, upperTester, events, trace);
2871
2872    success = advertiser.enable() and success;
2873    connected = initiator.connect();
2874    success = success and connected;
2875
2876    if connected:
2877        """
2878            Check for LE Channel Selection Algorithm Event in upper Tester...
2879        """
2880        success, handle, chSelAlgorithm = hasChannelSelectionAlgorithmEvent(transport, upperTester, trace);
2881        success = success and (chSelAlgorithm == 1);
2882
2883        transport.wait(2600);
2884
2885        success = initiator.disconnect(0x13) and success;
2886    else:
2887        success = advertiser.disable() and success;
2888
2889    return success;
2890
2891"""
2892    LL/CON/ADV/BV-10-C [Accepting Connection Request after Directed Advertising using Channel Selection Algorithm #2]
2893
2894    Last modified: 02-08-2019
2895    Reviewed and verified: 02-08-2019 Henrik Eriksen
2896"""
2897def ll_con_adv_bv_10_c(transport, upperTester, lowerTester, trace):
2898
2899    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
2900    """
2901        Enable the LE Channel Selection Algorithm Event
2902    """
2903    events = [0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00];
2904
2905    success = setLEEventMask(transport, upperTester, events, trace);
2906
2907    success = advertiser.enable() and success;
2908    connected = initiator.connect();
2909    success = success and connected;
2910
2911    if connected:
2912        """
2913            Check for LE Channel Selection Algorithm Event in upper Tester...
2914        """
2915        success, handle, chSelAlgorithm = hasChannelSelectionAlgorithmEvent(transport, upperTester, trace);
2916        success = success and (chSelAlgorithm == 1);
2917
2918        transport.wait(2600);
2919
2920        success = initiator.disconnect(0x13) and success;
2921    else:
2922        success = advertiser.disable() and success;
2923
2924    return success;
2925
2926"""
2927    LL/CON/ADV/BV-12-C [Extended Advertising, Accepting Connections; LE 2M PHY]
2928"""
2929def ll_con_adv_bv_12_c(transport, upperTester, lowerTester, trace, packets):
2930    return do_ll_con_adv_bv_05_12_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_2M)
2931
2932# Implements LL/CON/ADV/BV-14-C and LL/CON/ADV/BV-15-C test cases (only difference is the PHY)
2933def do_ll_con_adv_bv_14_15_c(transport, upperTester, lowerTester, trace, packets, phy):
2934    initAddresses = [
2935        0xDEAD42E98020, # random static address
2936        0x2EAD2C3510BF, # random, non-resolvable private address
2937        0x7FD2613EF26C  # random, resolvable private address
2938    ]
2939
2940    success = True
2941
2942    for round in range(len(initAddresses)):
2943        lowerRandomA = initAddresses[round]
2944
2945        Handle          = 0
2946        Properties      = 0x01 # Connectable advertising
2947        PrimMinInterval = toArray(0x0020, 3) # Minimum Advertise Interval = 32 x 0.625 ms = 20.00 ms
2948        PrimMaxInterval = toArray(0x0020, 3) # Maximum Advertise Interval = 32 x 0.625 ms = 20.00 ms
2949        PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
2950        OwnAddrType     = SimpleAddressType.PUBLIC
2951        PeerAddrType    = 0
2952        PeerAddress     = toArray(0, 6)
2953        FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
2954        TxPower         = 0
2955        PrimAdvPhy      = PhysicalChannel.LE_CODED if phy == PhysicalChannel.LE_CODED else PhysicalChannel.LE_1M # Primary advertisement PHY is LE 1M except for coded PHY
2956        SecAdvMaxSkip   = 0     # AUX_ADV_IND shall be sent prior to the next advertising event
2957        SecAdvPhy       = phy
2958        Sid             = 0
2959        ScanReqNotifyEnable = 0; # Scan request notifications disabled
2960
2961        success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
2962                                                          PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
2963                                                          PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
2964
2965        if not success:
2966            return False
2967
2968        success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0], [0], trace)
2969
2970        if not success:
2971            return False
2972
2973        # Enable LE Channel Selection Algorithm in event mask (it is disabled by default for some reason)
2974        events = [0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00]
2975        status = le_set_event_mask(transport, upperTester, events, 100)
2976        if status != 0:
2977            return False
2978        get_event(transport, upperTester, 200) # Read out command complete event for le_set_event_mask
2979
2980        advA = publicIdentityAddress(upperTester)
2981
2982        # Set initiator/lower tester random address
2983        success = preamble_set_random_address(transport, lowerTester, lowerRandomA, trace)
2984
2985        if not success:
2986            return False
2987
2988        initiator = Initiator(transport, lowerTester, None, trace, Address(ExtendedAddressType.RANDOM), advA, InitiatorFilterPolicy.FILTER_NONE,
2989                              True, 0x01 if phy == PhysicalChannel.LE_1M else 0x03)
2990        initiator.checkPrematureDisconnect = False
2991        success = initiator.connect()
2992
2993        if not success:
2994            return False
2995
2996        # Test: The Lower Tester receives an ADV_EXT_IND packet from the IUT with AdvMode set to 01b with only the AuxPtr Extended Header field (and ADI);
2997        #       The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
2998        for packet in packets.fetch(packet_filter=('ADV_EXT_IND')):
2999            success = success and packet.payload['AdvMode'] == 0b01
3000            success = success and 'AdvA' not in packet.payload
3001            success = success and 'TargetA' not in packet.payload
3002            success = success and 'CTEInfo' not in packet.payload
3003            success = success and 'ADI' in packet.payload
3004            success = success and 'AuxPtr' in packet.payload
3005            success = success and 'SyncInfo' not in packet.payload
3006            success = success and 'TxPower' not in packet.payload
3007            success = success and 'ACAD' not in packet.payload
3008            success = success and 'AD' not in packet.payload
3009            success = success and packet.phy == '1M'
3010
3011            offset = packet.payload['AuxPtr'].auxOffset * (30 if packet.payload['AuxPtr'].offsetUnits == 0 else 300)
3012            # Packet air length is: pre-amble + AA + header + payload + CRC
3013            packetLength = 1 + 4 + 2 + len(packet) + 3
3014            packetAirtime = 8*packetLength
3015            success = success and offset >= 300 + packetAirtime
3016
3017        # Test AUX_ADV_IND: AdvMode field set to 01b; The AdvA field shall contain the IUT’s Advertising Address; The IUT sends and receives data on the expected PHY selected in step 1
3018        for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
3019            success = success and packet.payload['AdvMode'] == 0b01
3020            success = success and packet.header.TxAdd == 0x00 # AdvA is public
3021            success = success and Address(SimpleAddressType.PUBLIC, packet.payload['AdvA']) == advA
3022            success = success and packet.phy == ('2M' if phy == PhysicalChannel.LE_2M else '1M')
3023
3024        # Test AUX_CONNECT_RSP: RxAdd = 1 and valid TargetA address; The IUT responds to the AUX_CONNECT_REQ within the 2 μs range around T_IFS
3025        auxConnectReqEndTS = 0
3026        for packet in packets.fetch(packet_filter=('AUX_CONNECT_RSP', 'AUX_CONNECT_REQ')):
3027            if packet.type == PacketType.AUX_CONNECT_REQ:
3028                # Packet air length is: pre-amble + AA + header + payload + CRC
3029                packetLength = (2 if packet.phy == '2M' else 1) + 4 + 2 + len(packet) + 3
3030                auxConnectReqEndTS = packet.ts + 8*packetLength/(2 if packet.phy == '2M' else 1)
3031            else:
3032                success = success and packet.header.RxAdd == 0x01 # TargetA is random
3033                success = success and packet.payload['TargetA'] == lowerRandomA
3034                success = success and packet.header.TxAdd == 0x00 # AdvA is public
3035                success = success and Address(SimpleAddressType.PUBLIC, packet.payload['AdvA']) == advA
3036                airTimeDiff = packet.ts - auxConnectReqEndTS
3037                success = success and airTimeDiff >= 150 - 2 and airTimeDiff <= 150 + 2
3038
3039
3040
3041        # Only 20 tries with AUX_CONNECT_REQ allowed, check that we didn't exceed that
3042        connectReqCount = 0
3043        for packet in packets.fetch(packet_filter=('AUX_CONNECT_REQ')):
3044            connectReqCount += 1
3045        success = success and connectReqCount <= 20
3046
3047        # Expect to receive an HCI_LE_Enhanced_Connection_Complete event followed by a HCI_LE_Channel_Selection_Algorithm
3048        # It is also expected to receive an HCI_LE_Advertising_Set_Terminated event, but this is not to be tested
3049        connectionHandle = None
3050        eventsWaiting = has_event(transport, upperTester, 200)[1]
3051        success = success and eventsWaiting >= 2
3052
3053        if not success:
3054            return False
3055
3056        # Consume all outstanding HCI events
3057        for i in range(eventsWaiting):
3058            event = get_event(transport, upperTester, 200)
3059            if i == 0 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_ENH_CONN_COMPLETE:
3060                # Nothing further to check for this event
3061                connectionHandle = event.decode()[1]
3062            elif i == 1 and event.subEvent == MetaEvents.BT_HCI_EVT_LE_CHAN_SEL_ALGO:
3063                handle, algorithm = event.decode()
3064                success = success and algorithm == 0x01 # LE Channel Selection Algorithm #2
3065            elif i < 2:
3066                # Unexpected/wrong event received
3067                success = False
3068
3069        # At least one LL data PDU should have been exchanged between the two devices
3070        iutLLData = None
3071        lowerTesterLLData = None
3072        for packet in packets.fetch(packet_filter=('LL_DATA_PDU')):
3073            if not lowerTesterLLData and packet.direction == 'Tx' and packet.idx == lowerTester:
3074                # SN and NESN should be 0
3075                success = success and packet.header.SN == 0 and packet.header.NESN == 0
3076                lowerTesterLLData = packet
3077            elif packet.direction == 'Tx' and packet.idx == upperTester:
3078                # LLID should be either 1 (for an empty packet) or 2 (for a non-empty packet)
3079                if packet.header.Length > 0:
3080                    success = success and packet.header.LLID == 0b10
3081                else:
3082                    success = success and packet.header.LLID == 0b01
3083                # Channel should match the lowerTesters packet
3084                success = success and packet.channel_num == lowerTesterLLData.channel_num
3085                # SN should be 0 and NESN 1
3086                success = success and packet.header.SN == 0 and packet.header.NESN == 1
3087                iutLLData = packet
3088            if iutLLData != None and lowerTesterLLData != None:
3089                break
3090
3091        success = success and not (iutLLData == None or lowerTesterLLData == None)
3092
3093        # Disconnect with "Remote User Terminated Connection"
3094        status = disconnect(transport, upperTester, connectionHandle, 0x13, 200)
3095        success = success and (status == 0)
3096
3097        # Make sure the disconnect gets handled before starting next round
3098        transport.wait(500)
3099
3100        # Flush any outstanding HCI events
3101        get_event(transport, upperTester, 200, True)
3102        get_event(transport, lowerTester, 200, True)
3103
3104        # Flush packets
3105        packets.flush()
3106
3107    return success
3108
3109"""
3110    LL/CON/ADV/BV-14-C [Extended Advertising, Accepting Connections with Random address]; LE 1M PHY
3111"""
3112def ll_con_adv_bv_14_c(transport, upperTester, lowerTester, trace, packets):
3113
3114    return do_ll_con_adv_bv_14_15_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_1M)
3115
3116"""
3117    LL/CON/ADV/BV-15-C [Extended Advertising, Accepting Connections with Random address]; LE 2M PHY
3118"""
3119def ll_con_adv_bv_15_c(transport, upperTester, lowerTester, trace, packets):
3120
3121    return do_ll_con_adv_bv_14_15_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_2M)
3122
3123"""
3124    LL/CON/INI/BV-01-C [Connection Initiation rejects Address change]
3125
3126    Last modified: 02-08-2019
3127    Reviewed and verified: 02-08-2019 Henrik Eriksen (NOTE: Timing for connection events not verified - see Air Trace)
3128"""
3129def ll_con_ini_bv_01_c(transport, upperTester, lowerTester, trace):
3130
3131    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
3132
3133    success = True;
3134    for channel in [ AdvertiseChannel.CHANNEL_37, AdvertiseChannel.CHANNEL_38, AdvertiseChannel.CHANNEL_39 ]:
3135
3136        advertiser.channels = channel;
3137
3138        for address in [ 0x456789ABCDEF, address_scramble_OUI(0x456789ABCDEF), address_scramble_LAP(0x456789ABCDEF), address_exchange_OUI_LAP(0x456789ABCDEF) ]:
3139
3140            trace.trace(7, "\nUsing channel %s and Lower Tester address %s\n" % (str(channel), formatAddress(toArray(address, 6))));
3141
3142            success = preamble_set_public_address(transport, lowerTester, address, trace) and success;
3143            initiator.peerAddress = Address( ExtendedAddressType.PUBLIC, address );
3144
3145            success = initiator.preConnect() and success;
3146
3147            randAddress = [ random.randint(0,255) for _ in range(6) ];
3148            randAddress[5] |= 0xC0;
3149            status = le_set_random_address(transport, upperTester, randAddress, 100);
3150            trace.trace(6, "LE Set Random Address Command returns status: 0x%02X" % status);
3151            success = success and (status == 0x0C);
3152            getCommandCompleteEvent(transport, upperTester, trace);
3153
3154            success = advertiser.enable() and success;
3155            connected = initiator.postConnect();
3156            success = success and connected;
3157
3158            if connected:
3159                transport.wait(2660);
3160                success = initiator.disconnect(0x13) and success;
3161            else:
3162                success = advertiser.disable() and success;
3163
3164            if not success:
3165                break;
3166
3167    return success;
3168
3169"""
3170    LL/CON/INI/BV-02-C [Connecting to Advertiser using Directed Advertising Packets]
3171
3172    Last modified: 02-08-2019
3173    Reviewed and verified: 02-08-2019 Henrik Eriksen (NOTE: Timing for connection events not verified - see Air Trace)
3174"""
3175def ll_con_ini_bv_02_c(transport, upperTester, lowerTester, trace):
3176
3177    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
3178
3179    success = advertiser.enable();
3180    connected = initiator.connect();
3181    success = success and connected;
3182
3183    if connected:
3184        transport.wait(2660);
3185        success = initiator.disconnect(0x13) and success;
3186    else:
3187        success = advertiser.disable() and success;
3188
3189    return success;
3190
3191"""
3192    LL/CON/INI/BV-06-C [Filtered Connection to Advertiser using Undirected Advertising Packets]
3193
3194    Last modified: 09-12-2019
3195    Reviewed and verified: 09-12-2019 Henrik Eriksen
3196"""
3197def ll_con_ini_bv_06_c(transport, upperTester, lowerTester, trace):
3198
3199    success = True;
3200    for j in range(2):
3201        if j == 0:
3202            advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
3203                                                       AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.CHANNEL_38, InitiatorFilterPolicy.FILTER_ACCEPT_LIST_ONLY);
3204        else:
3205            advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
3206                                                        ExtendedAddressType.RANDOM, ExtendedAddressType.RANDOM, AdvertisingFilterPolicy.FILTER_NONE, \
3207                                                        AdvertiseChannel.CHANNEL_38, InitiatorFilterPolicy.FILTER_ACCEPT_LIST_ONLY);
3208        """
3209            Place Public|Random address of lowerTester in the Filter Accept List
3210        """
3211        filterAcceptListAddress = publicIdentityAddress(lowerTester) if j == 0 else randomIdentityAddress(lowerTester);
3212
3213        success = addAddressesToFilterAcceptList(transport, upperTester, [ filterAcceptListAddress ], trace) and success;
3214        addresses = [ Address( ExtendedAddressType.RANDOM if filterAcceptListAddress.type == SimpleAddressType.PUBLIC \
3215                                                          else ExtendedAddressType.PUBLIC, filterAcceptListAddress.address ),
3216                      Address( ExtendedAddressType.PUBLIC if filterAcceptListAddress.type == SimpleAddressType.PUBLIC \
3217                                                          else ExtendedAddressType.RANDOM, address_scramble_LAP(toNumber(filterAcceptListAddress.address)) ),
3218                      filterAcceptListAddress ];
3219
3220        for i, advertiserAddress in enumerate( addresses ):
3221
3222            advertiser.ownAddress = advertiserAddress;
3223            if advertiserAddress.type == ExtendedAddressType.RANDOM:
3224                success = preamble_set_random_address(transport, lowerTester, toNumber(advertiserAddress.address), trace) and success;
3225            else:
3226                success = preamble_set_public_address(transport, lowerTester, toNumber(advertiserAddress.address), trace) and success;
3227
3228            success = advertiser.enable() and success;
3229            connected = initiator.connect();
3230            success = (connected if i == 2 else not connected) and success;
3231
3232            if connected:
3233                success = initiator.disconnect(0x13) and success;
3234            else:
3235                """
3236                    Need to stop connection attempt - otherwise following commands will fail with not allowed...
3237                """
3238                success = initiator.cancelConnect() and success;
3239                success = advertiser.disable() and success;
3240
3241            if not success:
3242                break
3243
3244    return success;
3245
3246"""
3247    LL/CON/INI/BV-07-C [Filtered Connection to Advertiser using Directed Advertising Packets]
3248
3249    Last modified: 09-12-2019
3250    Reviewed and verified: 09-12-2019 Henrik Eriksen
3251"""
3252def ll_con_ini_bv_07_c(transport, upperTester, lowerTester, trace):
3253
3254    success = True;
3255    for j in range(2):
3256        if j == 0:
3257            advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED, \
3258                                                       AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.CHANNEL_38, InitiatorFilterPolicy.FILTER_ACCEPT_LIST_ONLY);
3259        else:
3260            advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED, \
3261                                                        ExtendedAddressType.RANDOM, ExtendedAddressType.RANDOM, AdvertisingFilterPolicy.FILTER_NONE, \
3262                                                        AdvertiseChannel.CHANNEL_38, InitiatorFilterPolicy.FILTER_ACCEPT_LIST_ONLY);
3263        """
3264            Place Public|Random address of lowerTester in the Filter Accept List
3265        """
3266        filterAcceptListAddress = publicIdentityAddress(lowerTester) if j == 0 else randomIdentityAddress(lowerTester);
3267
3268        success = addAddressesToFilterAcceptList(transport, upperTester, [ filterAcceptListAddress ], trace) and success;
3269
3270        addresses = [ Address( ExtendedAddressType.RANDOM if filterAcceptListAddress.type == SimpleAddressType.PUBLIC \
3271                                                          else ExtendedAddressType.PUBLIC, filterAcceptListAddress.address ),
3272                      Address( ExtendedAddressType.PUBLIC if filterAcceptListAddress.type == SimpleAddressType.PUBLIC \
3273                                                          else ExtendedAddressType.RANDOM, address_scramble_LAP(toNumber(filterAcceptListAddress.address)) ),
3274                      filterAcceptListAddress ];
3275
3276        for i, advertiserAddress in enumerate( addresses ):
3277
3278            advertiser.ownAddress = advertiserAddress;
3279            if advertiserAddress.type == ExtendedAddressType.RANDOM:
3280                success = preamble_set_random_address(transport, lowerTester, toNumber(advertiserAddress.address), trace) and success;
3281            else:
3282                success = preamble_set_public_address(transport, lowerTester, toNumber(advertiserAddress.address), trace) and success;
3283
3284            success = advertiser.enable() and success;
3285            connected = initiator.connect();
3286            success = (connected if i == 2 else not connected) and success;
3287
3288            if connected:
3289                success = initiator.disconnect(0x13) and success;
3290            else:
3291                """
3292                    Need to stop connection attempt - otherwise following commands will fail with not allowed...
3293                """
3294                success = initiator.cancelConnect() and success;
3295                success = advertiser.disable() and success;
3296
3297    return success;
3298
3299"""
3300    LL/CON/INI/BV-08-C [Connecting to Connectable Undirected Advertiser with Network Privacy]
3301
3302    Last modified: 02-08-2019
3303    Reviewed and verified: 02-08-2019 Henrik Eriksen
3304"""
3305def ll_con_ini_bv_08_c(transport, upperTester, lowerTester, trace):
3306
3307    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
3308                                                ExtendedAddressType.PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
3309                                                AdvertisingFilterPolicy.FILTER_NONE, AdvertiseChannel.CHANNEL_38);
3310    """
3311        Add Public address of lowerTester to the Resolving List
3312    """
3313    RPA = ResolvableAddresses( transport, upperTester, trace, upperIRK );
3314    success = RPA.clear();
3315    success = RPA.add( publicIdentityAddress(lowerTester) ) and success;
3316    """
3317        Set resolvable private address timeout in seconds ( sixty seconds )
3318    """
3319    success = RPA.timeout( 60 ) and success;
3320    success = RPA.enable() and success;
3321
3322    success = advertiser.enable() and success;
3323    connected = initiator.connect();
3324    success = connected and success;
3325
3326    if connected:
3327        transport.wait(2660);
3328        success = initiator.disconnect(0x13) and success;
3329    else:
3330        success = advertiser.disable() and success;
3331
3332    success = RPA.disable() and success;
3333
3334    return success;
3335
3336"""
3337    LL/CON/INI/BV-09-C [Connecting to Connectable Undirected Advertiser with Network Privacy thru Resolving List]
3338
3339    Last modified: 02-08-2019
3340    Reviewed and verified: 02-08-2019 Henrik Eriksen
3341"""
3342def ll_con_ini_bv_09_c(transport, upperTester, lowerTester, trace):
3343
3344    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
3345    """
3346        Add Public address of lowerTester to the Resolving List
3347    """
3348    randIRK = [ random.randint(0,255) for _ in range(16) ];
3349
3350    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, randIRK ) ];
3351    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
3352    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3353    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
3354    """
3355        Set resolvable private address timeout in seconds ( sixty seconds )
3356    """
3357    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
3358    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
3359
3360    success = initiator.preConnect() and success;
3361    success = advertiser.enable() and success;
3362    connected = initiator.postConnect();
3363    success = success and not connected;
3364    if connected:
3365        success = initiator.disconnect(0x13) and success;
3366    else:
3367        success = advertiser.disable() and success;
3368
3369    success = RPAs[lowerTester].clear() and success;
3370    RPAs[lowerTester].localIRK = lowerIRK[ : ];
3371    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
3372
3373    success = advertiser.enable() and success;
3374    connected = initiator.postConnect();
3375    success = success and connected;
3376
3377    if connected:
3378        transport.wait(2660);
3379        success = initiator.disconnect(0x13) and success;
3380    else:
3381        success = advertiser.disable() and success;
3382
3383    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
3384
3385    return success;
3386
3387"""
3388    LL/CON/INI/BV-10-C [Connecting to Directed Advertiser with Network Privacy thru Resolving List]
3389
3390    Last modified: 02-08-2019
3391    Reviewed and verified: 02-08-2019 Henrik Eriksen
3392"""
3393def ll_con_ini_bv_10_c(transport, upperTester, lowerTester, trace):
3394
3395    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
3396    """
3397        Add Public address of lowerTester to the Resolving List
3398    """
3399    randIRK = [ random.randint(0,255) for _ in range(16) ];
3400
3401    RPAs = [ ResolvableAddresses( transport, upperTester, trace ), ResolvableAddresses( transport, lowerTester, trace, randIRK ) ];
3402    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
3403    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3404    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
3405    """
3406        Set resolvable private address timeout in seconds ( sixty seconds )
3407    """
3408    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
3409    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
3410
3411    success = initiator.preConnect() and success;
3412    success = advertiser.enable() and success;
3413    connected = initiator.postConnect();
3414    success = success and not connected;
3415    if connected:
3416        success = initiator.disconnect(0x13) and success;
3417    else:
3418        success = advertiser.disable() and success;
3419
3420    success = RPAs[lowerTester].clear() and success;
3421    RPAs[lowerTester].localIRK = lowerIRK[ : ];
3422    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
3423
3424    success = advertiser.enable() and success;
3425    connected = initiator.postConnect();
3426    success = success and connected;
3427
3428    if connected:
3429        transport.wait(2660);
3430        success = initiator.disconnect(0x13) and success;
3431    else:
3432        success = advertiser.disable() and success;
3433
3434    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
3435
3436    return success;
3437
3438"""
3439    LL/CON/INI/BV-11-C [Connecting to Directed Advertiser using  wrong address with Network Privacy thru Resolving List ]
3440
3441    Last modified: 02-08-2019
3442    Reviewed and verified: 02-08-2019 Henrik Eriksen (NOTE: Cannot confirm that the InitA used in ADV_DIRECT_INT is different from the one used in CONNECT_REQ - see Air trace)
3443"""
3444def ll_con_ini_bv_11_c(transport, upperTester, lowerTester, trace):
3445
3446    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
3447    """
3448        Add Public address of lowerTester to the Resolving List
3449    """
3450    randIRK = [ random.randint(0,255) for _ in range(16) ];
3451
3452    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, randIRK ) ];
3453    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
3454    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3455    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
3456    """
3457        Set resolvable private address timeout in seconds ( three seconds and sixty seconds )
3458    """
3459    success = RPAs[upperTester].timeout( 3 ) and RPAs[lowerTester].timeout( 60 ) and success;
3460    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
3461
3462    success = initiator.preConnect() and success;
3463    success = advertiser.enable() and success;
3464    connected = initiator.postConnect();
3465    success = success and not connected;
3466    if connected:
3467        success = initiator.disconnect(0x13) and success;
3468    else:
3469        success = advertiser.disable() and success;
3470
3471    success = RPAs[lowerTester].clear() and success;
3472    RPAs[lowerTester].localIRK = lowerIRK[ : ];
3473    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
3474
3475    success = advertiser.enable() and success;
3476    connected = initiator.postConnect();
3477    success = success and connected;
3478
3479    if connected:
3480        transport.wait(2660);
3481        success = initiator.disconnect(0x13) and success;
3482    else:
3483        success = advertiser.disable() and success;
3484
3485    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
3486
3487    return success;
3488
3489"""
3490    LL/CON/INI/BV-12-C [Connecting to Directed Advertiser using Identity address with Network Privacy thru Resolving List]
3491
3492    Last modified: 05-08-2019
3493    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Cannot confirm that the InitA used in ADV_DIRECT_INT is different from the one used in CONNECT_REQ - see Air trace)
3494"""
3495def ll_con_ini_bv_12_c(transport, upperTester, lowerTester, trace):
3496
3497    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
3498    """
3499        Add Public address of lowerTester to the Resolving List
3500    """
3501    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
3502    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
3503    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3504    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
3505    """
3506        Set resolvable private address timeout in seconds ( three seconds and sixty seconds )
3507    """
3508    success = RPAs[upperTester].timeout( 3 ) and RPAs[lowerTester].timeout( 60 ) and success;
3509    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
3510
3511    success = initiator.preConnect() and success;
3512    success = advertiser.enable() and success;
3513    connected = initiator.postConnect();
3514    success = success and not connected;
3515    success = advertiser.disable() and success;
3516
3517    success = RPAs[lowerTester].clear() and success;
3518    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
3519
3520    success = advertiser.enable() and success;
3521    connected = initiator.postConnect();
3522    success = success and connected;
3523
3524    if connected:
3525        trace.trace(8, "Initiators local RPA: %s" % formatAddress(initiator.localRPA()));
3526
3527        localRPAs = [ initiator.localRPA()[ : ], [ 0 for _ in range(6) ] ];
3528
3529        transport.wait(2660);
3530        success = initiator.disconnect(0x13) and success;
3531
3532        success = advertiser.enable() and success;
3533        connected = initiator.connect();
3534        success = success and connected;
3535
3536        if connected:
3537            trace.trace(8, "Initiators local RPA: %s" % formatAddress(initiator.localRPA()));
3538
3539            localRPAs[1] = initiator.localRPA()[ : ];
3540
3541            success = initiator.disconnect(0x13) and success;
3542            """
3543                Verify that the Initiator Address (RPA) used in the CONNECT_IND has changed due to RPA timeout...
3544            """
3545            success = success and localRPAs[0] != localRPAs[1];
3546        else:
3547            success = advertiser.disable() and success;
3548    else:
3549        success = advertiser.disable() and success;
3550
3551    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
3552
3553    return success;
3554
3555"""
3556    LL/CON/INI/BV-16-C [Connecting to Advertiser with Channel Selection Algorithm #2]
3557
3558    Last modified: 05-08-2019
3559    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing requirements cannot be verified - see Air trace)
3560"""
3561def ll_con_ini_bv_16_c(transport, upperTester, lowerTester, trace):
3562
3563    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
3564    """
3565       Enable the LE Channel Selection Algorithm Event
3566    """
3567    events = [0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00];
3568    success = setLEEventMask(transport, upperTester, events, trace);
3569
3570    success = advertiser.enable() and success;
3571    initiator.checkPrematureDisconnect = False;
3572    connected = initiator.connect();
3573    success = success and connected;
3574
3575    if connected:
3576        """
3577            Check for LE Channel Selection Algorithm Event in upper Tester...
3578        """
3579        ok, handle, chSelAlgorithm = hasChannelSelectionAlgorithmEvent(transport, upperTester, trace);
3580        success = success and ok and (chSelAlgorithm == 1);
3581
3582        transport.wait(2840);
3583
3584        success = initiator.disconnect(0x13) and success;
3585    else:
3586        success = advertiser.disable() and success;
3587
3588    return success;
3589
3590"""
3591    LL/CON/INI/BV-17-C [Connecting to Directed Advertiser with Channel Selection Algorithm #2]
3592
3593    Last modified: 05-08-2019
3594    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing requirements cannot be verified - see Air trace)
3595"""
3596def ll_con_ini_bv_17_c(transport, upperTester, lowerTester, trace):
3597
3598    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
3599    """
3600       Enable the LE Channel Selection Algorithm Event
3601    """
3602    events = [0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00];
3603    success = setLEEventMask(transport, upperTester, events, trace);
3604
3605    success = advertiser.enable() and success;
3606    initiator.checkPrematureDisconnect = False;
3607    connected = initiator.connect();
3608    success = success and connected;
3609
3610    if connected:
3611        """
3612            Check for LE Channel Selection Algorithm Event in upper Tester...
3613        """
3614        ok, handle, chSelAlgorithm = hasChannelSelectionAlgorithmEvent(transport, upperTester, trace);
3615        success = success and ok and (chSelAlgorithm == 1);
3616
3617        transport.wait(2840);
3618
3619        success = initiator.disconnect(0x13) and success;
3620    else:
3621        success = advertiser.disable() and success;
3622
3623    return success;
3624
3625"""
3626    LL/CON/INI/BV-18-C [Don't connect to Advertiser using Identity address with Network Privacy thru Resolving List]
3627
3628    Last modified: 05-08-2019
3629    Reviewed and verified: 05-08-2019 Henrik Eriksen
3630"""
3631def ll_con_ini_bv_18_c(transport, upperTester, lowerTester, trace):
3632
3633    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, ExtendedAddressType.PUBLIC);
3634    """
3635        Add Public address of lowerTester to the Resolving List
3636    """
3637    RPA = ResolvableAddresses( transport, upperTester, trace, upperIRK );
3638    success = RPA.clear();
3639    success = RPA.add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3640    """
3641        Set resolvable private address timeout in seconds ( sixty seconds )
3642    """
3643    success = RPA.timeout( 60 ) and success;
3644    success = RPA.enable() and success;
3645
3646    success = success and advertiser.enable();
3647    connected = initiator.connect();
3648    success = success and not connected;
3649
3650    if connected:
3651        success = initiator.disconnect(0x13) and success;
3652    else:
3653        success = initiator.cancelConnect();
3654        success = advertiser.disable() and success;
3655
3656    success = RPA.disable() and success;
3657
3658    return success;
3659
3660"""
3661    LL/CON/INI/BV-19-C [Don't connect to Directed Advertiser using Identity address with Network Privacy thru Resolving List]
3662
3663    Last modified: 05-08-2019
3664    Reviewed and verified: 05-08-2019 Henrik Eriksen
3665"""
3666def ll_con_ini_bv_19_c(transport, upperTester, lowerTester, trace):
3667
3668    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
3669    """
3670        Add Public address of lowerTester to the Resolving List
3671    """
3672    RPA = ResolvableAddresses( transport, upperTester, trace );
3673    success = RPA.clear();
3674    success = RPA.add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3675    """
3676        Set resolvable private address timeout in seconds ( sixty seconds )
3677    """
3678    success = RPA.timeout( 60 ) and success;
3679    success = RPA.enable() and success;
3680
3681    success = success and advertiser.enable();
3682    connected = initiator.connect();
3683    success = success and not connected;
3684
3685    if connected:
3686        success = initiator.disconnect(0x13) and success;
3687    else:
3688        success = initiator.cancelConnect();
3689        success = advertiser.disable() and success;
3690
3691    success = RPA.disable() and success;
3692
3693    return success;
3694
3695"""
3696    LL/CON/INI/BV-20-C [Connect to Advertiser using Identity address with Device Privacy thru Resolving List]
3697
3698    Last modified: 05-08-2019
3699    Reviewed and verified: 05-08-2019 Henrik Eriksen
3700"""
3701def ll_con_ini_bv_20_c(transport, upperTester, lowerTester, trace):
3702
3703    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
3704    """
3705        Add Public address of lowerTester to the Resolving List
3706    """
3707    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace ) ];
3708    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
3709    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3710    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
3711    """
3712        Set resolvable private address timeout in seconds ( sixty seconds )
3713    """
3714    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
3715    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
3716    """
3717        Set Privacy Mode
3718    """
3719    success = setPrivacyMode(transport, upperTester, publicIdentityAddress(lowerTester), PrivacyMode.DEVICE_PRIVACY, trace) and success;
3720
3721    success = success and advertiser.enable();
3722    connected = initiator.connect();
3723    success = success and connected;
3724
3725    if connected:
3726        transport.wait(2660);
3727
3728        success = initiator.disconnect(0x13) and success;
3729    else:
3730        success = advertiser.disable() and success;
3731
3732    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
3733
3734    return success;
3735
3736"""
3737    LL/CON/INI/BV-21-C [Connect to Directed Advertiser using Identity address with Device Privacy thru Resolving List]
3738
3739    Last modified: 05-08-2019
3740    Reviewed and verified: 05-08-2019 Henrik Eriksen
3741"""
3742def ll_con_ini_bv_21_c(transport, upperTester, lowerTester, trace):
3743
3744    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_LDC_DIRECTED);
3745    """
3746        Add Public address of lowerTester to the Resolving List
3747    """
3748    RPA = ResolvableAddresses( transport, upperTester, trace );
3749    success = RPA.clear();
3750    success = RPA.add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3751    """
3752        Set resolvable private address timeout in seconds ( sixty seconds )
3753    """
3754    success = RPA.timeout( 60 ) and success;
3755    success = RPA.enable() and success;
3756    """
3757        Set Privacy Mode
3758    """
3759    success = setPrivacyMode(transport, upperTester, publicIdentityAddress(lowerTester), PrivacyMode.DEVICE_PRIVACY, trace) and success;
3760
3761    success = success and advertiser.enable();
3762    connected = initiator.connect();
3763    success = success and connected;
3764
3765    if connected:
3766        transport.wait(2660);
3767
3768        success = initiator.disconnect(0x13) and success;
3769    else:
3770        success = advertiser.disable() and success;
3771
3772    success = RPA.disable() and success;
3773
3774    return success;
3775
3776"""
3777    LL/CON/INI/BV-23-C [Network Privacy - Connection Establishment using filterallowlist and resolving list with address resolution disabled]
3778
3779    Last modified: 17-12-2019
3780    Reviewed and verified: 17-12-2019 Henrik Eriksen
3781"""
3782def ll_con_ini_bv_23_c(transport, upperTester, lowerTester, trace):
3783
3784    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, ExtendedAddressType.PUBLIC,
3785                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, AdvertisingFilterPolicy.FILTER_NONE,
3786                                                AdvertiseChannel.ALL_CHANNELS, InitiatorFilterPolicy.FILTER_ACCEPT_LIST_ONLY);
3787    """
3788        Add Public address of lowerTester to the Resolving List
3789    """
3790    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace ) ];
3791    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
3792    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester) ) and success;
3793    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
3794    """
3795        Add two more entries not equal to lower tester with different local IRK for each entry
3796    """
3797    extraAddressses = [ Address( SimpleAddressType.PUBLIC, address_scramble_OUI(toNumber(publicIdentityAddress(lowerTester).address)) ),
3798                        Address( SimpleAddressType.PUBLIC, address_scramble_LAP(toNumber(publicIdentityAddress(lowerTester).address)) ) ];
3799    RPAs[upperTester].localIRK = [ random.randint(0,255) for _ in range(16) ];
3800    success = RPAs[upperTester].add( extraAddressses[0] ) and success;
3801    RPAs[upperTester].localIRK = [ random.randint(0,255) for _ in range(16) ];
3802    success = RPAs[upperTester].add( extraAddressses[1] ) and success;
3803    """
3804        Set resolvable private address timeout in seconds ( sixty seconds )
3805    """
3806    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
3807    success = RPAs[lowerTester].enable() and success;
3808    """
3809        Add Lower tester identity address to plus two more to Filter Accept List
3810    """
3811    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester), extraAddressses[0], extraAddressses[1] ], trace);
3812
3813    success = success and advertiser.enable();
3814    connected = initiator.connect();
3815    success = success and connected;
3816
3817    if connected:
3818        transport.wait(200);
3819        """
3820            Check that the InitA from the connect indication is a RPA
3821        """
3822        success = Address( None, initiator.localRPA() ).isResolvablePrivate() and success;
3823        success = initiator.disconnect(0x13) and success;
3824    else:
3825        success = advertiser.disable() and success;
3826
3827    success = RPAs[lowerTester].disable() and success;
3828
3829    return success;
3830
3831"""
3832    LL/CON/INI/BV-24-C [Network Privacy - Connection Establishment using resolving list with address resolution disabled]
3833
3834    Last modified: 17-12-2019
3835    Reviewed and verified: 17-12-2019 Henrik Eriksen
3836"""
3837def ll_con_ini_bv_24_c(transport, upperTester, lowerTester, trace):
3838
3839    advertiser, initiator = setPrivateInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, ExtendedAddressType.PUBLIC);
3840    """
3841        Add Public address of lowerTester to the Resolving List
3842    """
3843    RPA = ResolvableAddresses( transport, upperTester, trace, upperIRK );
3844    success = RPA.clear();
3845    success = RPA.add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
3846    """
3847        Set resolvable private address timeout in seconds ( sixty seconds )
3848    """
3849    success = RPA.timeout( 60 ) and success;
3850    success = RPA.disable() and success;
3851
3852    success = success and advertiser.enable();
3853    connected = initiator.connect();
3854    success = success and not connected;
3855
3856    if connected:
3857        success = initiator.disconnect(0x13) and success;
3858    else:
3859        success = initiator.cancelConnect();
3860        success = advertiser.disable() and success;
3861
3862    return success;
3863
3864"""
3865    LL/CON/PER/BV-04-C [Connection where Peripheral sends data to Central]
3866
3867    Last modified: 05-08-2019
3868    Reviewed and verified: 05-08-2019 Henrik Eriksen
3869"""
3870def ll_con_per_bv_04_c(transport, upperTester, lowerTester, trace):
3871
3872    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
3873    """
3874        Obtain maximum Data Packet size and maximum number of Data Packets
3875    """
3876    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, upperTester, trace);
3877
3878    success = advertiser.enable() and success;
3879    connected = initiator.connect();
3880    success = success and connected;
3881
3882    if connected:
3883        txData = [0 for _ in range(10)];
3884        pbFlags = 1;
3885        """
3886            Sending Data Packets with a fixed length less than 27...
3887        """
3888        for count in [ 100, 100, 1, 99 ]:
3889            pbFlags ^= 1;
3890            for j in range(count):
3891
3892                dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
3893                success = success and dataSent;
3894                if dataSent:
3895                    dataReceived, rxData = readData(transport, lowerTester, trace);
3896                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
3897
3898        if maxPacketLength > 27:
3899            """
3900                Sending Data Packets with a random length greater than 27...
3901            """
3902            pbFlags, count = 0, 0;
3903
3904            while count < 1000:
3905                txData = [0 for _ in range(random.randint(28, maxPacketLength))];
3906
3907                dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
3908                success = success and dataSent;
3909                if dataSent:
3910                    dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
3911                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
3912
3913                count += len(txData);
3914
3915        success = initiator.disconnect(0x13) and success;
3916    else:
3917        success = advertiser.disable() and success;
3918
3919    return success;
3920
3921"""
3922    LL/CON/PER/BV-05-C [Connection where Peripheral receives data from Central]
3923
3924    Last modified: 05-08-2019
3925    Reviewed and verified: 05-08-2019 Henrik Eriksen
3926"""
3927def ll_con_per_bv_05_c(transport, upperTester, lowerTester, trace):
3928
3929    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
3930
3931    success = advertiser.enable();
3932    connected = initiator.connect();
3933    success = success and connected;
3934
3935    if connected:
3936        txData = [0 for _ in range(10)];
3937        pbFlags = 1;
3938        """
3939            Sending Data Packets with a fixed length less than 27...
3940        """
3941        for count in [ 100, 100, 1, 99 ]:
3942            pbFlags ^= 1;
3943            trace.trace(7, '-'*77);
3944            for j in range(count):
3945                dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
3946                success = success and dataSent;
3947                if dataSent:
3948                    dataReceived, rxData = readData(transport, upperTester, trace);
3949                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
3950        trace.trace(7, '-'*77);
3951
3952        success = initiator.disconnect(0x13) and success;
3953    else:
3954        success = advertiser.disable() and success;
3955
3956    return success;
3957
3958"""
3959    LL/CON/PER/BV-06-C [Connection where Peripheral sends and receives data to and from Central]
3960
3961    Last modified: 05-08-2019
3962    Reviewed and verified: 05-08-2019 Henrik Eriksen
3963"""
3964def ll_con_per_bv_06_c(transport, upperTester, lowerTester, trace):
3965
3966    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
3967
3968    success = advertiser.enable();
3969    connected = initiator.connect();
3970    success = success and connected;
3971
3972    if connected:
3973        txData = [0 for _ in range(10)];
3974        pbFlags = 0;
3975        """
3976            Sending Data Packets with a fixed length less than 27...
3977        """
3978        for j in range(100):
3979            """
3980                Upper Tester is sending Data...
3981            """
3982            pbFlags ^= 1;
3983            trace.trace(7, '-'*77);
3984            dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
3985            success = success and dataSent;
3986            if dataSent:
3987                dataReceived, rxData = readData(transport, lowerTester, trace);
3988                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
3989            """
3990                Lower Tester is sending Data...
3991            """
3992            pbFlags ^= 1;
3993            dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
3994            success = success and dataSent;
3995            if dataSent:
3996                dataReceived, rxData = readData(transport, upperTester, trace);
3997                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
3998        trace.trace(7, '-'*77);
3999
4000        success = initiator.disconnect(0x13) and success;
4001    else:
4002        success = advertiser.disable() and success;
4003
4004    return success;
4005
4006"""
4007    LL/CON/PER/BV-10-C [Peripheral accepting Connection Parameter Update from Central]
4008
4009    Last modified: 05-08-2019
4010    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing cannot be verified - see Air trace)
4011"""
4012def ll_con_per_bv_10_c(transport, upperTester, lowerTester, trace):
4013
4014    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4015
4016    success = advertiser.enable();
4017    connected = initiator.connect();
4018    success = success and connected;
4019
4020    if connected:
4021        transport.wait(100);
4022
4023        for interval, timeout in zip([ 6, 3200, 6 ], [ 300, 3200, 300 ]):
4024            """
4025                Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
4026            """
4027            success = initiator.update(interval, interval, initiator.latency, timeout) and success;
4028            """
4029                Accept the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP...
4030            """
4031            success = initiator.acceptUpdate() and success;
4032            """
4033                Both lower and upper Tester should receive a LE Connection Update Complete Event...
4034            """
4035            success = initiator.updated() and success;
4036
4037            transport.wait(int(4 * interval * 1.25));
4038
4039        success = initiator.disconnect(0x13) and success;
4040    else:
4041        success = advertiser.disable() and success;
4042
4043    return success;
4044
4045"""
4046    LL/CON/PER/BV-11-C [Peripheral sending Termination to Central]
4047
4048    Last modified: 05-08-2019
4049    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing cannot be verified - see Air trace)
4050"""
4051def ll_con_per_bv_11_c(transport, upperTester, lowerTester, trace):
4052
4053    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4054
4055    success = advertiser.enable();
4056    connected = initiator.connect();
4057    success = success and connected;
4058
4059    if connected:
4060        initiator.switchRoles();
4061        success = initiator.disconnect(0x13) and (initiator.reasons[0] == 0x16) and (initiator.reasons[1] == 0x13) and success;
4062        initiator.resetRoles();
4063    else:
4064        success = advertiser.disable() and success;
4065
4066    return success;
4067
4068"""
4069    LL/CON/PER/BV-12-C [Peripheral accepting Termination from Central]
4070
4071    Last modified: 05-08-2019
4072    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing cannot be verified - see Air trace)
4073"""
4074def ll_con_per_bv_12_c(transport, upperTester, lowerTester, trace):
4075
4076    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4077
4078    success = advertiser.enable();
4079    connected = initiator.connect();
4080    success = success and connected;
4081
4082    if connected:
4083        success = initiator.disconnect(0x13) and (initiator.reasons[0] == 0x16) and (initiator.reasons[1] == 0x13) and success;
4084    else:
4085        success = advertiser.disable() and success;
4086
4087    return success;
4088
4089"""
4090    LL/CON/PER/BV-13-C [Peripheral Terminating Connection on Supervision Timer]
4091"""
4092def ll_con_per_bv_13_c(transport, upperTester, lowerTester, trace):
4093
4094    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4095
4096    success = advertiser.enable();
4097    initiator.supervisionTimer = 3200;
4098    connected = initiator.connect();
4099    success = success and connected;
4100
4101    if connected:
4102        transport.wait(3200);
4103        hasEvent = has_event(transport, upperTester, 3200)[0];
4104        success = success and hasEvent;
4105        if hasEvent:
4106            event = get_event(transport, upperTester, 100);
4107            trace.trace(7, str(event));
4108        else:
4109            success = initiator.disconnect(0x13) and success;
4110    else:
4111        success = advertiser.disable() and success;
4112
4113    return success;
4114
4115"""
4116    LL/CON/PER/BV-14-C [Peripheral performs Feature Setup procedure]
4117
4118    Last modified: 05-08-2019
4119    Reviewed and verified: 05-08-2019 Henrik Eriksen
4120"""
4121def ll_con_per_bv_14_c(transport, upperTester, lowerTester, trace):
4122
4123    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4124
4125    success = advertiser.enable();
4126    connected = initiator.connect();
4127    success = success and connected;
4128
4129    if connected:
4130        """
4131            Send LL_FEATURE_REQ to IUT
4132        """
4133        success = readRemoteFeatures(transport, lowerTester, initiator.handles[0], trace) and success;
4134        """
4135            Verify if lower tester received LE Read Remote Features Complete Event
4136        """
4137        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, lowerTester, trace);
4138        success = hasFeatures and success;
4139        if hasFeatures:
4140            showFeatures(features, trace);
4141
4142        success = initiator.disconnect(0x13) and success;
4143    else:
4144        success = advertiser.disable() and success;
4145
4146    return success;
4147
4148"""
4149    LL/CON/PER/BV-19-C [Peripheral requests Version Exchange procedure]
4150
4151    Last modified: 05-08-2019
4152    Reviewed and verified: 05-08-2019 Henrik Eriksen
4153"""
4154def ll_con_per_bv_19_c(transport, upperTester, lowerTester, trace):
4155
4156    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4157
4158    success = advertiser.enable();
4159    connected = initiator.connect();
4160    success = success and connected;
4161
4162    if connected:
4163        success = readRemoteVersionInformation(transport, upperTester, initiator.handles[1], trace) and success;
4164
4165        hasVersion, handle, version, manufacturer, subVersion = hasReadRemoteVersionInformationCompleteEvent(transport, upperTester, trace);
4166        success = success and hasVersion;
4167        if hasVersion:
4168            trace.trace(8, "     version: 0x%02x" % version);
4169            trace.trace(8, " sub-version: 0x%04x" % subVersion);
4170            trace.trace(8, "manufacturer: 0x%04x" % manufacturer);
4171
4172        success = initiator.disconnect(0x13) and success;
4173    else:
4174        success = advertiser.disable() and success;
4175
4176    return success;
4177
4178"""
4179    LL/CON/PER/BV-20-C [Peripheral responds to Version Exchange procedure]
4180
4181    Last modified: 05-08-2019
4182    Reviewed and verified: 05-08-2019 Henrik Eriksen
4183"""
4184def ll_con_per_bv_20_c(transport, upperTester, lowerTester, trace):
4185
4186    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4187
4188    success = advertiser.enable();
4189    connected = initiator.connect();
4190    success = success and connected;
4191
4192    if connected:
4193        success = readRemoteVersionInformation(transport, lowerTester, initiator.handles[0], trace) and success;
4194
4195        hasVersion, handle, version, manufacturer, subVersion = hasReadRemoteVersionInformationCompleteEvent(transport, lowerTester, trace);
4196        success = success and hasVersion;
4197        if hasVersion:
4198            trace.trace(8, "     version: 0x%02x" % version);
4199            trace.trace(8, " sub-version: 0x%04x" % subVersion);
4200            trace.trace(8, "manufacturer: 0x%04x" % manufacturer);
4201
4202        success = initiator.disconnect(0x13) and success;
4203    else:
4204        success = advertiser.disable() and success;
4205
4206    return success;
4207
4208"""
4209    LL/CON/PER/BV-22-C [Peripheral requests Feature Exchange procedure]
4210
4211    Last modified: 05-08-2019
4212    Reviewed and verified: 05-08-2019 Henrik Eriksen
4213"""
4214def ll_con_per_bv_22_c(transport, upperTester, lowerTester, trace):
4215
4216    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4217
4218    success = advertiser.enable();
4219    connected = initiator.connect();
4220    success = success and connected;
4221
4222    if connected:
4223        """
4224            Upper Tester sends an HCI_LE_Read_Local_Supported_Features command...
4225        """
4226        success = readLocalFeatures(transport, upperTester, trace)[0] and success;
4227        """
4228            Upper Tester sends an HCI_LE_Read_Remote_Features command...
4229        """
4230        success = readRemoteFeatures(transport, upperTester, initiator.handles[0], trace) and success;
4231        """
4232            Upper tester expects LE Read Remote Features Complete event...
4233        """
4234        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, upperTester, trace);
4235        success = hasFeatures and success;
4236        if hasFeatures:
4237            showFeatures(features, trace);
4238
4239        success = initiator.disconnect(0x13) and success;
4240    else:
4241        success = advertiser.disable() and success;
4242
4243    return success;
4244
4245"""
4246    LL/CON/PER/BV-24-C [Peripheral requests Connection Parameters - Central Accepts]
4247
4248    Last modified: 05-08-2019
4249    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing not verified - see Air trace)
4250"""
4251def ll_con_per_bv_24_c(transport, upperTester, lowerTester, trace):
4252
4253    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4254
4255    success = advertiser.enable();
4256    connected = initiator.connect();
4257    success = success and connected;
4258
4259    if connected:
4260        initiator.switchRoles();
4261        """
4262            The test consists of 3 cases for specific connection intervals and supervision timeouts
4263        """
4264        for interval, timeout in zip([ 6, 3200, 6 ], [ 300, 3200, 300 ]):
4265            """
4266                Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
4267            """
4268            success = initiator.update(interval, interval, initiator.latency, timeout) and success;
4269            """
4270                Accept the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP...
4271            """
4272            success = initiator.acceptUpdate() and success;
4273            """
4274                Both lower and upper Tester should receive a LE Connection Update Complete Event...
4275            """
4276            success = initiator.updated() and success;
4277
4278            transport.wait(int(4 * interval * 1.25));
4279
4280        initiator.resetRoles();
4281        success = initiator.disconnect(0x13) and success;
4282    else:
4283        success = advertiser.disable() and success;
4284
4285    return success;
4286
4287"""
4288    LL/CON/PER/BV-25-C [Peripheral requests Connection Parameters - Central Rejects]
4289
4290    Last modified: 05-08-2019
4291    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing not verified - see Air trace)
4292"""
4293def ll_con_per_bv_25_c(transport, upperTester, lowerTester, trace):
4294
4295    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4296
4297    success = advertiser.enable();
4298    connected = initiator.connect();
4299    success = success and connected;
4300
4301    if connected:
4302        initiator.switchRoles();
4303
4304        interval, timeout = 6, 300;
4305        """
4306            Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
4307        """
4308        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
4309        """
4310            Reject the LE Remote Connection Parameter Request Event by issuing a LL_REJECTEXT_IND...
4311        """
4312        success = initiator.rejectUpdate(0x0C) and success;
4313        """
4314            Both lower and upper Tester should receive a LE Connection Update Complete Event... if request was accepted
4315        """
4316        success = not initiator.updated() and initiator.status == 0x0C and success;
4317
4318        transport.wait(int(4 * interval * 1.25));
4319
4320        initiator.resetRoles();
4321        success = initiator.disconnect(0x13) and success;
4322    else:
4323        success = advertiser.disable() and success;
4324
4325    return success;
4326
4327"""
4328    LL/CON/PER/BV-26-C [Peripheral requests Connection Parameters - same procedure collision]
4329
4330    Last modified: 05-08-2019
4331    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing not verified - see Air trace)
4332"""
4333def ll_con_per_bv_26_c(transport, upperTester, lowerTester, trace):
4334
4335    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4336
4337    success = advertiser.enable();
4338    connected = initiator.connect();
4339    success = success and connected;
4340
4341    if connected:
4342        initiator.switchRoles();
4343
4344        interval, timeout, errCode = 6, 300, 0x23;
4345        """
4346            Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
4347        """
4348        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
4349        """
4350            Reject the LE Remote Connection Parameter Request Event by issuing a LL_REJECTEXT_IND...
4351            NOTE: Not according to test specification, LL_CONNECTION_PARAM_REQ should be issued prior to LL_REJECTEXT_IND,
4352                  but Zephyr is preventing us from sending the the LL_CONNECTION_PARAM_REQ first, returning COMMAND DISALLOWED
4353        """
4354        success = initiator.rejectUpdate(errCode) and success;
4355
4356        initiator.resetRoles();
4357        """
4358            Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
4359        """
4360        updInitiatorRequest = initiator.update(interval, interval, initiator.latency, timeout);
4361        updPeerRequest = initiator.updPeerRequest;
4362        success = success and updInitiatorRequest and updPeerRequest;
4363
4364        initiator.switchRoles();
4365        """
4366            Both lower and upper Tester should receive a LE Connection Update Complete Event... if request was accepted
4367        """
4368        updated = initiator.updated();
4369        success = success and not updated and (initiator.status == errCode);
4370
4371        initiator.resetRoles();
4372        """
4373            Accept the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP...
4374        """
4375        initiator.updInitiatorRequest, initiator.updPeerRequest = updInitiatorRequest, updPeerRequest;
4376        success = initiator.acceptUpdate() and success;
4377        """
4378            Both lower and upper Tester should receive a LE Connection Update Complete Event...
4379        """
4380        success = initiator.updated() and success;
4381
4382        transport.wait(int(4 * interval * 1.25));
4383
4384        success = initiator.disconnect(0x13) and success;
4385    else:
4386        success = advertiser.disable() and success;
4387
4388    return success;
4389
4390"""
4391    LL/CON/PER/BV-27-C [Peripheral requests Connection Parameters - channel map update procedure collision]
4392
4393    Last modified: 05-08-2019
4394    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing not verified - see Air trace)
4395"""
4396def ll_con_per_bv_27_c(transport, upperTester, lowerTester, trace):
4397
4398    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4399
4400    success = advertiser.enable();
4401    connected = initiator.connect();
4402    success = success and connected;
4403
4404    if connected:
4405        initiator.switchRoles();
4406
4407        interval, timeout, errCode, channelMap = 6, 300, 0x2A, 0x1555555555;
4408        """
4409            Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
4410        """
4411        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
4412        """
4413            Request an update of used channels - sends an LL_CHANNEL_MAP_IND...
4414        """
4415        success = channelMapUpdate(transport, lowerTester, channelMap, trace) and success;
4416        """
4417            Reject the LE Remote Connection Parameter Request Event by issuing a LL_REJECTEXT_IND...
4418        """
4419        success = initiator.rejectUpdate(errCode) and success;
4420        """
4421            Both lower and upper Tester should receive a LE Connection Update Complete Event... if request was accepted
4422        """
4423        success = not initiator.updated() and (initiator.status == errCode) and success;
4424
4425        initiator.resetRoles();
4426
4427        transport.wait(int(4 * interval * 1.25));
4428
4429        success = initiator.disconnect(0x13) and success;
4430    else:
4431        success = advertiser.disable() and success;
4432
4433    return success;
4434
4435"""
4436    LL/CON/PER/BV-29-C [Peripheral responds to Connection Parameters - Central no Preferred Periodicity]
4437
4438    Last modified: 05-08-2019
4439    Reviewed and verified: 05-08-2019 Henrik Eriksen (NOTE: Timing not verified - see Air trace)
4440"""
4441def ll_con_per_bv_29_c(transport, upperTester, lowerTester, trace):
4442
4443    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4444
4445    success = advertiser.enable();
4446    connected = initiator.connect();
4447    success = success and connected;
4448
4449    if connected:
4450        for interval, timeout in zip([6, 3200, 6], [300, 3200, 200]):
4451            """
4452                Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
4453            """
4454            success = initiator.update(interval, interval, initiator.latency, timeout) and success;
4455            """
4456                Accept the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP...
4457            """
4458            success = initiator.acceptUpdate() and success;
4459            """
4460                Both lower and upper Tester should receive a LE Connection Update Complete Event... if request was accepted
4461            """
4462            success = initiator.updated() and success;
4463
4464            transport.wait(int(4 * interval * 1.25));
4465
4466        success = initiator.disconnect(0x13) and success;
4467    else:
4468        success = advertiser.disable() and success;
4469
4470    return success;
4471
4472"""
4473    LL/CON/PER/BV-33-C [Peripheral responds to Connection Parameters request - event masked]
4474
4475    Last modified: 05-08-2019
4476    Reviewed and verified: 05-08-2019 Henrik Eriksen
4477"""
4478def ll_con_per_bv_33_c(transport, upperTester, lowerTester, trace):
4479
4480    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4481
4482    success = advertiser.enable();
4483    connected = initiator.connect();
4484    success = success and connected;
4485    """
4486        Mask LE Remote Connection Parameter Request Event
4487    """
4488    events = [0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
4489    success = setLEEventMask(transport, upperTester, events, trace) and success;
4490
4491    if connected:
4492        interval, timeout, errCode = 6, 300, 0x1A;
4493        """
4494            Send LL_CONNECTION_PARAM_REQ to IUT...
4495        """
4496        success = initiator.update(interval, interval, initiator.latency, timeout) and not initiator.updPeerRequest and success;
4497        """
4498            Verify that lower tester receives a LL_REJECT_EXT_IND... unfortunately we cannot verify that (but it appears in the Air trace)!
4499        """
4500        success = initiator.updated() and success;
4501
4502        transport.wait(int(4 * interval * 1.25))
4503
4504        success = initiator.disconnect(0x13) and success;
4505    else:
4506        success = advertiser.disable() and success;
4507
4508    return success;
4509
4510"""
4511    LL/CON/PER/BV-34-C [Peripheral responds to Connection Parameters request - Host rejects]
4512
4513    Last modified: 05-08-2019
4514    Reviewed and verified: 05-08-2019 Henrik Eriksen
4515"""
4516def ll_con_per_bv_34_c(transport, upperTester, lowerTester, trace):
4517
4518    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4519
4520    success = advertiser.enable();
4521    connected = initiator.connect();
4522    success = success and connected;
4523
4524    if connected:
4525        interval, timeout, errCode = 6, 300, 0x3B;
4526        """
4527            Send LL_CONNECTION_PARAM_REQ to IUT...
4528        """
4529        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
4530        """
4531            Reject the LE Remote Connection Parameter Request Event by issuing a LL_REJECT_EXT_IND...
4532        """
4533        success = initiator.rejectUpdate(errCode) and success;
4534        """
4535            Both lower and upper Tester should receive a LE Connection Update Complete Event... if request was accepted
4536        """
4537        success = not initiator.updated() and (initiator.status == errCode) and success;
4538
4539        success = initiator.disconnect(0x13) and success;
4540    else:
4541        success = advertiser.disable() and success;
4542
4543    return success;
4544
4545"""
4546    LL/CON/PER/BV-40-C [Peripheral requests PHY Update procedure]
4547
4548    Last modified: 05-08-2019
4549    Reviewed and verified: 05-08-2019 Henrik Eriksen
4550"""
4551def ll_con_per_bv_40_c(transport, upperTester, lowerTester, trace):
4552
4553    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4554
4555    success = advertiser.enable();
4556    connected = initiator.connect();
4557    success = success and connected;
4558
4559    columns = defaultdict(list); # each value in each column is appended to a list
4560
4561    with open('src/tests/params_con_per_bv_40.csv') as f:
4562        reader = csv.reader(f);
4563        next(reader);
4564        for row in reader:
4565            for (i,v) in enumerate(row):
4566                columns[i].append(int(v, 16));
4567
4568    all_phys, tx_phys, rx_phys = columns[1], columns[2], columns[3];
4569
4570    if connected:
4571        initiator.switchRoles();
4572
4573        for i in range(0, len(columns[0])):
4574            if (tx_phys[i] == 0) or (tx_phys[i] > 3) or (rx_phys[i] == 0) or (rx_phys[i] > 3):
4575                continue
4576
4577            trace.trace(7, "Execute PHY Update with the following parameters:\tALL_PHYS: %s\tTX: %s\tRX: %s" % (str(all_phys[i]), str(tx_phys[i]), str(rx_phys[i])));
4578
4579            success = initiator.updatePhys(all_phys[i], tx_phys[i], rx_phys[i], 0) and success;
4580
4581            trace.trace(4, "Updated PHYs:\tTX: %s\tRX: %s\n" % (str(initiator.txPhys), str(initiator.rxPhys)))
4582
4583        transport.wait(int(4 * initiator.intervalMin * 1.25))
4584
4585        initiator.resetRoles()
4586
4587        success = initiator.disconnect(0x13) and success;
4588    else:
4589        success = advertiser.disable() and success;
4590
4591    return success;
4592
4593"""
4594    LL/CON/PER/BV-42-C [Peripheral responds to PHY Update procedure]
4595
4596    Last modified: 05-08-2019
4597    Reviewed and verified: 05-08-2019 Henrik Eriksen
4598"""
4599def ll_con_per_bv_42_c(transport, upperTester, lowerTester, trace):
4600
4601    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4602
4603    success = advertiser.enable();
4604    connected = initiator.connect();
4605    success = success and connected;
4606
4607    if connected:
4608        initiator.switchRoles();
4609
4610        success = initiator.updatePhys( 3, 0, 0, 0 ) and success;
4611
4612        initiator.resetRoles();
4613
4614        tabel = list(zip( [2, 1, 2, 1, 3, 3, 1, 2, 3], [2, 2, 1, 1, 2, 1, 3, 3, 3], [2, 1, 2, 1, 2, 2, 1, 2, 2], [2, 2, 1, 1, 2, 1, 2, 2, 2] ));
4615
4616        for i in range(2):
4617            for txPhys, rxPhys, expTxPhys, expRxPhys in tabel:
4618                success = initiator.updatePhys(0, txPhys, rxPhys, 0) and success;
4619                success = success and (initiator.txPhys == expTxPhys) and (initiator.rxPhys == expRxPhys);
4620            random.shuffle(tabel)
4621
4622        success = initiator.disconnect(0x13) and success;
4623    else:
4624        success = advertiser.disable() and success;
4625
4626    return success;
4627
4628"""
4629    LL/CON/PER/BV-77-C [Peripheral Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 1M PHY]
4630
4631    Last modified: 09-08-2019
4632    Reviewed and verified: 09-08-2019 Henrik Eriksen (Note: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
4633"""
4634def ll_con_per_bv_77_c(transport, upperTester, lowerTester, trace):
4635
4636    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4637    """
4638        Obtain maximum Data Packet size and maximum number of Data Packets
4639    """
4640    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
4641    maxPacketTime, cmaxTxOctets, cmaxTxTime = calcMaxPacketTime(maxPacketLength), 27, 328;
4642
4643    success = advertiser.enable() and success;
4644    connected = initiator.connect();
4645    success = success and connected;
4646
4647    if connected:
4648        """
4649            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
4650        """
4651        success = readRemoteFeatures(transport, lowerTester, initiator.handles[0], trace) and success;
4652        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, lowerTester, trace);
4653        showLEFeatures(features, trace);
4654
4655        """
4656            Exchange data...
4657        """
4658        lenValues  = list(range(28, maxPacketLength-1)) + list(range(maxPacketLength+1, 250));
4659        timeValues = list(range(329, maxPacketTime-1)) + list(range(maxPacketTime+1, 2119));
4660
4661        for txOctets, txTime in zip( [ 27, 251, maxPacketLength, 27, 27, 27, 251, 251, 251, maxPacketLength, maxPacketLength, maxPacketLength, \
4662                                       random.choice(lenValues), random.choice(lenValues), random.choice(lenValues), random.choice(lenValues) ], \
4663                                     [ 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, \
4664                                       random.choice(timeValues), random.choice(timeValues), random.choice(timeValues), random.choice(timeValues) ] ):
4665
4666            success = setDataLength(transport, upperTester, initiator.handles[1], txOctets, txTime, trace) and success;
4667            requested = success;
4668            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
4669
4670            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
4671
4672            if requested and changed:
4673                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, upperTester, trace);
4674                success = success and gotEvent;
4675                gotEvent = hasDataLengthChangedEvent(transport, lowerTester, trace)[0];
4676                success = success and gotEvent;
4677
4678            pbFlags = 0;
4679            """
4680                Upper Tester is sending Data...
4681            """
4682            txData = [_ for _ in range(maxPacketLength)];
4683            dataSent = writeData(transport, lowerTester, initiator.handles[0], pbFlags, txData, trace);
4684            success = success and dataSent;
4685            if dataSent:
4686                dataReceived, rxData = readDataFragments(transport, upperTester, trace);
4687                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
4688            """
4689                Lower Tester is sending Data...
4690            """
4691            txData = [_ for _ in range(27)];
4692            for i in range(20):
4693                dataSent = writeData(transport, upperTester, initiator.handles[1], pbFlags, txData, trace);
4694                success = success and dataSent;
4695                if dataSent:
4696                    dataReceived, rxData = readData(transport, lowerTester, trace);
4697                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
4698        """
4699            Note: Disconnect can generate another LE Data Length Change event...
4700        """
4701        success = initiator.disconnect(0x13) and success;
4702    else:
4703        success = advertiser.disable() and success;
4704
4705    return success;
4706
4707"""
4708    LL/CON/PER/BV-78-C [Peripheral requests Packet Data Length Update procedure; LE 1M PHY]
4709
4710    Last modified: 06-08-2019
4711    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
4712"""
4713def ll_con_per_bv_78_c(transport, upperTester, lowerTester, trace):
4714
4715    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4716    """
4717        Obtain maximum Data Packet size and maximum number of Data Packets
4718    """
4719    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
4720    cmaxTxOctets, cmaxTxTime, maxPacketTime = 27, 328, int(2120 * maxPacketLength / 251);
4721
4722    trace.trace(8, "Max supported packet length: %d octets. Max supported transmit time: %d micro seconds" % (maxPacketLength, maxPacketTime));
4723
4724    success = advertiser.enable() and success;
4725    connected = initiator.connect();
4726    success = success and connected;
4727
4728    if connected:
4729        """
4730            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
4731        """
4732        success = readRemoteFeatures(transport, lowerTester, initiator.handles[0], trace) and success;
4733        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, lowerTester, trace);
4734        showLEFeatures(features, trace);
4735
4736        for txOctets, txTime in zip([ maxPacketLength, 27, 251, maxPacketLength, 27, 251, maxPacketLength, 27, 251, maxPacketLength, 27, 251 ], \
4737                                    [ maxPacketTime, maxPacketTime, maxPacketTime, 328, 328, 328, 2120, 2120, 2120, 2120, 2120, 2120 ]):
4738
4739            success = setDataLength(transport, upperTester, initiator.handles[1], txOctets, txTime, trace) and success;
4740            requested = success;
4741            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
4742
4743            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
4744
4745            if requested and changed:
4746                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, upperTester, trace);
4747                if not gotEvent:
4748                    trace.trace(7, "Missing Data Length Changed event from upperTester!");
4749                success = success and gotEvent;
4750                gotEvent = hasDataLengthChangedEvent(transport, lowerTester, trace)[0];
4751                if not gotEvent:
4752                    trace.trace(7, "Missing Data Length Changed event from lowerTester!");
4753                success = success and gotEvent;
4754
4755            pbFlags = 0;
4756            """
4757                Upper Tester is sending Data...
4758            """
4759            txData = [_ for _ in range(maxPacketLength)];
4760            dataSent = writeData(transport, upperTester, initiator.handles[1], pbFlags, txData, trace);
4761            success = success and dataSent;
4762            if dataSent:
4763                dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
4764                success = success and dataReceived and (len(rxData) == len(txData));
4765            """
4766                Lower Tester is sending Data...
4767            """
4768            txData = [_ for _ in range(27)];
4769            for i in range(20):
4770                dataSent = writeData(transport, lowerTester, initiator.handles[0], pbFlags, txData, trace);
4771                success = success and dataSent;
4772                if dataSent:
4773                    dataReceived, rxData = readData(transport, upperTester, trace);
4774                    success = success and dataReceived and (len(rxData) == len(txData));
4775        """
4776            Note: Disconnect can generate another LE Data Length Change event...
4777        """
4778        success = initiator.disconnect(0x13) and success;
4779    else:
4780        success = advertiser.disable() and success;
4781
4782    return success;
4783
4784"""
4785    LL/CON/PER/BV-80-C [Peripheral Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 2M PHY]
4786
4787    Last modified: 09-08-2019
4788    Reviewed and verified: 09-08-2019 Henrik Eriksen (Note: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
4789"""
4790def ll_con_per_bv_80_c(transport, upperTester, lowerTester, trace):
4791
4792    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4793    """
4794        Obtain maximum Data Packet size and maximum number of Data Packets
4795    """
4796    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
4797    maxPacketTime, cmaxTxOctets, cmaxTxTime = calcMaxPacketTime(maxPacketLength), 27, 328;
4798
4799    success = advertiser.enable() and success;
4800    connected = initiator.connect();
4801    success = success and connected;
4802
4803    if connected:
4804        """
4805            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
4806        """
4807        success = readRemoteFeatures(transport, lowerTester, initiator.handles[0], trace) and success;
4808        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, lowerTester, trace);
4809        showLEFeatures(features, trace);
4810
4811        """
4812            Switch to LE 2M PHY channel...
4813        """
4814        allPhys, txPhys, rxPhys, optionPhys = 0, 2, 2, 0;
4815
4816        success = initiator.updatePhys(allPhys, txPhys, rxPhys, optionPhys) and success;
4817        success = (initiator.txPhys == txPhys) and (initiator.rxPhys == rxPhys) and success
4818        """
4819            Exchange data...
4820        """
4821        lenValues  = list(range(28, maxPacketLength-1)) + list(range(maxPacketLength+1, 250));
4822        timeValues = list(range(329, maxPacketTime-1)) + list(range(maxPacketTime+1, 2119));
4823
4824        for txOctets, txTime in zip( [ 27, 251, maxPacketLength, 27, 27, 27, 251, 251, 251, maxPacketLength, maxPacketLength, maxPacketLength, \
4825                                       random.choice(lenValues), random.choice(lenValues), random.choice(lenValues), random.choice(lenValues) ], \
4826                                     [ 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, \
4827                                       random.choice(timeValues), random.choice(timeValues), random.choice(timeValues), random.choice(timeValues) ] ):
4828
4829            success = setDataLength(transport, upperTester, initiator.handles[1], txOctets, txTime, trace) and success;
4830            requested = success;
4831            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
4832
4833            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
4834
4835            if requested and changed:
4836                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, upperTester, trace);
4837                success = success and gotEvent;
4838                gotEvent = hasDataLengthChangedEvent(transport, lowerTester, trace)[0];
4839                success = success and gotEvent;
4840
4841            pbFlags = 0;
4842            """
4843                Upper Tester is sending Data...
4844            """
4845            txData = [_ for _ in range(maxPacketLength)];
4846            dataSent = writeData(transport, lowerTester, initiator.handles[0], pbFlags, txData, trace);
4847            success = success and dataSent;
4848            if dataSent:
4849                dataReceived, rxData = readDataFragments(transport, upperTester, trace);
4850                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
4851            """
4852                Lower Tester is sending Data...
4853            """
4854            txData = [_ for _ in range(27)];
4855            for i in range(20):
4856                dataSent = writeData(transport, upperTester, initiator.handles[1], pbFlags, txData, trace);
4857                success = success and dataSent;
4858                if dataSent:
4859                    dataReceived, rxData = readData(transport, lowerTester, trace);
4860                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
4861        """
4862            Note: Disconnect can generate another LE Data Length Change event...
4863        """
4864        success = initiator.disconnect(0x13) and success;
4865    else:
4866        success = advertiser.disable() and success;
4867
4868    return success;
4869
4870"""
4871    LL/CON/PER/BV-81-C [Peripheral requests Packet Data Length Update procedure; LE 2M PHY]
4872
4873    Last modified: 06-08-2019
4874    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
4875"""
4876def ll_con_per_bv_81_c(transport, upperTester, lowerTester, trace):
4877
4878    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4879    """
4880        Obtain maximum Data Packet size and maximum number of Data Packets
4881    """
4882    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
4883    cmaxTxOctets, cmaxTxTime, maxPacketTime = 27, 328, int(2120 * maxPacketLength / 251);
4884
4885    trace.trace(8, "Max supported packet length: %d octets. Max supported transmit time: %d micro seconds" % (maxPacketLength, maxPacketTime));
4886
4887    success = advertiser.enable() and success;
4888    connected = initiator.connect();
4889    success = success and connected;
4890
4891    if connected:
4892        """
4893            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
4894        """
4895        success = readRemoteFeatures(transport, lowerTester, initiator.handles[0], trace) and success;
4896        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, lowerTester, trace);
4897        showLEFeatures(features, trace);
4898
4899        initiator.switchRoles();
4900        """
4901            Switch to the 2M PHY channel
4902        """
4903        txPhys, rxPhys, allPhys, optionPhys = 2, 2, 0, 0;
4904        success = initiator.updatePhys(allPhys, txPhys, rxPhys, optionPhys) and success;
4905        success = success and (initiator.txPhys == txPhys) and (initiator.rxPhys == rxPhys);
4906
4907        initiator.resetRoles();
4908
4909        for txOctets, txTime in zip([ maxPacketLength, 27, 251, maxPacketLength, 27, 251, maxPacketLength, 27, 251, maxPacketLength, 27, 251 ], \
4910                                    [ maxPacketTime, maxPacketTime, maxPacketTime, 328, 328, 328, 2120, 2120, 2120, 2120, 2120, 2120 ]):
4911
4912            success = setDataLength(transport, upperTester, initiator.handles[1], txOctets, txTime, trace) and success;
4913            requested = success;
4914            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
4915
4916            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
4917
4918            if requested and changed:
4919                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, upperTester, trace);
4920                success = success and gotEvent;
4921                gotEvent = hasDataLengthChangedEvent(transport, lowerTester, trace)[0];
4922                success = success and gotEvent;
4923
4924            pbFlags = 0;
4925            """
4926                Upper Tester is sending Data...
4927            """
4928            txData = [_ for _ in range(maxPacketLength)];
4929            dataSent = writeData(transport, upperTester, initiator.handles[1], pbFlags, txData, trace);
4930            success = success and dataSent;
4931            if dataSent:
4932                dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
4933                success = success and dataReceived and (len(rxData) == len(txData));
4934            """
4935                Lower Tester is sending Data...
4936            """
4937            txData = [_ for _ in range(27)];
4938            for i in range(20):
4939                dataSent = writeData(transport, lowerTester, initiator.handles[0], pbFlags, txData, trace);
4940                success = success and dataSent;
4941                if dataSent:
4942                    dataReceived, rxData = readData(transport, upperTester, trace);
4943                    success = success and dataReceived and (len(rxData) == len(txData));
4944        """
4945            Note: Disconnect can generate another LE Data Length Change event...
4946        """
4947        success = initiator.disconnect(0x13) and success;
4948    else:
4949        success = advertiser.disable() and success;
4950
4951    return success;
4952
4953"""
4954    LL/CON/PER/BI-08-C [Peripheral responds to Connection Parameters request - Illegal Parameters]
4955
4956    Last modified: 06-08-2019
4957    Reviewed and verified: 06-08-2019 Henrik Eriksen
4958"""
4959def ll_con_per_bi_08_c(transport, upperTester, lowerTester, trace):
4960
4961    advertiser, initiator = setPublicInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4962
4963    success = advertiser.enable();
4964    connected = initiator.connect();
4965    success = success and connected;
4966
4967    if connected:
4968        interval, errCode = 4, 0x1E;
4969        """
4970            Send LL_CONNECTION_PARAM_REQ to IUT...
4971        """
4972        success = initiator.update(interval, interval, initiator.latency, 300) and success;
4973        """
4974            Verify that lower tester receives a CONNECTION UPDATE COMPLETE Event...
4975        """
4976        success = not initiator.updated() and (initiator.status == errCode) and success;
4977
4978        success = initiator.disconnect(0x13) and success;
4979    else:
4980        success = advertiser.disable() and success;
4981
4982    return success;
4983
4984"""
4985    LL/CON/CEN/BV-03-C [Central sending Data packets to Peripheral]
4986
4987    Last modified: 06-08-2019
4988    Reviewed and verified: 06-08-2019 Henrik Eriksen
4989"""
4990def ll_con_cen_bv_03_c(transport, upperTester, lowerTester, trace):
4991
4992    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
4993    """
4994       Obtain maximum Data Packet size and maximum number of Data Packets
4995    """
4996    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
4997
4998    success = advertiser.enable() and success;
4999    connected = initiator.connect();
5000    success = success and connected;
5001
5002    if connected:
5003        txData = [0 for _ in range(10)];
5004        pbFlags = 1;
5005        """
5006            Sending Data Packets with a fixed length less than 27...
5007        """
5008        for count in [ 100, 100, 1, 99 ]:
5009            pbFlags ^= 1;
5010            for j in range(count):
5011                dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
5012                success = success and dataSent;
5013                if dataSent:
5014                    dataReceived, rxData = readData(transport, lowerTester, trace);
5015                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5016
5017        if maxPacketLength > 27:
5018            """
5019                Sending Data Packets with a random length greater than 27...
5020            """
5021            pbFlags, count = 0, 0;
5022
5023            while count < 1000:
5024                txData = [0 for _ in range(random.randint(28, maxPacketLength))];
5025
5026                dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
5027                success = success and dataSent;
5028                count += len(txData);
5029                if dataSent:
5030                    dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
5031                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5032                else:
5033                    break;
5034
5035        success = initiator.disconnect(0x13) and success;
5036    else:
5037        success = advertiser.disable() and success;
5038
5039    return success;
5040
5041"""
5042    LL/CON/CEN/BV-04-C [Central receiving Data packets from Peripheral]
5043
5044    Last modified: 06-08-2019
5045    Reviewed and verified: 06-08-2019 Henrik Eriksen
5046"""
5047def ll_con_cen_bv_04_c(transport, upperTester, lowerTester, trace):
5048
5049    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5050
5051    success = advertiser.enable();
5052    connected = initiator.connect();
5053    success = success and connected;
5054
5055    if connected:
5056        txData = [0 for _ in range(10)];
5057        pbFlags = 1;
5058        """
5059            Sending Data Packets with a fixed length less than 27...
5060        """
5061        for count in [ 100, 100, 1, 99 ]:
5062            pbFlags ^= 1;
5063            trace.trace(7, '-'*77);
5064            for j in range(count):
5065                dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
5066                success = success and dataSent;
5067                if dataSent:
5068                    dataReceived, rxData = readData(transport, upperTester, trace);
5069                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5070        trace.trace(7, '-'*77);
5071
5072        success = initiator.disconnect(0x13) and success;
5073    else:
5074        success = advertiser.disable() and success;
5075
5076    return success;
5077
5078"""
5079    LL/CON/CEN/BV-05-C [Central sending and receiving Data packets to and form Peripheral]
5080
5081    Last modified: 06-08-2019
5082    Reviewed and verified: 06-08-2019 Henrik Eriksen
5083"""
5084def ll_con_cen_bv_05_c(transport, upperTester, lowerTester, trace):
5085
5086    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5087
5088    success = advertiser.enable();
5089    connected = initiator.connect();
5090    success = success and connected;
5091
5092    if connected:
5093        pbFlags = 0;
5094        """
5095            Sending Data Packets with a fixed length less than 27...
5096        """
5097        for j in range(100):
5098            """
5099                Upper Tester is sending Data...
5100            """
5101            trace.trace(7, '-'*77);
5102            txData = [0x00 for _ in range(10)];
5103            dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
5104            success = success and dataSent;
5105            if dataSent:
5106                dataReceived, rxData = readData(transport, lowerTester, trace);
5107                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5108            """
5109                Lower Tester is sending Data...
5110            """
5111            txData = [0xFF for _ in range(10)];
5112            dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
5113            success = success and dataSent;
5114            if dataSent:
5115                dataReceived, rxData = readData(transport, upperTester, trace);
5116                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5117
5118            if j == 0:
5119                pbFlags = 1;
5120        trace.trace(7, '-'*77);
5121
5122        success = initiator.disconnect(0x13) and success;
5123    else:
5124        success = advertiser.disable() and success;
5125
5126    return success;
5127
5128"""
5129    LL/CON/CEN/BV-07-C [Central requests Connection Parameter Update]
5130
5131    Last modified: 06-08-2019
5132    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: connection event where change take place cannot be verified - see Air trace)
5133"""
5134def ll_con_cen_bv_07_c(transport, upperTester, lowerTester, trace):
5135
5136    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5137
5138    success = advertiser.enable();
5139    connected = initiator.connect();
5140    success = success and connected;
5141
5142    if connected:
5143        interval, timeout = 64, 3200;
5144        """
5145            Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5146        """
5147        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5148        """
5149            Accept the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP...
5150        """
5151        success = initiator.acceptUpdate() and success;
5152        """
5153            Both lower and upper Tester should receive a LE Connection Update Complete Event...
5154        """
5155        success = initiator.updated() and success;
5156        """
5157            Wait for change to take place...
5158        """
5159        transport.wait(int(4 * interval * 1.25));
5160
5161        success = initiator.disconnect(0x13) and success;
5162    else:
5163        success = advertiser.disable() and success;
5164
5165    return success
5166
5167"""
5168    LL/CON/CEN/BV-08-C [Central Terminating Connection]
5169
5170    Last modified: 06-08-2019
5171    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Not verified that IUT stops sending empty data packets - see Air trace)
5172"""
5173def ll_con_cen_bv_08_c(transport, upperTester, lowerTester, trace):
5174
5175    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5176
5177    success = advertiser.enable();
5178    connected = initiator.connect();
5179    success = success and connected;
5180
5181    if connected:
5182        success = initiator.disconnect(0x13) and (initiator.reasons[0] == 0x16) and success;
5183    else:
5184        success = advertiser.disable() and success;
5185
5186    return success;
5187
5188"""
5189    LL/CON/CEN/BV-09-C [Central accepting Connection Termination]
5190
5191    Last modified: 06-08-2019
5192    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Not verified that IUT stops sending empty data packets - see Air trace)
5193"""
5194def ll_con_cen_bv_09_c(transport, upperTester, lowerTester, trace):
5195
5196    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5197
5198    success = advertiser.enable();
5199    connected = initiator.connect();
5200    success = success and connected;
5201
5202    if connected:
5203        initiator.switchRoles();
5204        success = initiator.disconnect(0x13) and (initiator.reasons[1] == 0x13) and success;
5205    else:
5206        success = advertiser.disable() and success;
5207
5208    return success;
5209
5210"""
5211    LL/CON/CEN/BV-13-C [Central requests Feature Setup procedure]
5212
5213    Last modified: 06-08-2019
5214    Reviewed and verified: 06-08-2019 Henrik Eriksen
5215"""
5216def ll_con_cen_bv_13_c(transport, upperTester, lowerTester, trace):
5217
5218    LL_FEAT_BIT_MASK_VALID = 0x1CF2F # Bitmask for features not impacting feature masking (ll_feat.h)
5219
5220    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5221
5222    success = advertiser.enable();
5223    connected = initiator.connect();
5224    success = success and connected;
5225
5226    if connected:
5227        """
5228            Read local features from lower- and upperTester to establish expected remote read
5229            result
5230        """
5231        hasFeatures, expectedFeatures = readLocalFeatures(transport, lowerTester, trace)
5232        hasFeatures, upperFeatures    = readLocalFeatures(transport, upperTester, trace)
5233        upperLocalFeatures = toNumber(upperFeatures)
5234        """
5235            Keep octets 1-7, and do the logical and on octet 0; also ignore the non-valid bits
5236            See BT Core spec V5.2, Vol 6. Part B chapter 4.6
5237        """
5238        expectedMaskedFeatures = toNumber([upperFeatures[0] & expectedFeatures[0]] + list(expectedFeatures[1:7]))
5239        expectedMaskedFeatures = expectedMaskedFeatures & LL_FEAT_BIT_MASK_VALID
5240        """
5241            Issue the LE Read Remote Features Command, verify the reception of a Command Status Event
5242        """
5243        success = readRemoteFeatures(transport, upperTester, initiator.handles[0], trace) and success;
5244        """
5245            Await the reception of a LE Read Remote Features Command Complete Event
5246        """
5247        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, upperTester, trace);
5248        success = success and hasFeatures;
5249        if hasFeatures:
5250            showLEFeatures(features, trace)
5251            receivedMaskedFeatures = toNumber(features) & LL_FEAT_BIT_MASK_VALID
5252            success = (receivedMaskedFeatures == expectedMaskedFeatures) and success
5253
5254        success = initiator.disconnect(0x13) and success;
5255    else:
5256        success = advertiser.disable() and success;
5257
5258    return success;
5259
5260"""
5261    LL/CON/CEN/BV-20-C [Central requests Version Exchange procedure]
5262
5263    Last modified: 06-08-2019
5264    Reviewed and verified: 06-08-2019 Henrik Eriksen
5265"""
5266def ll_con_cen_bv_20_c(transport, upperTester, lowerTester, trace):
5267
5268    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5269
5270    success = advertiser.enable();
5271    connected = initiator.connect();
5272    success = success and connected;
5273
5274    if connected:
5275        """
5276            Issue the Read Remote Version Information Command, verify the reception of a Command Status Event
5277        """
5278        success = readRemoteVersionInformation(transport, upperTester, initiator.handles[0], trace) and success;
5279        """
5280            Await the reception of a Read Remote Version Information Complete Event
5281        """
5282        hasVersion, handle, version, manufacturer, subVersion = hasReadRemoteVersionInformationCompleteEvent(transport, upperTester, trace);
5283        success = success and hasVersion;
5284        if hasVersion:
5285            trace.trace(8, "     version: 0x%02x" % version);
5286            trace.trace(8, " sub-version: 0x%04x" % subVersion);
5287            trace.trace(8, "manufacturer: 0x%04x" % manufacturer);
5288
5289        success = initiator.disconnect(0x13) and success;
5290    else:
5291        success = advertiser.disable() and success;
5292
5293    return success;
5294
5295"""
5296    LL/CON/CEN/BV-21-C [Central responds to Version Exchange procedure]
5297
5298    Last modified: 06-08-2019
5299    Reviewed and verified: 06-08-2019 Henrik Eriksen
5300"""
5301def ll_con_cen_bv_21_c(transport, upperTester, lowerTester, trace):
5302
5303    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5304
5305    success = advertiser.enable();
5306    connected = initiator.connect();
5307    success = success and connected;
5308
5309    if connected:
5310        """
5311            Issue the Read Remote Version Information Command, verify the reception of a Command Status Event
5312        """
5313        success = readRemoteVersionInformation(transport, lowerTester, initiator.handles[1], trace) and success;
5314        """
5315            Await the reception of a Read Remote Version Information Complete Event
5316        """
5317        hasVersion, handle, version, manufacturer, subVersion = hasReadRemoteVersionInformationCompleteEvent(transport, lowerTester, trace);
5318        success = success and hasVersion;
5319        if hasVersion:
5320            trace.trace(8, "     version: 0x%02x" % version);
5321            trace.trace(8, " sub-version: 0x%04x" % subVersion);
5322            trace.trace(8, "manufacturer: 0x%04x" % manufacturer);
5323
5324        success = initiator.disconnect(0x13) and success;
5325    else:
5326        success = advertiser.disable() and success;
5327
5328    return success;
5329
5330"""
5331    LL/CON/CEN/BV-23-C [Central responds to Feature Exchange procedure]
5332
5333    Last modified: 06-08-2019
5334    Reviewed and verified: 06-08-2019 Henrik Eriksen
5335"""
5336def ll_con_cen_bv_23_c(transport, upperTester, lowerTester, trace):
5337
5338    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5339
5340    success = advertiser.enable();
5341    connected = initiator.connect();
5342    success = success and connected;
5343
5344    if connected:
5345        """
5346            Issue the LE Read Remote Features Command, verify the reception of a Command Status Event
5347        """
5348        success = success and readRemoteFeatures(transport, lowerTester, initiator.handles[1], trace);
5349        """
5350            Await the reception of a LE Read Remote Features Command Complete Event
5351        """
5352        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, lowerTester, trace);
5353        success = success and hasFeatures;
5354        if hasFeatures:
5355            showLEFeatures(features, trace);
5356            # Bit 27 is "Masked to Peer" an must be cleared
5357            success = ((toNumber(features) & (1 << 27)) == 0) and success;
5358
5359        success = initiator.disconnect(0x13) and success;
5360    else:
5361        success = advertiser.disable() and success;
5362
5363    return success;
5364
5365"""
5366    LL/CON/CEN/BV-24-C [Central requests Connection Parameters - Peripheral Accepts]
5367
5368    Last modified: 06-08-2019
5369    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Actual effect of change cannot be verified - see Air trace)
5370"""
5371def ll_con_cen_bv_24_c(transport, upperTester, lowerTester, trace):
5372
5373    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5374
5375    success = advertiser.enable();
5376    connected = initiator.connect();
5377    success = success and connected;
5378
5379    if connected:
5380        for interval, timeout in zip([ 6, 3200, 6 ], [ 300, 3200, 300 ]):
5381            """
5382                Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5383            """
5384            success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5385            """
5386                Accept the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP...
5387            """
5388            success = initiator.acceptUpdate() and success;
5389            """
5390                Both lower and upper Tester should receive a LE Connection Update Complete Event...
5391            """
5392            success = initiator.updated() and success;
5393            """
5394                Wait for change to take place...
5395            """
5396            transport.wait(int(4 * interval * 1.25));
5397
5398        success = initiator.disconnect(0x13) and success;
5399    else:
5400        success = advertiser.disable() and success;
5401
5402    return success;
5403
5404"""
5405    LL/CON/CEN/BV-25-C [Central requests Connection Parameters - Peripheral Rejects]
5406
5407    Last modified: 06-08-2019
5408    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Actual effect of change cannot be verified - see Air trace)
5409"""
5410def ll_con_cen_bv_25_c(transport, upperTester, lowerTester, trace):
5411
5412    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5413
5414    success = advertiser.enable();
5415    connected = initiator.connect();
5416    success = success and connected;
5417
5418    if connected:
5419        interval, timeout = 6, 300;
5420        for reject in [ True, False ]:
5421            """
5422                Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5423            """
5424            success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5425            """
5426                Accept or Reject the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP or a LL_REJECT_EXT_IND...
5427            """
5428            success = (initiator.rejectUpdate(0x3B) if reject else initiator.acceptUpdate()) and success;
5429            """
5430                Both lower and upper Tester should receive a LE Connection Update Complete Event... if request was accepted
5431            """
5432            if reject:
5433                success = not initiator.updated() and (initiator.status == 0x3B) and success;
5434            else:
5435                success = initiator.updated() and success;
5436            """
5437                Wait for optional change to take place...
5438            """
5439            transport.wait(int(4 * interval * 1.25));
5440
5441        success = initiator.disconnect(0x13) and success;
5442    else:
5443        success = advertiser.disable() and success;
5444
5445    return success;
5446
5447"""
5448    LL/CON/CEN/BV-26-C [Central requests Connection Parameters - same procedure collision]
5449
5450    Last modified: 06-08-2019
5451    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Test not according to specs - not possible!)
5452"""
5453def ll_con_cen_bv_26_c(transport, upperTester, lowerTester, trace):
5454
5455    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5456
5457    success = advertiser.enable();
5458    connected = initiator.connect();
5459    success = success and connected;
5460
5461    if connected:
5462        interval, timeout = 6, 300;
5463        """
5464            Request an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5465        """
5466        updRequested = initiator.update(interval, interval, initiator.latency, timeout);
5467        success = success and updRequested;
5468        """
5469            Verify that the lower tester receives a LE Remote Connection Parameter Request Event...
5470        """
5471        updPeerInvolved = initiator.updPeerRequest;
5472        success = success and updPeerInvolved;
5473        """
5474            Send a LL_CONNECTION_PARAM_REQ as a reaction to the LE Remote Connection Parameter Request Event...
5475            NOTE: We use a little nasty trick here. Swap the roles of initiator and peer and swap assigned handles...
5476        """
5477        initiator.switchRoles();
5478        """
5479            Update request will be rejected with an error code 0x0C - command disallowed...
5480        """
5481        success = success and not initiator.update(interval, interval, initiator.latency, timeout) and initiator.status == 0x0C;
5482        """
5483            Get back to original roles of initiator and peer...
5484        """
5485        initiator.resetRoles();
5486        """
5487            Send a LL_CONNECTION_PARAM_RSP as a reaction to the original LE Remote Connection Parameter Request Event...
5488        """
5489        initiator.updInitiatorRequest, initiator.updPeerRequest = updRequested, updPeerInvolved;
5490        success = success and initiator.acceptUpdate();
5491        """
5492            Both lower and upper Tester should receive a LE Connection Update Complete Event...
5493        """
5494        success = success and initiator.updated();
5495        """
5496            Wait for change to take place...
5497        """
5498        transport.wait(int(4 * interval * 1.25));
5499
5500        success = initiator.disconnect(0x13) and success;
5501    else:
5502        success = advertiser.disable() and success;
5503
5504    return success;
5505
5506"""
5507    LL/CON/CEN/BV-27-C [Central requests Connection Parameters - Channel Map Update procedure collision]
5508
5509    Last modified: 06-08-2019
5510    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Switch to only even channels cannot be verified - see Air trace)
5511"""
5512def ll_con_cen_bv_27_c(transport, upperTester, lowerTester, trace):
5513
5514    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5515
5516    success = advertiser.enable();
5517    connected = initiator.connect();
5518    success = success and connected;
5519
5520    if connected:
5521        interval, timeout = 6, 300;
5522        """
5523            Use only even channels...
5524        """
5525        success = channelMapUpdate(transport, upperTester, 0x1555555555, trace) and success;
5526        """
5527            Lower tester requests an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5528            NOTE: We use a little nasty trick here. Swap the roles of initiator and peer and swap assigned handles...
5529        """
5530        initiator.switchRoles();
5531        transport.wait(20); # FIXME: Avoid test failure due to Zephyr controller occasionally generating Different Transaction Collision
5532        """
5533            Lower tester requests an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5534        """
5535        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5536        """
5537            Reject the LE Remote Connection Parameter Request Event by issuing a LL_REJECT_EXT_IND...
5538        """
5539        success = initiator.rejectUpdate(0x2A) and success;
5540        """
5541            Verify that the update was rejected with error code 0x2A
5542        """
5543        success = not initiator.updated() and (initiator.status == 0x2A) and success;
5544        """
5545            Get back to original roles of initiator and peer...
5546        """
5547        initiator.resetRoles();
5548        initiator.pre_updated = True;
5549        interval = 24;
5550        """
5551            Wait for change to take place...
5552        """
5553        transport.wait(int(8 * interval * 1.25));
5554
5555        success = initiator.disconnect(0x13) and success;
5556    else:
5557        success = advertiser.disable() and success;
5558
5559    return success;
5560
5561"""
5562    LL/CON/CEN/BV-29-C [Central requests Connection Parameters - Peripheral unsupported]
5563
5564    Last modified: 06-08-2019
5565    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Change to connection interval cannot be verified - see Air trace)
5566"""
5567def ll_con_cen_bv_29_c(transport, upperTester, lowerTester, trace):
5568
5569    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5570
5571    success = advertiser.enable();
5572    connected = initiator.connect();
5573    success = success and connected;
5574
5575    if connected:
5576        interval, timeout = 6, 300;
5577        """
5578            Upper tester requests an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5579        """
5580        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5581        """
5582            Reject the LE Remote Connection Parameter Request Event by issuing a LL_REJECT_EXT_IND... (update will take place)
5583        """
5584        success = initiator.rejectUpdate(0x1A) and success;
5585        """
5586            Verify that the update was accepted
5587        """
5588        success = initiator.updated() and success;
5589        """
5590            Wait for change to take place...
5591        """
5592        transport.wait(int(8 * interval * 1.25));
5593
5594        success = initiator.disconnect(0x13) and success;
5595    else:
5596        success = advertiser.disable() and success;
5597
5598    return success;
5599
5600"""
5601    LL/CON/CEN/BV-30-C [Central responds to Connection Parameters request - no Preferred_Periodicity]
5602
5603    Last modified: 06-08-2019
5604    Reviewed and verified: 06-08-2019 Henrik Eriksen (NOTE: Change to connection interval cannot be verified - see Air trace)
5605"""
5606def ll_con_cen_bv_30_c(transport, upperTester, lowerTester, trace):
5607
5608    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5609
5610    success = advertiser.enable();
5611    connected = initiator.connect();
5612    success = success and connected;
5613
5614    if connected:
5615        for interval, timeout in zip([ 6, 3200, 6 ], [ 300, 3200, 300 ]):
5616            """
5617                Lower tester requests an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5618                NOTE: We use a little nasty trick here. Swap the roles of initiator and peer and swap assigned handles...
5619            """
5620            initiator.switchRoles();
5621
5622            success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5623            """
5624                Accept the LE Remote Connection Parameter Request Event by issuing a LL_CONNECTION_PARAM_RSP...
5625            """
5626            success = initiator.acceptUpdate() and success;
5627            """
5628                Both lower and upper Tester should receive a LE Connection Update Complete Event...
5629            """
5630            success = initiator.updated() and success;
5631            """
5632                Wait for change to take place...
5633            """
5634            transport.wait(int(4 * interval * 1.25));
5635
5636            initiator.resetRoles();
5637
5638        success = initiator.disconnect(0x13) and success;
5639    else:
5640        success = advertiser.disable() and success;
5641
5642    return success;
5643
5644"""
5645    LL/CON/CEN/BV-34-C [Central responds to Connection Parameters request - event masked]
5646
5647    Last modified: 06-08-2019
5648    Reviewed and verified: 06-08-2019 Henrik Eriksen
5649"""
5650def ll_con_cen_bv_34_c(transport, upperTester, lowerTester, trace):
5651
5652    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5653
5654    success = advertiser.enable();
5655    connected = initiator.connect();
5656    success = success and connected;
5657    """
5658        Disable the LE Remote Connection Parameter Request event (Bit 5)
5659    """
5660    events = [0xDF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00];
5661    success = setLEEventMask(transport, upperTester, events, trace) and success;
5662
5663    if connected:
5664        interval, timeout = 6, 300;
5665        """
5666            Lower tester requests an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5667            NOTE: We use a little nasty trick here. Swap the roles of initiator and peer and swap assigned handles...
5668        """
5669        initiator.switchRoles();
5670
5671        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5672        """
5673            Update request should be rejected with a LL_REJECT_EXT_IND...
5674        """
5675        success = not initiator.updated() and (initiator.status == 0x1A) and success;
5676
5677        initiator.resetRoles();
5678
5679        success = initiator.disconnect(0x13) and success;
5680    else:
5681        success = advertiser.disable() and success;
5682
5683    return success;
5684
5685"""
5686    LL/CON/CEN/BV-35-C [Central responds to Connection Parameters request - Host rejects]
5687
5688    Last modified: 06-08-2019
5689    Reviewed and verified: 06-08-2019 Henrik Eriksen
5690"""
5691def ll_con_cen_bv_35_c(transport, upperTester, lowerTester, trace):
5692
5693    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5694
5695    success = advertiser.enable();
5696    connected = initiator.connect();
5697    success = success and connected;
5698
5699    if connected:
5700        interval, timeout = 6, 300;
5701        """
5702            Lower tester requests an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
5703            NOTE: We use a little nasty trick here. Swap the roles of initiator and peer and swap assigned handles...
5704        """
5705        initiator.switchRoles();
5706
5707        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
5708        """
5709            Reject the LE Remote Connection Parameter Request Event by issuing a LL_REJECT_EXT_IND...
5710        """
5711        success = initiator.rejectUpdate(0x3B) and success;
5712        """
5713            Verify that the update was rejected...
5714        """
5715        success = not initiator.updated() and success;
5716
5717        initiator.resetRoles();
5718
5719        success = initiator.disconnect(0x13) and success;
5720    else:
5721        success = advertiser.disable() and success;
5722
5723    return success;
5724
5725"""
5726    LL/CON/CEN/BV-41-C [Central requests PHY Update procedure]
5727
5728    Last modified: 06-08-2019
5729    Reviewed and verified: 06-08-2019 Henrik Eriksen
5730"""
5731def ll_con_cen_bv_41_c(transport, upperTester, lowerTester, trace):
5732
5733    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5734
5735    success = advertiser.enable();
5736    connected = initiator.connect();
5737    success = success and connected;
5738
5739    if connected:
5740        optionPhys = 0;
5741
5742        table = list(zip( [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3], \
5743                     [2, 1, 2, 1, 3, 3, 1, 2, 3, 0, 2, 0], \
5744                     [2, 2, 1, 1, 2, 1, 3, 3, 3, 2, 0, 0], \
5745                     [2, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2], \
5746                     [2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 2, 2] ));
5747
5748        for i in range(2):
5749            for allPhys, txPhys, rxPhys, expTxPhys, expRxPhys in table:
5750                success = initiator.updatePhys(allPhys, txPhys, rxPhys, optionPhys) and success;
5751                success = success and (initiator.txPhys == expTxPhys) and (initiator.rxPhys == expRxPhys);
5752            random.shuffle(table);
5753
5754        success = initiator.disconnect(0x13) and success;
5755    else:
5756        success = advertiser.disable() and success;
5757
5758    return success;
5759
5760"""
5761    LL/CON/CEN/BV-43-C [Central responds to PHY Update procedure]
5762
5763    Last modified: 06-08-2019
5764    Reviewed and verified: 06-08-2019 Henrik Eriksen
5765"""
5766def ll_con_cen_bv_43_c(transport, upperTester, lowerTester, trace):
5767
5768    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5769
5770    success = advertiser.enable();
5771    connected = initiator.connect();
5772    success = success and connected;
5773
5774    if connected:
5775        allPhys, optionPhys, expTxPhys, expRxPhys = 3, 0, 2, 2;
5776
5777        success = initiator.updatePhys(allPhys, 1, 1, optionPhys) and success;
5778        success = success and (initiator.txPhys == expTxPhys) and (initiator.rxPhys == expRxPhys);
5779
5780        table = list(zip( [2, 1, 2, 1, 3, 3, 1, 2, 3], \
5781                     [2, 2, 1, 1, 2, 1, 3, 3, 3], \
5782                     [2, 1, 2, 1, 2, 2, 1, 2, 2], \
5783                     [2, 2, 1, 1, 2, 1, 2, 2, 2] ));
5784        allPhys = 0;
5785
5786        initiator.switchRoles();
5787
5788        for i in range(2):
5789            for txPhys, rxPhys, expTxPhys, expRxPhys in table:
5790                success = initiator.updatePhys(allPhys, txPhys, rxPhys, optionPhys) and success;
5791                success = success and (initiator.txPhys == expTxPhys) and (initiator.rxPhys == expRxPhys);
5792            random.shuffle(table);
5793
5794        initiator.resetRoles();
5795
5796        success = initiator.disconnect(0x13) and success;
5797    else:
5798        success = advertiser.disable() and success;
5799
5800    return success;
5801
5802"""
5803    LL/CON/CEN/BV-73-C [Central Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 1M PHY]
5804
5805    Last modified: 08-08-2019
5806    Reviewed and verified: 08-08-2019 Henrik Eriksen (Note: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
5807"""
5808def ll_con_cen_bv_73_c(transport, upperTester, lowerTester, trace):
5809
5810    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5811    """
5812        Obtain maximum Data Packet size and maximum number of Data Packets
5813    """
5814    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
5815    maxPacketTime, cmaxTxOctets, cmaxTxTime = calcMaxPacketTime(maxPacketLength), 27, 328;
5816
5817    success = advertiser.enable() and success;
5818    connected = initiator.connect();
5819    success = success and connected;
5820
5821    if connected:
5822        """
5823            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
5824        """
5825        success = readRemoteFeatures(transport, upperTester, initiator.handles[0], trace) and success;
5826        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, upperTester, trace);
5827        showLEFeatures(features, trace);
5828
5829        """
5830            Exchange data...
5831        """
5832        lenValues  = list(range(28, maxPacketLength-1)) + list(range(maxPacketLength+1, 250));
5833        timeValues = list(range(329, maxPacketTime-1)) + list(range(maxPacketTime+1, 2119));
5834
5835        for txOctets, txTime in zip( [ 27, 251, maxPacketLength, 27, 27, 27, 251, 251, 251, maxPacketLength, maxPacketLength, maxPacketLength, \
5836                                       random.choice(lenValues), random.choice(lenValues), random.choice(lenValues), random.choice(lenValues) ], \
5837                                     [ 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, \
5838                                       random.choice(timeValues), random.choice(timeValues), random.choice(timeValues), random.choice(timeValues) ] ):
5839
5840            success = setDataLength(transport, lowerTester, initiator.handles[1], txOctets, txTime, trace) and success;
5841            requested = success;
5842            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
5843
5844            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
5845
5846            if requested and changed:
5847                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, lowerTester, trace);
5848                success = success and gotEvent;
5849                if not gotEvent:
5850                    trace.trace(6, "Error: Missed Data Length Changed Event from lowerTester");
5851                gotEvent = hasDataLengthChangedEvent(transport, upperTester, trace)[0];
5852                success = success and gotEvent;
5853                if not gotEvent:
5854                    trace.trace(6, "Error: Missed Data Length Changed Event from upperTester");
5855
5856            pbFlags = 0;
5857            """
5858                Upper Tester is sending Data...
5859            """
5860            txData = [_ for _ in range(maxPacketLength)];
5861            dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
5862            success = success and dataSent;
5863            if dataSent:
5864                dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
5865                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5866            """
5867                Lower Tester is sending Data...
5868            """
5869            txData = [_ for _ in range(27)];
5870            for i in range(20):
5871                dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
5872                success = success and dataSent;
5873                if dataSent:
5874                    dataReceived, rxData = readData(transport, upperTester, trace);
5875                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5876        """
5877            Note: Disconnect can generate another LE Data Length Change event...
5878        """
5879        success = initiator.disconnect(0x13) and success;
5880    else:
5881        success = advertiser.disable() and success;
5882
5883    return success;
5884
5885"""
5886    LL/CON/CEN/BV-74-C [Central Packet Data Length Update - Initiating Packet Data Length Update Procedure; LE 1M PHY]
5887
5888    Last modified: 06-08-2019
5889    Reviewed and verified: 06-08-2019 Henrik Eriksen (Note: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
5890"""
5891def ll_con_cen_bv_74_c(transport, upperTester, lowerTester, trace):
5892
5893    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5894    """
5895        Obtain maximum Data Packet size and maximum number of Data Packets
5896    """
5897    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
5898    maxPacketTime, cmaxTxOctets, cmaxTxTime = calcMaxPacketTime(maxPacketLength), 27, 328;
5899
5900    success = advertiser.enable() and success;
5901    connected = initiator.connect();
5902    success = success and connected;
5903
5904    if connected:
5905        """
5906            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
5907        """
5908        success = readRemoteFeatures(transport, upperTester, initiator.handles[0], trace) and success;
5909        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, upperTester, trace);
5910        showLEFeatures(features, trace);
5911
5912        for txOctets, txTime in zip( [ maxPacketLength, 27, 251, maxPacketLength, 27, 251, maxPacketLength, 27, 251, 60, 27, 251 ], \
5913                                     [ maxPacketTime, maxPacketTime, maxPacketTime, 328, 328, 328, 2120, 2120, 2120, 2120, 2120, 2120 ] ):
5914
5915            success = setDataLength(transport, upperTester, initiator.handles[0], txOctets, txTime, trace) and success;
5916            requested = success;
5917            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
5918
5919            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
5920
5921            if requested and changed:
5922                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, upperTester, trace);
5923                success = success and gotEvent;
5924                gotEvent = hasDataLengthChangedEvent(transport, lowerTester, trace)[0];
5925                success = success and gotEvent;
5926
5927            pbFlags = 0;
5928            """
5929                Upper Tester is sending Data...
5930            """
5931            txData = [_ for _ in range(maxPacketLength)];
5932            dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
5933            success = success and dataSent;
5934            if dataSent:
5935                dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
5936                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5937            """
5938                Lower Tester is sending Data...
5939            """
5940            txData = [_ for _ in range(27)];
5941            for i in range(20):
5942                dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
5943                success = success and dataSent;
5944                if dataSent:
5945                    dataReceived, rxData = readData(transport, upperTester, trace);
5946                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
5947        """
5948            Note: Disconnect can generate another LE Data Length Change event...
5949        """
5950        success = initiator.disconnect(0x13) and success;
5951    else:
5952        success = advertiser.disable() and success;
5953
5954    return success;
5955
5956"""
5957    LL/CON/CEN/BV-76-C [Central Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 2M PHY]
5958
5959    Last modified: 08-08-2019
5960    Reviewed and verified: 08-08-2019 Henrik Eriksen (Note: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
5961"""
5962def ll_con_cen_bv_76_c(transport, upperTester, lowerTester, trace):
5963
5964    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
5965    """
5966        Obtain maximum Data Packet size and maximum number of Data Packets
5967    """
5968    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
5969    maxPacketTime, cmaxTxOctets, cmaxTxTime = calcMaxPacketTime(maxPacketLength), 27, 328;
5970
5971    success = advertiser.enable() and success;
5972    connected = initiator.connect();
5973    success = success and connected;
5974
5975    if connected:
5976        """
5977            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
5978        """
5979        success = readRemoteFeatures(transport, upperTester, initiator.handles[0], trace) and success;
5980        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, upperTester, trace);
5981        showLEFeatures(features, trace);
5982
5983        """
5984            Switch to LE 2M PHY channel...
5985        """
5986        allPhys, txPhys, rxPhys, optionPhys = 0, 2, 2, 0;
5987
5988        success = initiator.updatePhys(allPhys, txPhys, rxPhys, optionPhys) and success;
5989        success = (initiator.txPhys == txPhys) and (initiator.rxPhys == rxPhys) and success
5990        """
5991            Exchange data...
5992        """
5993        lenValues  = list(range(28, maxPacketLength-1)) + list(range(maxPacketLength+1, 250));
5994        timeValues = list(range(329, maxPacketTime-1)) + list(range(maxPacketTime+1, 2119));
5995
5996        for txOctets, txTime in zip( [ 27, 251, maxPacketLength, 27, 27, 27, 251, 251, 251, maxPacketLength, maxPacketLength, maxPacketLength, \
5997                                       random.choice(lenValues), random.choice(lenValues), random.choice(lenValues), random.choice(lenValues) ], \
5998                                     [ 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, 328, 2120, maxPacketTime, \
5999                                       random.choice(timeValues), random.choice(timeValues), random.choice(timeValues), random.choice(timeValues) ] ):
6000
6001            success = setDataLength(transport, lowerTester, initiator.handles[1], txOctets, txTime, trace) and success;
6002            requested = success;
6003            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
6004
6005            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
6006
6007            if requested and changed:
6008                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, lowerTester, trace);
6009                success = success and gotEvent;
6010                gotEvent = hasDataLengthChangedEvent(transport, upperTester, trace)[0];
6011                success = success and gotEvent;
6012
6013            pbFlags = 0;
6014            """
6015                Upper Tester is sending Data...
6016            """
6017            txData = [_ for _ in range(maxPacketLength)];
6018            dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
6019            success = success and dataSent;
6020            if dataSent:
6021                dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
6022                success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
6023            """
6024                Lower Tester is sending Data...
6025            """
6026            txData = [_ for _ in range(27)];
6027            for i in range(20):
6028                dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
6029                success = success and dataSent;
6030                if dataSent:
6031                    dataReceived, rxData = readData(transport, upperTester, trace);
6032                    success = success and dataReceived and (len(rxData) == len(txData)) and (rxData == txData);
6033        """
6034            Note: Disconnect can generate another LE Data Length Change event...
6035        """
6036        success = initiator.disconnect(0x13) and success;
6037    else:
6038        success = advertiser.disable() and success;
6039
6040    return success;
6041
6042"""
6043    LL/CON/CEN/BV-77-C [Central Packet Data Length Update - Initiating Packet Data Length Update Procedure; LE 2M PHY]
6044
6045    Last modified: 06-08-2019
6046    Reviewed and verified: 06-08-2019 Henrik Eriksen (Note: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app.)
6047"""
6048def ll_con_cen_bv_77_c(transport, upperTester, lowerTester, trace):
6049
6050    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
6051    """
6052        Obtain maximum Data Packet size and maximum number of Data Packets
6053    """
6054    success, maxPacketLength, maxPacketNumbers = readBufferSize(transport, lowerTester, trace);
6055    maxPacketTime, cmaxTxOctets, cmaxTxTime = calcMaxPacketTime(maxPacketLength), 27, 328;
6056
6057    success = advertiser.enable() and success;
6058    connected = initiator.connect();
6059    success = success and connected;
6060
6061    if connected:
6062        """
6063            Feature exchange as specified in LL.TS.5.1.1, chapter 4.1.5
6064        """
6065        success = readRemoteFeatures(transport, upperTester, initiator.handles[0], trace) and success;
6066        hasFeatures, handle, features = hasReadRemoteFeaturesCompleteEvent(transport, upperTester, trace);
6067        showLEFeatures(features, trace);
6068
6069        allPhys, txPhys, rxPhys, optionPhys = 0, 2, 2, 0;
6070
6071        success = initiator.updatePhys(allPhys, txPhys, rxPhys, optionPhys) and success;
6072        success = (initiator.txPhys == txPhys) and (initiator.rxPhys == rxPhys) and success
6073
6074        for txOctets, txTime in zip( [ maxPacketLength, 27, 251, maxPacketLength, 27, 251, maxPacketLength, 27, 251, maxPacketLength, 27, 251 ], \
6075                                     [ maxPacketTime, maxPacketTime, maxPacketTime, 328, 328, 328, 2120, 2120, 2120, 2120, 2120, 2120 ] ):
6076
6077            success = setDataLength(transport, upperTester, initiator.handles[0], txOctets, txTime, trace) and success;
6078            requested = success;
6079            success = success or (not success and ((txOctets > maxPacketLength) or (txTime > maxPacketTime)));
6080
6081            changed = not ((cmaxTxOctets == min(txOctets, maxPacketLength)) and ((cmaxTxTime == max(txTime, 328))));
6082
6083            if requested and changed:
6084                gotEvent, handle, cmaxTxOctets, cmaxTxTime, maxRxOctets, maxRxTime = hasDataLengthChangedEvent(transport, upperTester, trace);
6085                if not gotEvent:
6086                    trace.trace(7, "Missing Data Length Changed Event from upperTester!");
6087                success = success and gotEvent;
6088                gotEvent = hasDataLengthChangedEvent(transport, lowerTester, trace)[0];
6089                if not gotEvent:
6090                    trace.trace(7, "Missing Data Length Changed Event from lowerTester!");
6091                success = success and gotEvent;
6092
6093            pbFlags = 0
6094            """
6095                Upper Tester is sending Data...
6096            """
6097            txData = [_ for _ in range(maxPacketLength)]
6098            dataSent = writeData(transport, upperTester, initiator.handles[0], pbFlags, txData, trace);
6099            success = success and dataSent;
6100            if dataSent:
6101                dataReceived, rxData = readDataFragments(transport, lowerTester, trace);
6102                success = success and dataReceived and (len(rxData) == len(txData));
6103            """
6104                Lower Tester is sending Data...
6105            """
6106            txData = [_ for _ in range(27)]
6107            for i in range(20):
6108                dataSent = writeData(transport, lowerTester, initiator.handles[1], pbFlags, txData, trace);
6109                success = success and dataSent;
6110                if dataSent:
6111                    dataReceived, rxData = readData(transport, upperTester, trace);
6112                    success = success and dataReceived and (len(rxData) == len(txData));
6113        """
6114            Note: Disconnect can generate another LE Data Length Change event...
6115        """
6116        success = initiator.disconnect(0x13) and success;
6117    else:
6118        success = advertiser.disable() and success;
6119
6120    return success;
6121
6122"""
6123    LL/CON/CEN/BI-06-C [Central responds to Connection Parameter Request - illegal parameters]
6124
6125    Last modified: 06-08-2019
6126    Reviewed and verified: 06-08-2019 Henrik Eriksen
6127"""
6128def ll_con_cen_bi_06_c(transport, upperTester, lowerTester, trace):
6129
6130    advertiser, initiator = setPublicInitiator(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED);
6131
6132    success = advertiser.enable();
6133    connected = initiator.connect();
6134    success = success and connected;
6135
6136    if connected:
6137        interval, timeout = 4, 300;
6138        """
6139            Lower tester requests an update of the connection parameters - sends an LL_CONNECTION_PARAM_REQ...
6140            NOTE: We use a little nasty trick here. Swap the roles of initiator and peer and swap assigned handles...
6141        """
6142        initiator.switchRoles();
6143
6144        success = initiator.update(interval, interval, initiator.latency, timeout) and success;
6145        """
6146            Verify that the update was rejected...
6147        """
6148        success = not initiator.updated() and (initiator.status == 0x1E) and success;
6149
6150        initiator.resetRoles();
6151
6152        success = initiator.disconnect(0x13) and success;
6153    else:
6154        success = advertiser.disable() and success;
6155
6156    return success;
6157
6158"""
6159    LL/SEC/ADV/BV-01-C [Changing Static Address while Advertising]
6160
6161    Last modified: 07-08-2019
6162    Reviewed and verified: 07-08-2019 Henrik Eriksen (NOTE: Test fails - test specification is omitting Filter Accept List addition!)
6163"""
6164def ll_sec_adv_bv_01_c(transport, upperTester, lowerTester, trace):
6165
6166    advertiser, scanner = setPrivateActiveScanning(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 30, 5, \
6167                                                   ExtendedAddressType.RANDOM, ExtendedAddressType.RANDOM, AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6168    adData = ADData();
6169    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT' );
6170    """
6171        Adding lowerTester address to the Filter Accept List
6172    """
6173    success = addAddressesToFilterAcceptList(transport, upperTester, [ randomIdentityAddress(lowerTester) ], trace);
6174
6175    success = advertiser.enable();
6176    success = scanner.enable() and success;
6177    scanner.monitor();
6178    """
6179        Attempt to change advertiser (upperTester) address...
6180    """
6181    status = le_set_random_address(transport, upperTester, toArray(address_scramble_OUI( toNumber(tests.test_utils.upperRandomAddress) ), 6), 100);
6182    trace.trace(6, "LE Set Random Address Command returns status: 0x%02X" % status);
6183    success = getCommandCompleteEvent(transport, upperTester, trace) and (status == 0x0C) and success;
6184
6185    success = scanner.disable() and success;
6186    success = success and scanner.qualifyReports( 5 );
6187    success = success and scanner.qualifyResponses( 5, advertiser.responseData);
6188
6189    success = advertiser.disable() and success;
6190
6191    return success;
6192
6193"""
6194    LL/SEC/ADV/BV-02-C [Non Connectable Undirected Advertising with non-resolvable private address]
6195
6196    Last modified: 07-08-2019
6197    Reviewed and verified: 07-08-2019 Henrik Eriksen
6198"""
6199def ll_sec_adv_bv_02_c(transport, upperTester, lowerTester, trace):
6200
6201    """
6202        Make sure that random address for upperTester is a non-resolvable private addresses
6203    """
6204    setNonResolvableRandomAddress(transport, upperTester, trace);
6205
6206    advertiser, scanner = setPrivatePassiveScanning(transport, lowerTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 100, \
6207                                                    ExtendedAddressType.RESOLVABLE_OR_RANDOM, ExtendedAddressType.PUBLIC);
6208    """
6209        Add Random address of upperTester to the Resolving List
6210    """
6211    RPA = ResolvableAddresses( transport, upperTester, trace );
6212    success = RPA.add( publicIdentityAddress( lowerTester ) );
6213    """
6214        Enable Private Address Resolution
6215     """
6216    success = RPA.timeout( 60 ) and success;
6217    success = RPA.enable() and success;
6218
6219    """
6220        Start NON_CONNECTABLE_ADVERTISING using non-resolvable private adddress
6221    """
6222    success = advertiser.enable() and success;
6223    success = scanner.enable() and success;
6224    scanner.monitor()
6225    success = scanner.disable() and success;
6226    success = success and scanner.qualifyReports( 100, randomIdentityAddress(upperTester) );
6227
6228    success = advertiser.disable() and success;
6229    success = RPA.disable() and success;
6230
6231    return success;
6232
6233"""
6234    LL/SEC/ADV/BV-03-C [Non Connectable Undirected Advertising with resolvable private address]
6235
6236    Last modified: 21-08-2019
6237    Reviewed and verified: 21-08-2019 Henrik Eriksen
6238    Change: ReadLocalResolvableAddress() -> ReadPeerResolvableAddress()
6239"""
6240def ll_sec_adv_bv_03_c(transport, upperTester, lowerTester, trace):
6241
6242    advertiser, scanner = setPrivatePassiveScanning(transport, lowerTester, trace, Advertising.NON_CONNECTABLE_UNDIRECTED, 20);
6243    """
6244        Add Public address of lowerTester to the Resolving List with the upperIRK
6245    """
6246    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace ) ];
6247    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6248    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester) ) and success;
6249    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6250    """
6251        Set resolvable private address timeout in seconds ( two and sixty seconds )
6252    """
6253    success = RPAs[upperTester].timeout( 2 ) and RPAs[lowerTester].timeout( 60 ) and success;
6254    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6255
6256    resolvableAddresses = [ 0, 0 ];
6257    success = advertiser.enable() and success;
6258
6259    for n in range(2):
6260        success = scanner.enable() and success;
6261        scanner.monitor();
6262        success = scanner.disable() and success;
6263        success = success and scanner.qualifyReports( 20, resolvablePublicAddress(upperTester) );
6264        """
6265            Read local address in resolving list.
6266        """
6267        addressRead, resolvableAddresses[n] = readPeerResolvableAddress(transport, lowerTester, publicIdentityAddress(upperTester), trace);
6268        trace.trace(6, "Local Resolvable Address: %s" % formatAddress(resolvableAddresses[n]));
6269
6270        if n == 0:
6271            transport.wait(2000); # Wait for RPA timeout to expire
6272
6273    success = advertiser.disable() and success;
6274    success = success and toNumber(resolvableAddresses[0]) != toNumber(resolvableAddresses[1]);
6275    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6276
6277    return success;
6278
6279"""
6280    LL/SEC/ADV/BV-04-C [Scannable Undirected Advertising with non-resolvable private address]
6281
6282    Last modified: 07-08-2019
6283    Reviewed and verified: 07-08-2019 Henrik Eriksen
6284"""
6285def ll_sec_adv_bv_04_c(transport, upperTester, lowerTester, trace):
6286
6287    """
6288        Make sure that random addresses for lower- and upper-Tester are non-resolvable private addresses
6289    """
6290    setNonResolvableRandomAddress(transport, lowerTester, trace);
6291    setNonResolvableRandomAddress(transport, upperTester, trace);
6292
6293    advertiser, scanner = setPrivateActiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 100, 5, \
6294                                                   ExtendedAddressType.RANDOM, ExtendedAddressType.RANDOM);
6295
6296    success = advertiser.enable();
6297    success = scanner.enable() and success;
6298    scanner.monitor();
6299    success = scanner.disable() and success;
6300    success = advertiser.disable() and success;
6301    success = scanner.qualifyReports( 100, randomIdentityAddress(upperTester) ) and success;
6302    success = scanner.qualifyResponses( 5, advertiser.responseData) and success;
6303
6304    return success;
6305
6306"""
6307    LL/SEC/ADV/BV-05-C [Scannable Undirected Advertising with resolvable private address]
6308
6309    Last modified: 07-08-2019
6310    Reviewed and verified: 07-08-2019 Henrik Eriksen
6311"""
6312def ll_sec_adv_bv_05_c(transport, upperTester, lowerTester, trace):
6313
6314    advertiser, scanner = setPrivateActiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20, 1, \
6315                                                   ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
6316                                                   AdvertisingFilterPolicy.FILTER_SCAN_REQUESTS);
6317
6318    """
6319        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6320    """
6321    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6322    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6323    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6324    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6325    """
6326        Adding lowerTester address to the Filter Accept List
6327    """
6328    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6329    """
6330        Set resolvable private address timeout in seconds ( two and sixty seconds )
6331    """
6332    success = RPAs[upperTester].timeout( 2 ) and RPAs[lowerTester].timeout( 60 ) and success;
6333    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6334
6335    success = success and advertiser.enable();
6336
6337    resolvableAddresses = [ 0, 0 ];
6338    for n in range(2):
6339        success = scanner.enable() and success;
6340        scanner.monitor();
6341        success = scanner.disable() and success;
6342        success = scanner.qualifyReports( 20, resolvablePublicAddress(upperTester) ) and success;
6343        success = scanner.qualifyResponses( 1, advertiser.responseData ) and success;
6344
6345        addressRead, resolvableAddresses[n] = readLocalResolvableAddress(transport, upperTester, publicIdentityAddress(lowerTester), trace);
6346        trace.trace(6, "AdvA: %s" % formatAddress(resolvableAddresses[n]));
6347        if n == 0:
6348            transport.wait(2000); # Wait for RPA timeout
6349
6350    success = advertiser.disable() and success;
6351    success = success and toNumber(resolvableAddresses[0]) != toNumber(resolvableAddresses[1]);
6352    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6353
6354    return success;
6355
6356"""
6357    LL/SEC/ADV/BV-06-C [Connecting with Undirected Connectable Advertiser using non-resolvable private address]
6358
6359    Last modified: 07-08-2019
6360    Reviewed and verified: 07-08-2019 Henrik Eriksen
6361"""
6362def ll_sec_adv_bv_06_c(transport, upperTester, lowerTester, trace):
6363
6364    """
6365        Make sure that random address for upperTester is a non-resolvable private addresses
6366    """
6367    setNonResolvableRandomAddress(transport, upperTester, trace);
6368
6369    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
6370                                                ExtendedAddressType.RESOLVABLE_OR_RANDOM, ExtendedAddressType.PUBLIC);
6371
6372    lowerAddresses = [ publicIdentityAddress(lowerTester), \
6373                       Address( ExtendedAddressType.PUBLIC, toNumber(tests.test_utils.lowerRandomAddress) | 0xC00000000000 ), \
6374                       Address( ExtendedAddressType.PUBLIC, toNumber(tests.test_utils.lowerRandomAddress) & 0x3FFFFFFFFFFF ) ];
6375
6376    success = True;
6377    for lowerAddress in lowerAddresses:
6378        advertiser.peerAddress = lowerAddress;
6379        initiator.initiatorAddress = lowerAddress;
6380        initiator.peerAddress = randomIdentityAddress(upperTester);
6381
6382        if lowerAddress.type == ExtendedAddressType.PUBLIC:
6383            success = preamble_set_public_address(transport, lowerTester, toNumber(lowerAddress.address), trace) and success;
6384        else:
6385            success = preamble_set_random_address(transport, lowerTester, toNumber(lowerAddress.address), trace) and success;
6386
6387        success = advertiser.enable() and success;
6388        connected = initiator.connect();
6389        success = connected and success;
6390        if connected:
6391            success = initiator.disconnect(0x13) and success;
6392        else:
6393            success = advertiser.disable() and success;
6394
6395    return success;
6396
6397"""
6398    LL/SEC/ADV/BV-07-C [Connecting with Undirected Connectable Advertiser with Local IRK but no Peer IRK]
6399
6400    Last modified: 07-08-2019
6401    Reviewed and verified: 07-08-2019 Henrik Eriksen (NOTE: Test fails - filtering doesn't work!)
6402"""
6403def ll_sec_adv_bv_07_c(transport, upperTester, lowerTester, trace):
6404
6405    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
6406                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC, \
6407                                                AdvertisingFilterPolicy.FILTER_CONNECTION_REQUESTS);
6408    """
6409        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6410    """
6411    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace ) ];
6412    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6413    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester) ) and success;
6414    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6415    """
6416        Adding lowerTester address to the Filter Accept List
6417    """
6418    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6419    """
6420        Set resolvable private address timeout in seconds ( sixty seconds )
6421    """
6422    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6423    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6424
6425    success = advertiser.enable() and success;
6426    connected = initiator.connect();
6427    success = success and connected;
6428
6429    if connected:
6430        """
6431            Upper tester terminates the connection
6432        """
6433        initiator.switchRoles();
6434        success = initiator.disconnect(0x13) and success;
6435        initiator.resetRoles();
6436    else:
6437        success = advertiser.disable() and success;
6438
6439    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6440
6441    return success;
6442
6443"""
6444    LL/SEC/ADV/BV-08-C [Connecting with Undirected Connectable Advertiser with both Local and Peer IRK]
6445
6446    Last modified: 07-08-2019
6447    Reviewed and verified: 07-08-2019 Henrik Eriksen
6448"""
6449def ll_sec_adv_bv_08_c(transport, upperTester, lowerTester, trace):
6450
6451    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
6452                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
6453                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6454    """
6455        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6456    """
6457    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6458    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6459    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6460    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6461    """
6462        Adding lowerTester address to the Filter Accept List
6463    """
6464    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6465    """
6466        Set resolvable private address timeout in seconds ( sixty seconds )
6467    """
6468    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6469    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6470
6471    success = advertiser.enable() and success;
6472    connected = initiator.connect();
6473    success = success and connected;
6474
6475    if connected:
6476        """
6477            Upper tester (PERIPHERAL) terminates the connection
6478        """
6479        initiator.switchRoles();
6480        success = initiator.disconnect(0x13) and success;
6481        initiator.resetRoles();
6482    else:
6483        success = advertiser.disable() and success;
6484
6485    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6486
6487    return success;
6488
6489"""
6490    LL/SEC/ADV/BV-09-C [Connecting with Undirected Connectable Advertiser with no Local IRK but peer IRK]
6491
6492    Last modified: 07-08-2019
6493    Reviewed and verified: 07-08-2019 Henrik Eriksen
6494"""
6495def ll_sec_adv_bv_09_c(transport, upperTester, lowerTester, trace):
6496
6497    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
6498                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
6499                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6500    """
6501        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6502    """
6503    RPAs = [ ResolvableAddresses( transport, upperTester, trace ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6504    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6505    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6506    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
6507    """
6508        Adding lowerTester address to the Filter Accept List
6509    """
6510    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6511    """
6512        Set resolvable private address timeout in seconds ( sixty seconds )
6513    """
6514    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6515    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6516
6517    success = advertiser.enable() and success;
6518    connected = initiator.connect();
6519    success = success and connected;
6520
6521    if connected:
6522        """
6523            Upper tester (PERIPHERAL) terminates the connection
6524        """
6525        initiator.switchRoles();
6526        success = initiator.disconnect(0x13) and success;
6527        initiator.resetRoles();
6528    else:
6529        success = advertiser.disable() and success;
6530
6531    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success
6532
6533    return success;
6534
6535"""
6536    LL/SEC/ADV/BV-10-C [Connecting with Undirected Connectable Advertiser where no match for Peer Device Identity]
6537
6538    Last modified: 07-08-2019
6539    Reviewed and verified: 07-08-2019 Henrik Eriksen
6540"""
6541def ll_sec_adv_bv_10_c(transport, upperTester, lowerTester, trace):
6542
6543    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
6544                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
6545                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6546    """
6547        Configure RPAs to use the IRKs for address resolutions
6548    """
6549    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6550    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6551    """
6552        Add Identity Addresses to Resolving Lists
6553    """
6554    bogusIRK = [ random.randint(0,255) for _ in range(16) ];
6555    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), bogusIRK ) and success;
6556    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6557    """
6558        Add Identity Address of lower Tester to Filter Accept List to enable responding to Scan Requests
6559    """
6560    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6561
6562    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6563    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6564
6565    success = advertiser.enable() and success;
6566
6567    for n in range(10):
6568        connected = initiator.connect();
6569        success = success and not connected;
6570        if connected:
6571            success = initiator.disconnect(0x13) and success;
6572            break;
6573
6574    success = advertiser.disable() and success;
6575
6576    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6577
6578    return success;
6579
6580"""
6581    LL/SEC/ADV/BV-11-C [Connecting with Directed Connectable Advertiser using local and remote IRK]
6582
6583    Last modified: 17-12-2019
6584    Reviewed and verified: 17-12-2019 Henrik Eriksen
6585"""
6586def ll_sec_adv_bv_11_c(transport, upperTester, lowerTester, trace):
6587
6588    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED, \
6589                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
6590                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6591    """
6592        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6593    """
6594    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6595    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6596    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6597    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6598    """
6599        Set resolvable private address timeout in seconds ( sixty seconds )
6600    """
6601    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6602    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6603
6604    success = advertiser.enable() and success;
6605    connected = initiator.connect();
6606    success = success and connected;
6607
6608    if connected:
6609        """
6610            Verify that connection was established with resolvable private addresses
6611        """
6612        isRPA = Address( None, initiator.localRPA() ).isResolvablePrivate();
6613        isRPA = Address( None, initiator.peerRPA() ).isResolvablePrivate() and isRPA;
6614        success = isRPA and success;
6615        if not isRPA:
6616            trace.trace(6, "Wrong RPAs - local RPA: %s peer RPA: %s" %(Address( None, initiator.localRPA() ), Address( None, initiator.peerRPA() )));
6617        """
6618            Upper tester (PERIPHERAL) terminates the connection
6619        """
6620        initiator.switchRoles();
6621        success = initiator.disconnect(0x13) and success;
6622        initiator.resetRoles();
6623    else:
6624        success = advertiser.disable() and success;
6625
6626    success = RPAs[upperTester].disable() and success;
6627
6628    advertiserTimeout = False;
6629    success = advertiser.enable() and success;
6630    initiator.checkPrematureDisconnect = False;
6631    """
6632        Retry connection 20 times.
6633    """
6634    for i in range(20):
6635        connected = initiator.connect();
6636        success = success and not connected;
6637        if connected:
6638            success = initiator.disconnect(0x13) and success;
6639            break;
6640        else:
6641            advertiserTimeout, waitTime = False, 0;
6642            while not advertiserTimeout:
6643                flush_events(transport, lowerTester, 100);
6644                advertiserTimeout = advertiser.timeout();
6645                waitTime += 100;
6646                if waitTime >= 1300:
6647                    break;
6648            if advertiserTimeout:
6649                trace.trace(7, "Advertising done!");
6650                success = advertiser.enable(True) and success;
6651            else:
6652                break;
6653
6654    if not advertiserTimeout:
6655        success = advertiser.disable() and success;
6656
6657    return success;
6658
6659"""
6660    LL/SEC/ADV/BV-12-C [Connecting with Directed Connectable Advertising with local IRK but without remote IRK]
6661
6662    Last modified: 21-08-2019
6663    Reviewed and verified: 21-08-2019 Henrik Eriksen
6664    Change: ReadLocalResolvableAddress() -> ReadPeerResolvableAddress()
6665"""
6666def ll_sec_adv_bv_12_c(transport, upperTester, lowerTester, trace):
6667
6668    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED, \
6669                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC);
6670    """
6671        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6672    """
6673    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace ) ];
6674    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6675    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester) ) and success;
6676    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6677    """
6678        Set resolvable private address timeout in seconds ( two seconds )
6679    """
6680    success = RPAs[upperTester].timeout( 2 ) and RPAs[lowerTester].timeout( 2 ) and success;
6681    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6682
6683    privateAddresses = [ 0, 0 ];
6684
6685    success = advertiser.enable() and success;
6686    connected = initiator.connect();
6687    success = success and connected;
6688
6689    if connected:
6690        """
6691            Read the resolvable address used in the AdvA field
6692        """
6693        addressRead, privateAddresses[0] = readPeerResolvableAddress(transport, lowerTester, publicIdentityAddress(upperTester), trace);
6694        trace.trace(6, "AdvA Address: %s" % formatAddress(privateAddresses[0]));
6695        """
6696            Upper tester (PERIPHERAL) terminates the connection
6697        """
6698        initiator.switchRoles();
6699        success = initiator.disconnect(0x13) and success;
6700        initiator.resetRoles();
6701
6702        transport.wait( 2000 ); # wait for RPA to timeout
6703        """
6704            Extra connect step is necassary in order to the read the
6705        """
6706        success = advertiser.enable() and success;
6707        connected = initiator.connect();
6708        success = success and connected;
6709
6710        if connected:
6711            """
6712                Read the resolvable address used in the AdvA field
6713            """
6714            addressRead, privateAddresses[1] = readPeerResolvableAddress(transport, lowerTester, publicIdentityAddress(upperTester), trace);
6715            trace.trace(6, "AdvA Address: %s" % formatAddress(privateAddresses[1]));
6716
6717            success = initiator.disconnect(0x13) and success;
6718        else:
6719            success = advertiser.disable() and success;
6720    else:
6721        success = advertiser.disable() and success;
6722
6723    success = success and (privateAddresses[0] != privateAddresses[1]);
6724    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6725
6726    return success;
6727
6728"""
6729    LL/SEC/ADV/BV-13-C [Directed Connectable Advertising without local IRK but with remote IRK]
6730
6731    Last modified: 07-08-2019
6732    Reviewed and verified: 07-08-2019 Henrik Eriksen (NOTE: Test fails!)
6733"""
6734def ll_sec_adv_bv_13_c(transport, upperTester, lowerTester, trace):
6735
6736    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED, \
6737                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
6738                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6739    """
6740        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6741    """
6742    RPAs = [ ResolvableAddresses( transport, upperTester, trace ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6743    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6744    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6745    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester) ) and success;
6746    """
6747        Set resolvable private address timeout in seconds ( two seconds )
6748    """
6749    success = RPAs[upperTester].timeout( 2 ) and RPAs[lowerTester].timeout( 2 ) and success;
6750    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6751
6752    privateAddresses = [ 0, 0 ];
6753
6754    success = advertiser.enable() and success;
6755    connected = initiator.connect();
6756    success = success and connected;
6757
6758    if connected:
6759        """
6760            Read the resolvable address used in the AdvA field
6761        """
6762        addressRead, privateAddresses[0] = readLocalResolvableAddress(transport, lowerTester, publicIdentityAddress(upperTester), trace);
6763        trace.trace(6, "InitA Address: %s" % formatAddress(privateAddresses[0]));
6764        """
6765            Upper tester (PERIPHERAL) terminates the connection
6766        """
6767        initiator.switchRoles();
6768        success = initiator.disconnect(0x13) and success;
6769        initiator.resetRoles();
6770
6771        transport.wait( 2000 ); # wait for RPA to timeout
6772
6773        success = advertiser.enable() and success;
6774        connected = initiator.connect();
6775        success = success and connected;
6776        """
6777            Read the resolvable address used in the AdvA field
6778        """
6779        addressRead, privateAddresses[1] = readLocalResolvableAddress(transport, lowerTester, publicIdentityAddress(upperTester), trace);
6780        trace.trace(6, "InitA Address: %s" % formatAddress(privateAddresses[1]));
6781
6782        success = initiator.disconnect(0x13) and success;
6783    else:
6784        success = advertiser.disable() and success;
6785
6786    success = success and (privateAddresses[0] != privateAddresses[1]);
6787    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6788
6789    return success;
6790
6791"""
6792    LL/SEC/ADV/BV-14-C [Directed Connectable Advertising using Resolving List and Peer Device Identity not in the List]
6793
6794    Last modified: 07-08-2019
6795    Reviewed and verified: 07-08-2019 Henrik Eriksen
6796"""
6797def ll_sec_adv_bv_14_c(transport, upperTester, lowerTester, trace):
6798
6799    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED, \
6800                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.RESOLVABLE_OR_PUBLIC, \
6801                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6802    """
6803        Configure RPAs to use the IRKs for address resolutions
6804    """
6805    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6806    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6807    """
6808        Add Identity Addresses to Resolving Lists
6809    """
6810    bogusIRK = [ random.randint(0,255) for _ in range(16) ];
6811    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), bogusIRK ) and success;
6812    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6813    """
6814        Add Identity Address of lower Tester to Filter Accept List to enable responding to Scan Requests
6815    """
6816    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6817
6818    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6819    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6820
6821    success = advertiser.enable() and success;
6822    connected = initiator.connect();
6823    success = success and not connected;
6824
6825    if connected:
6826        success = initiator.disconnect(0x13) and success;
6827    else:
6828        """
6829            Need to stop connection attempt - otherwies Resolvable List disable will fail with command not allowed...
6830        """
6831        success = initiator.cancelConnect() and success;
6832        success = advertiser.disable() and success;
6833
6834    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6835
6836    return success;
6837
6838"""
6839    LL/SEC/ADV/BV-15-C [Scannable Advertising with resolvable private address, no Scan Response to Identity Address]
6840
6841    Last modified: 07-08-2019
6842    Reviewed and verified: 07-08-2019 Henrik Eriksen
6843"""
6844def ll_sec_adv_bv_15_c(transport, upperTester, lowerTester, trace):
6845
6846    advertiser, scanner = setPrivateActiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20, 1, \
6847                                                   ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC, AdvertisingFilterPolicy.FILTER_SCAN_REQUESTS);
6848    """
6849        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6850    """
6851    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace ) ];
6852    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6853    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6854    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6855    """
6856        Adding lowerTester address to the Filter Accept List
6857    """
6858    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6859    """
6860        Set resolvable private address timeout in seconds ( sixty seconds )
6861    """
6862    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6863    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6864
6865    success = advertiser.enable() and success;
6866
6867    success = scanner.enable() and success;
6868    scanner.monitor();
6869    success = scanner.qualifyReports( 20, resolvablePublicAddress(upperTester) ) and success;
6870    success = not scanner.qualifyResponses( 1 ) and success;
6871    success = scanner.disable() and success;
6872    success = advertiser.disable() and success;
6873
6874    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6875
6876    return success;
6877
6878"""
6879    LL/SEC/ADV/BV-16-C [Undirected Connectable Advertising with resolvable private address; no Connection to Identity Address]
6880
6881    Last modified: 10-09-2019
6882    Reviewed and verified: 10-09-2019 Henrik Eriksen
6883"""
6884def ll_sec_adv_bv_16_c(transport, upperTester, lowerTester, trace):
6885
6886    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
6887                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC, \
6888                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6889    """
6890        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6891    """
6892    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace ) ];
6893    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6894    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6895    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6896    """
6897        Adding lowerTester address to the Filter Accept List
6898    """
6899    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6900    """
6901        Set resolvable private address timeout in seconds ( sixty seconds )
6902    """
6903    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6904    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6905
6906    success = advertiser.enable() and success;
6907    connected = initiator.connect();
6908    success = success and not connected;
6909    if connected:
6910        success = initiator.disconnect(0x13) and success;
6911    else:
6912        success = advertiser.disable() and success;
6913
6914    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6915
6916    return success;
6917
6918"""
6919    LL/SEC/ADV/BV-17-C [Directed Connectable Advertising using local and remote IRK, Ignore Identity Address]
6920
6921    Last modified: 08-08-2019
6922    Reviewed and verified: 08-08-2019 Henrik Eriksen
6923"""
6924def ll_sec_adv_bv_17_c(transport, upperTester, lowerTester, trace):
6925
6926    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED, \
6927                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC, \
6928                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
6929    """
6930        Add Identity addresses of upperTester and lowerTester to respective Resolving Lists with the distributed IRKs
6931    """
6932    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6933    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6934    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6935    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6936    """
6937        Set resolvable private address timeout in seconds ( sixty seconds )
6938    """
6939    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6940    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6941
6942    success = advertiser.enable() and success;
6943    connected = initiator.connect();
6944    success = success and not connected;
6945    if connected:
6946        success = initiator.disconnect(0x13) and success;
6947    else:
6948        success = advertiser.disable() and success;
6949
6950    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6951
6952    return success
6953
6954"""
6955    LL/SEC/ADV/BV-18-C [Scannable Advertising with resolvable private address, accept Identity Address]
6956
6957    Last modified: 08-08-2019
6958    Reviewed and verified: 08-08-2019 Henrik Eriksen
6959"""
6960def ll_sec_adv_bv_18_c(transport, upperTester, lowerTester, trace):
6961
6962    advertiser, scanner = setPrivateActiveScanning(transport, lowerTester, trace, Advertising.SCANNABLE_UNDIRECTED, 20, 1, \
6963                                                   ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC);
6964    """
6965        Configure RPAs to use the IRKs for address resolutions
6966    """
6967    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
6968    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
6969    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
6970    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
6971    """
6972        Set Device Privacy
6973    """
6974    success = setPrivacyMode(transport, upperTester, publicIdentityAddress(lowerTester), PrivacyMode.DEVICE_PRIVACY, trace) and success;
6975    """
6976        Add Identity Address of lower Tester to Filter Accept List to enable responding to Scan Requests
6977    """
6978    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
6979    """
6980        Set resolvable private address timeout in seconds ( sixty seconds )
6981    """
6982    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
6983    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
6984
6985    success = advertiser.enable() and success;
6986    success = scanner.enable() and success;
6987    scanner.monitor();
6988    success = scanner.disable() and success;
6989    success = advertiser.disable() and success;
6990    success = scanner.qualifyReports( 20, resolvablePublicAddress(upperTester) ) and success;
6991    success = scanner.qualifyResponses( 1, advertiser.responseData ) and success;
6992
6993    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
6994
6995    return success;
6996
6997"""
6998    LL/SEC/ADV/BV-19-C [Undirected Connectable Advertising with Local IRK and Peer IRK, accept Identity Address]
6999
7000    Last modified: 08-08-2019
7001    Reviewed and verified: 08-08-2019 Henrik Eriksen (NOTE: Test fails!)
7002"""
7003def ll_sec_adv_bv_19_c(transport, upperTester, lowerTester, trace):
7004
7005    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_UNDIRECTED, \
7006                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC, \
7007                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
7008    """
7009        Configure RPAs to use the IRKs for address resolutions
7010    """
7011    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
7012    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
7013    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
7014    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
7015    """
7016        Set Device Privacy
7017    """
7018    success = setPrivacyMode(transport, upperTester, publicIdentityAddress(lowerTester), PrivacyMode.DEVICE_PRIVACY, trace) and success;
7019    """
7020        Add Identity Address of lower Tester to Filter Accept List to enable responding to Scan Requests
7021    """
7022    success = addAddressesToFilterAcceptList(transport, upperTester, [ publicIdentityAddress(lowerTester) ], trace) and success;
7023    """
7024        Set resolvable private address timeout in seconds ( two and sixty seconds )
7025    """
7026    success = RPAs[upperTester].timeout( 2 ) and RPAs[lowerTester].timeout( 60 ) and success;
7027    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
7028
7029    success = advertiser.enable() and success;
7030    connected = initiator.connect();
7031    success = success and connected;
7032
7033    if connected:
7034        transport.wait(2100); # Wait for address renewal
7035        success = initiator.disconnect(0x13) and success;
7036    else:
7037        success = advertiser.disable() and success;
7038
7039    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
7040
7041    return success;
7042
7043"""
7044    LL/SEC/ADV/BV-20-C [Directed Connectable Advertising with resolvable private address; Connect to Identity Address]
7045
7046    Last modified: 08-08-2019
7047    Reviewed and verified: 08-08-2019 Henrik Eriksen
7048"""
7049def ll_sec_adv_bv_20_c(transport, upperTester, lowerTester, trace):
7050
7051    advertiser, initiator = setPrivateInitiator(transport, lowerTester, trace, Advertising.CONNECTABLE_HDC_DIRECTED, \
7052                                                ExtendedAddressType.RESOLVABLE_OR_PUBLIC, ExtendedAddressType.PUBLIC, \
7053                                                AdvertisingFilterPolicy.FILTER_BOTH_REQUESTS);
7054    """
7055        Configure RPAs to use the IRKs for address resolutions
7056    """
7057    RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ];
7058    success = RPAs[upperTester].clear() and RPAs[lowerTester].clear();
7059    success = RPAs[upperTester].add( publicIdentityAddress(lowerTester), lowerIRK ) and success;
7060    success = RPAs[lowerTester].add( publicIdentityAddress(upperTester), upperIRK ) and success;
7061    """
7062        Set Device Privacy
7063    """
7064    success = setPrivacyMode(transport, upperTester, publicIdentityAddress(lowerTester), PrivacyMode.DEVICE_PRIVACY, trace) and success;
7065    """
7066        Set resolvable private address timeout in seconds ( sixty seconds )
7067    """
7068    success = RPAs[upperTester].timeout( 60 ) and RPAs[lowerTester].timeout( 60 ) and success;
7069    success = RPAs[upperTester].enable() and RPAs[lowerTester].enable() and success;
7070
7071    success = advertiser.enable() and success;
7072    connected = initiator.connect();
7073    success = success and connected;
7074
7075    if connected:
7076        success = initiator.disconnect(0x13) and success;
7077    else:
7078        success = advertiser.disable() and success;
7079
7080    success = RPAs[upperTester].disable() and RPAs[lowerTester].disable() and success;
7081
7082    return success
7083
7084"""
7085    LL/SEC/SCN/BV-01-C [Changing Static Address while Scanning]
7086
7087    Last modified: 08-08-2019
7088    Reviewed and verified: 08-08-2019 Henrik Eriksen
7089"""
7090def ll_sec_scn_bv_01_c(transport, upperTester, lowerTester, trace):
7091
7092    advertiser, scanner = setPrivateActiveScanning(transport, upperTester, trace, Advertising.CONNECTABLE_UNDIRECTED, 20, 1, \
7093                                                   ExtendedAddressType.RANDOM, ExtendedAddressType.RANDOM);
7094    adData = ADData();
7095    advertiser.responseData = adData.encode( ADType.COMPLETE_LOCAL_NAME, 'IUT' );
7096
7097    success = advertiser.enable();
7098    success = scanner.enable() and success;
7099    scanner.monitor();
7100    """
7101        Attempt to change scanner (upperTester) address...
7102    """
7103    status = le_set_random_address(transport, upperTester, toArray(address_scramble_OUI( toNumber(tests.test_utils.upperRandomAddress) ), 6), 100);
7104    trace.trace(6, "LE Set Random Address Command returns status: 0x%02X" % status);
7105    """
7106        Event queue may hold several Advertising Events...
7107    """
7108    while not getCommandCompleteEvent(transport, upperTester, trace):
7109        pass;
7110    success = (status == 0x0C) and success;
7111
7112    success = scanner.disable() and success;
7113    success = scanner.qualifyReports( 20, randomIdentityAddress(lowerTester) ) and success;
7114    success = scanner.qualifyResponses( 5, advertiser.responseData) and success;
7115
7116    success = advertiser.disable() and success;
7117
7118    address = toNumber( randomIdentityAddress(lowerTester).address );
7119    randAddr = (address >> 24) & 0xFFFFFF;
7120    hashAddr = address & 0xFFFFFF;
7121
7122    trace.trace(8, "Address parts: rand: 0x%06X hash: 0x%06X" % (randAddr, hashAddr));
7123    ok, localHash = encrypt(transport, upperTester, lowerIRK, toArray(randAddr, 16), trace);
7124    success = success and ok and (toNumber(localHash) & 0xFFFFFF == hashAddr);
7125    trace.trace(8, "Regenerated: hash: 0x%06X" % (toNumber(localHash) & 0xFFFFFF));
7126
7127    return success;
7128
7129
7130def cis_setup_response_procedure_peripheral(transport, upper_tester, lower_tester, trace, params):
7131    """
7132    [CIS Setup Response Procedure, Peripheral]
7133    """
7134    success, initiator, _, (cisConnectionHandle,) = \
7135        state_connected_isochronous_stream(transport, upper_tester, lower_tester, trace, params)
7136
7137    # 10. The Lower Tester sends data packets to the IUT.
7138    # 11. The Upper Tester IUT sends an ISO data packet to the Upper Tester.
7139    def lt_send_data_packet(pkt_seq_num):
7140        return iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, cisConnectionHandle,
7141                                    params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, pkt_seq_num)
7142
7143    # 12. Perform either Alternative 12A or 12B depending on whether P_To_C Payload (PDU) in Table 4.146 is 0:
7144    #     Alternative 12A (P_To_C Payload (PDU) is not equal to 0):
7145    #       12A.1. TODO: The IUT sends an Ack to the Lower Tester.
7146    #     Alternative 12B (P_To_C Payload (PDU) is equal to 0):
7147    #       12B.1. TODO: The IUT sends a CIS Null PDU to the Lower Tester.
7148
7149    # 13. Repeat steps 10-12 a total of 50 times.
7150    for j in range(50):
7151        success = lt_send_data_packet(j) and success
7152
7153    ### TERMINATION ###
7154    success = initiator.disconnect(0x13) and success
7155
7156    return success
7157
7158
7159"""
7160    LL/CIS/PER/BV-01-C [CIS Setup Response Procedure, Peripheral]
7161"""
7162def ll_cis_per_bv_01_c(transport, upperTester, lowerTester, trace):
7163    params = SetCIGParameters(
7164        SDU_Interval_C_To_P     = 7500, # 7.5 ms
7165        SDU_Interval_P_To_C     = 7500, # 7.5 ms
7166        ISO_Interval            = int(7.5 // 1.25), # 7.5
7167        NSE                     = 2,
7168        Max_PDU_C_To_P          = 60, # TODO: Supposed to be 160
7169        Max_PDU_P_To_C          = 60, # TODO: Supposed to be 160
7170        PHY_C_To_P              = 1,
7171        PHY_P_To_C              = 1,
7172        FT_C_To_P               = 1,
7173        FT_P_To_C               = 1,
7174        BN_C_To_P               = 1,
7175        BN_P_To_C               = 1,
7176    )
7177
7178    return cis_setup_response_procedure_peripheral(transport, upperTester, lowerTester, trace, params)
7179
7180
7181def cis_setup_peripheral_rejected(transport, peripheral, central, trace):
7182    success = True
7183
7184    status = le_set_host_feature(transport, central, FeatureSupport.ISOCHRONOUS_CHANNELS, 1, 100)
7185    success = getCommandCompleteEvent(transport, central, trace) and (status == 0x00) and success
7186
7187    status = le_set_host_feature(transport, peripheral, FeatureSupport.ISOCHRONOUS_CHANNELS, 1, 100)
7188    success = getCommandCompleteEvent(transport, peripheral, trace) and (status == 0x00) and success
7189
7190    advertiser, initiator = setPublicInitiator(transport, central, trace, Advertising.CONNECTABLE_UNDIRECTED)
7191    success = advertiser.enable() and success
7192    connected = initiator.connect()
7193    success = success and connected
7194
7195    if not connected:
7196        success = advertiser.disable() and success
7197        return success
7198
7199    # 1. The Upper Tester sends an HCI_LE_Set_Event_Mask command with all events enabled,
7200    #    including the HCI_LE_CIS_Request event. The IUT sends a successful
7201    #    HCI_Command_Complete in response.
7202    #
7203    # NOTE: This is already performed during the preamble step
7204
7205    # 2. The Lower Tester sends an LL_CIS_REQ PDU with valid data as specified for the Set CIG
7206    #    Parameters command in Section 4.10.1.3 Default Values for Set CIG Parameters Commands to
7207    #    the IUT.
7208    # NOTE: CIG_ID is hardcoded to 0
7209    params = SetCIGParameters()
7210
7211    status, cigId, cisCount, cis_handle_central = \
7212    le_set_cig_parameters_test(transport, central, 0, *params.get_cig_parameters_test(), 100)
7213    success = getCommandCompleteEvent(transport, central, trace) and (status == 0x00) and success
7214
7215    status = le_create_cis(transport, central, 1, cis_handle_central, [initiator.handles[0]], 100)
7216    success = verifyAndShowEvent(transport, central, Events.BT_HCI_EVT_CMD_STATUS, trace) and (status == 0) and success
7217
7218    # 3. The Upper Tester receives an HCI_LE_CIS_Request event from the IUT.
7219    s, event = verifyAndFetchMetaEvent(transport, peripheral, MetaEvents.BT_HCI_EVT_LE_CIS_REQUEST, trace)
7220    success = s and success
7221    aclConnectionHandle, cis_handle_peripheral, cigId, cisId = event.decode()
7222
7223    # 4. The Upper Tester sends an HCI_LE_Reject_CIS_Request command to the IUT with a valid
7224    #    reason code and receives a successful return status.
7225    status, _ = le_reject_cis_request(transport, peripheral, cis_handle_peripheral, 0x0D, 100)
7226
7227    # 5. The Upper Tester receives an HCI_Command_Complete event from the IUT.
7228    success = getCommandCompleteEvent(transport, peripheral, trace) and (status == 0x00) and success
7229
7230    # 6. The Lower Tester receives an LL_REJECT_EXT_IND from the IUT with a valid reason code.
7231    s, event = verifyAndFetchMetaEvent(transport, central, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace)
7232    success = s and (event.decode()[0] == 0x0D) and success
7233
7234    ### TERMINATION ###
7235    success = initiator.disconnect(0x13) and success
7236
7237    return success
7238
7239
7240def ll_cis_per_bv_02_c(transport, upperTester, lowerTester, trace):
7241    """LL/CIS/PER/BV-02-C [CIS Setup Response Procedure, Peripheral, Reject Response]"""
7242    return cis_setup_peripheral_rejected(transport, upperTester, lowerTester, trace)
7243
7244
7245def test_cis_map_update(transport, peripheral, central, trace, bn_c_to_p, nse, sdu_interval_c_to_p):
7246    params = SetCIGParameters(
7247        SDU_Interval_C_To_P     = sdu_interval_c_to_p,
7248        ISO_Interval            = int(100 // 1.25),  # 100 ms
7249        NSE                     = nse,
7250        Max_PDU_P_To_C          = 0,
7251        BN_C_To_P               = bn_c_to_p,
7252        BN_P_To_C               = 0,
7253    )
7254
7255    success, initiator, _, (cis_conn_handle,) = \
7256        state_connected_isochronous_stream(transport, peripheral, central, trace, params)
7257    if not initiator:
7258        return success
7259
7260    acl_handle = initiator.handles[1]
7261    channel_map_new = 0x1249249249
7262    success = channelMapUpdate(transport, central, channel_map_new, trace) and success
7263
7264    instant_to = initiator.prevInterval * 10  # TODO: calculate based on LL_CHANNEL_MAP_IND PDU instant
7265    transport.wait(instant_to)
7266    status, handle, channel_map = le_read_channel_map(transport, peripheral, acl_handle, 100)
7267    success = getCommandCompleteEvent(transport, peripheral, trace) and status == 0x00 and handle == acl_handle and success
7268
7269    success = channel_map == channel_map_new and success
7270
7271    # 4. The Lower Tester sends data packets to the IUT.
7272    for pkt_seq_num in range(50):
7273        success = iso_send_payload_pdu(transport, central, peripheral, trace, cis_conn_handle,
7274                                       params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, pkt_seq_num) and success
7275
7276    ### TERMINATION ###
7277    success = initiator.disconnect(0x13) and success
7278
7279    return success
7280
7281
7282"""
7283    LL/CIS/PER/BV-03-C [CIS Map Update]
7284"""
7285def ll_cis_per_bv_03_c(transport, upper_tester, lower_tester, trace):
7286    return test_cis_map_update(transport, upper_tester, lower_tester, trace, 0x01, 0x01, 100000)
7287
7288
7289"""
7290    LL/CIS/PER/BV-37-C [CIS Map Update]
7291"""
7292def ll_cis_per_bv_37_c(transport, upper_tester, lower_tester, trace):
7293    return test_cis_map_update(transport, upper_tester, lower_tester, trace, 0x02, 0x02, 50000)
7294
7295
7296"""
7297    LL/CIS/PER/BV-05-C [Receiving data in Unidirectional CIS]
7298"""
7299def ll_cis_per_bv_05_c(transport, upperTester, lowerTester, trace):
7300    # Establish Initial Condition
7301    #
7302    # Connected in the relevant role as defined in the following initial states:
7303    #
7304    # Note: “default” refers to values specified in Section 4.10.1.3 Default Values for Set CIG Parameters
7305    # Commands.
7306
7307    # Table 4.126: State Variable Values
7308    # NOTE: As the IUT is the Peripheral, the CIG Parameters are those of the Central
7309    max_cis_nse = get_ixit_value(transport, upperTester, IXITS["TSPX_max_cis_nse"], 100)
7310
7311    params = SetCIGParameters(
7312        SDU_Interval_C_To_P     = 50000,  # 50 ms
7313        SDU_Interval_P_To_C     = 50000,  # 50 ms
7314        ISO_Interval            = int(50 // 1.25), # 50 ms
7315        NSE                     = min(max_cis_nse, 4),  # Note 1: TSPX_max_cis_nse or 0x04, whichever is less
7316        # Max_PDU_P_To_C          = 0,  # TODO: Supposed to be 0
7317        PHY_C_To_P              = 1,
7318        PHY_P_To_C              = 1,
7319        FT_C_To_P               = 1,
7320        FT_P_To_C               = 1,
7321        BN_C_To_P               = 2,
7322        BN_P_To_C               = 1, # TODO: Supposed to be 0
7323    )
7324
7325    success, initiator, _, (cisConnectionHandle,) = \
7326        state_connected_isochronous_stream(transport, upperTester, lowerTester, trace, params)
7327    if not initiator:
7328        return success
7329
7330    for pkt_seq_num in range(3):
7331        success = iso_send_payload_pdu(transport, lowerTester, upperTester, trace, cisConnectionHandle,
7332                                       params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, pkt_seq_num) and success
7333
7334    ### TERMINATION ###
7335    success = initiator.disconnect(0x13) and success
7336
7337    return success
7338
7339
7340def sending_and_receiving_data_complete(transport, central, peripheral, trace, params, cis_handle_pairs, packets_sent):
7341    # Fetch all the EDTT Write ISO Data command responses
7342    success = le_iso_data_write_complete(transport, peripheral, trace, len(packets_sent[peripheral]), 100)
7343    success = le_iso_data_write_complete(transport, central, trace, len(packets_sent[central]), 100) and success
7344
7345    # Fetch all the HCI Number of Completed Packets events
7346    _, conn_handles_p, num_packets_p = \
7347        fetch_number_of_completed_packets(transport, peripheral, trace, len(packets_sent[peripheral]),
7348                                          params.SDU_Interval_P_To_C)
7349    success = len(packets_sent[peripheral]) == sum(num_packets_p) and success
7350
7351    _, conn_handles_c, num_packets_c = \
7352        fetch_number_of_completed_packets(transport, central, trace, len(packets_sent[central]),
7353                                          params.SDU_Interval_C_To_P)
7354    success = len(packets_sent[central]) == sum(num_packets_c) and success
7355
7356    def cis_handle_central(cis_handle_peripheral):
7357        for handle_p, handle_c in cis_handle_pairs:
7358            if handle_p == cis_handle_peripheral:
7359                return handle_c
7360        return -1
7361
7362    def cis_handle_peripheral(cis_handle_central):
7363        for handle_p, handle_c in cis_handle_pairs:
7364            if handle_c == cis_handle_central:
7365                return handle_p
7366        return -1
7367
7368    # Fetch and verify the payloads received
7369    for _ in range(len(packets_sent[peripheral])):
7370        s, cis_handle_c, payload = iso_receive_sdu(transport, central, trace, params.SDU_Interval_P_To_C)
7371        cis_handle_p = cis_handle_peripheral(cis_handle_c)
7372        if (cis_handle_p, payload) in packets_sent[peripheral]:
7373            packets_sent[peripheral].remove((cis_handle_p, payload))
7374            success = success and s
7375        else:
7376            success = False
7377
7378    for _ in range(len(packets_sent[central])):
7379        s, cis_handle_p, payload = iso_receive_sdu(transport, peripheral, trace, params.SDU_Interval_C_To_P)
7380        cis_handle_c = cis_handle_central(cis_handle_p)
7381        if (cis_handle_c, payload) in packets_sent[central]:
7382            packets_sent[central].remove((cis_handle_c, payload))
7383            success = success and s
7384        else:
7385            success = False
7386
7387    return success
7388
7389
7390def test_sending_and_receiving_data_in_multiple_cises(transport, central, peripheral, trace, params,
7391                                                      num_iso_data_packets_per_cis, send_delay_c=0,
7392                                                      adjust_conn_interval=False):
7393    success, initiator, peripheral_cis_handles, central_cis_handles = \
7394        state_connected_isochronous_stream(transport, peripheral, central, trace, params,
7395                                           adjust_conn_interval=adjust_conn_interval)
7396    if not initiator:
7397        return success
7398
7399    cis_handle_pairs = tuple(zip(peripheral_cis_handles, central_cis_handles))
7400
7401    s, _, _, peripheral_iso_buffer_len, _ = readBufferSizeV2(transport, peripheral, trace)
7402    success = s and success
7403    s, _, _, central_iso_buffer_len, _ = readBufferSizeV2(transport, central, trace)
7404    success = s and success
7405
7406    # Repeat all steps 3 times
7407    for round_num in range(3):
7408        packets_sent = {
7409            peripheral: [],
7410            central: [],
7411        }
7412
7413        for i in range(num_iso_data_packets_per_cis):
7414            pkt_seq_num = round_num * num_iso_data_packets_per_cis + i
7415            for j in range(len(peripheral_cis_handles)):
7416                s, sdu = le_iso_data_write_nbytes(transport, peripheral, trace, peripheral_cis_handles[j],
7417                                                  params.Max_SDU_P_To_C[j], pkt_seq_num, peripheral_iso_buffer_len)
7418                success = s and success
7419                packets_sent[peripheral].append((peripheral_cis_handles[j], sdu))
7420
7421            if send_delay_c:
7422                # wait some time so that ISO event begins with central's Null PDU
7423                transport.wait(send_delay_c)
7424
7425            for j in range(len(central_cis_handles)):
7426                s, sdu = le_iso_data_write_nbytes(transport, central, trace, central_cis_handles[j],
7427                                                  params.Max_SDU_C_To_P[j], pkt_seq_num, central_iso_buffer_len)
7428                success = s and success
7429                packets_sent[central].append((central_cis_handles[j], sdu))
7430
7431        success = sending_and_receiving_data_complete(transport, central, peripheral, trace, params, cis_handle_pairs,
7432                                                      packets_sent) and success
7433
7434    ### TERMINATION ###
7435    success = initiator.disconnect(0x13) and success
7436
7437    return success
7438
7439
7440def test_sending_and_receiving_data_in_bidirectional_cis(transport, central, peripheral, trace, enc_keys=None):
7441    # Establish Initial Condition
7442    #
7443    # Connected in the relevant role as defined in the following initial states.
7444    # Note 2: TSPX_max_cis_bn, or 0x03, whichever is less.
7445    cis_nse = min(0x06, get_ixit_value(transport, peripheral, IXITS["TSPX_max_cis_nse"], 100))
7446    cis_bn = min(0x03, get_ixit_value(transport, peripheral, IXITS["TSPX_max_cis_bn"], 100))
7447
7448    params = SetCIGParameters(
7449        SDU_Interval_C_To_P     = 100000,  # 100 ms
7450        SDU_Interval_P_To_C     = 100000,  # 100 ms
7451        FT_C_To_P               = 1,
7452        FT_P_To_C               = 1,
7453        ISO_Interval            = int(300 // 1.25),  # 300 ms
7454        NSE                     = cis_nse,
7455        PHY_C_To_P              = 1,
7456        PHY_P_To_C              = 1,
7457        BN_C_To_P               = cis_bn,
7458        BN_P_To_C               = cis_bn,
7459    )
7460
7461    success, initiator, (peripheral_cis_handle,), (central_cis_handle,) = \
7462        state_connected_isochronous_stream(transport, peripheral, central, trace, params, enc_keys=enc_keys)
7463    if not initiator:
7464        return success
7465
7466    cis_handle_pairs = ((peripheral_cis_handle, central_cis_handle),)
7467
7468    s, _, _, peripheral_iso_buffer_len, _ = readBufferSizeV2(transport, peripheral, trace)
7469    success = s and success
7470    s, _, _, central_iso_buffer_len, _ = readBufferSizeV2(transport, central, trace)
7471    success = s and success
7472
7473    for round_num in range(cis_bn):
7474        if not success:
7475            break
7476
7477        packets_sent = {
7478            peripheral: [],
7479            central: [],
7480        }
7481
7482        success = True
7483        s, sdu = le_iso_data_write_nbytes(transport, central, trace, central_cis_handle, params.Max_SDU_C_To_P[0],
7484                                          round_num, central_iso_buffer_len)
7485        success = s and success
7486        packets_sent[central].append((central_cis_handle, sdu))
7487
7488        s, sdu = le_iso_data_write_nbytes(transport, peripheral, trace, peripheral_cis_handle, params.Max_SDU_P_To_C[0],
7489                                          round_num, peripheral_iso_buffer_len)
7490        success = s and success
7491        packets_sent[peripheral].append((peripheral_cis_handle, sdu))
7492
7493        success = sending_and_receiving_data_complete(transport, central, peripheral, trace, params, cis_handle_pairs,
7494                                                      packets_sent) and success
7495
7496    ### TERMINATION ###
7497    success = initiator.disconnect(0x13) and success
7498
7499    return success
7500
7501
7502"""
7503    LL/CIS/PER/BV-06-C [Sending and Receiving Data in Bidirectional CIS]
7504"""
7505def ll_cis_per_bv_06_c(transport, upper_tester, lower_tester, trace):
7506    return test_sending_and_receiving_data_in_bidirectional_cis(transport, lower_tester, upper_tester, trace)
7507
7508
7509"""
7510    LL/CIS/PER/BV-27-C [Sending and Receiving Data in Bidirectional CIS]
7511"""
7512def ll_cis_per_bv_27_c(transport, upper_tester, lower_tester, trace):
7513    return test_sending_and_receiving_data_in_bidirectional_cis(transport, lower_tester, upper_tester, trace, ENC_KEYS)
7514
7515
7516"""
7517    LL/CIS/PER/BV-07-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG,
7518                        Peripheral]
7519"""
7520def ll_cis_per_bv_07_c(transport, upper_tester, lower_tester, trace):
7521    # Establish Initial Condition
7522    #
7523    # State: Connected Isochronous Stream, Peripheral
7524    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
7525
7526    params = SetCIGParameters(
7527        SDU_Interval_C_To_P     = 50000,  # 50 ms
7528        SDU_Interval_P_To_C     = 50000,  # 50 ms
7529        FT_C_To_P               = 1,
7530        FT_P_To_C               = 1,
7531        ISO_Interval            = int(100 // 1.25),  # 100 ms
7532        Packing                 = 1,
7533        CIS_Count               = 2,
7534        NSE                     = min(max_cis_nse, 4),  # Note 1: TSPX_max_cis_nse or 0x04, whichever is less
7535        PHY_C_To_P              = 1,
7536        PHY_P_To_C              = 1,
7537        BN_C_To_P               = 2,
7538        BN_P_To_C               = 2,
7539    )
7540
7541    # The Lower Tester sends Null PDU to the IUT on CISes first, so lets wait a specific time prior sending ISO Data PDU
7542    lower_tester_send_delay = int(params.ISO_Interval / (params.NSE[0] + params.NSE[1])) + 1
7543
7544    success = test_sending_and_receiving_data_in_multiple_cises(transport, lower_tester, upper_tester, trace, params, 2,
7545                                                                lower_tester_send_delay)
7546
7547    return success
7548
7549
7550def cis_updating_peer_clock_accuracy(transport, upper_tester, lower_tester, trace, role):
7551    assert role == "Peripheral" or role == "Central"
7552    # Initial Condition
7553
7554    # Connected in the relevant role.
7555    # An ACL connection has been established between the IUT and Lower Tester with a valid Connection Handle.
7556    if role == "Peripheral":
7557        success, advertiser, initiator = establish_acl_connection(transport, lower_tester, upper_tester, trace)
7558        acl_conn_handle = initiator.handles[1]
7559    else:
7560        success, advertiser, initiator = establish_acl_connection(transport, upper_tester, lower_tester, trace)
7561        acl_conn_handle = initiator.handles[0]
7562
7563    # 1. The Upper Tester sends an HCI_LE_Request_Peer_SCA command to the IUT with a valid Connection_Handle.
7564    # 2. The Upper Tester receives the Command Status event.
7565    status = le_request_peer_sca(transport, upper_tester, acl_conn_handle, 100)
7566    s = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace)
7567    success = s and status == 0x00 and success
7568
7569    # 3. The Lower Tester receives an LL_CLOCK_ACCURACY_REQ PDU from the IUT and sends back an LL_CLOCK_ACCURACY_RSP
7570    #    PDU with a valid Peer_Clock_Accuracy value.
7571    # 4. The Upper Tester receives an HCI_LE_Request_Peer_SCA_Complete event with the Connection_Handle of the ACL and
7572    #    the Peer_Clock_Accuracy parameter when the HCI_LE_Request_Peer_SCA command completes.
7573    s, event = verifyAndFetchMetaEvent(transport, upper_tester, MetaEvents.BT_HCI_EVT_LE_REQUEST_PEER_SCA_COMPLETE,
7574                                       trace, 1000)
7575    status, conn_handle, peer_clock_accuracy = event.decode()
7576    success = s and status == 0x00 and conn_handle == acl_conn_handle and success
7577
7578    # 5. The Upper Tester sends an HCI_LE_Request_Peer_SCA command to the IUT with a valid, but
7579    # non-existent Connection_Handle and receives the error code Unknown Connection Identifier
7580    # (0x02).
7581    acl_conn_handle_non_existent = (acl_conn_handle + 1) % 0x0EFF
7582    status = le_request_peer_sca(transport, upper_tester, acl_conn_handle_non_existent, 100)
7583    s = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace)
7584    success = s and status == 0x02 and success
7585
7586    ### TERMINATION ###
7587    success = initiator.disconnect(0x13) and success
7588
7589    return success
7590
7591
7592def ll_cis_per_bv_18_c(transport, upper_tester, lower_tester, trace):
7593    """LL/CIS/PER/BV-18-C [CIS Updating Peer Clock Accuracy]"""
7594    return cis_updating_peer_clock_accuracy(transport, upper_tester, lower_tester, trace, "Peripheral")
7595
7596
7597"""
7598    LL/CIS/PER/BV-08-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Sequential,
7599                        Peripheral]
7600"""
7601def ll_cis_per_bv_08_c(transport, upper_tester, lower_tester, trace):
7602    # Establish Initial Condition
7603    #
7604    # State: Connected Isochronous Stream, Peripheral
7605    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
7606
7607    params = SetCIGParameters(
7608        SDU_Interval_C_To_P     = 100000,  # 100 ms
7609        SDU_Interval_P_To_C     = 50000,  # 50 ms
7610        FT_C_To_P               = 1,
7611        FT_P_To_C               = 1,
7612        ISO_Interval            = int(100 // 1.25),  # 100 ms
7613        Packing                 = 0,  # Sequential
7614        CIS_Count               = 2,
7615        NSE                     = min(max_cis_nse, 4),  # Note 1: TSPX_max_cis_nse or 0x04, whichever is less
7616        PHY_C_To_P              = 1,
7617        PHY_P_To_C              = 1,
7618        BN_C_To_P               = 1,
7619        BN_P_To_C               = 2,
7620    )
7621
7622    # The Lower Tester sends Null PDU to the IUT on CISes first, so lets wait a specific time prior sending ISO Data PDU
7623    lower_tester_send_delay = int(params.ISO_Interval / (params.NSE[0] + params.NSE[1])) + 1
7624
7625    success = test_sending_and_receiving_data_in_multiple_cises(transport, lower_tester, upper_tester, trace, params, 2,
7626                                                                lower_tester_send_delay)
7627
7628    return success
7629
7630
7631"""
7632    LL/CIS/PER/BV-19-C [CIS Setup Response Procedure, Peripheral]
7633"""
7634def ll_cis_per_bv_19_c(transport, upperTester, lowerTester, trace):
7635    params = SetCIGParameters(
7636        SDU_Interval_C_To_P     = 11250, # 11.25 ms
7637        SDU_Interval_P_To_C     = 11250, # 11.25 ms
7638        ISO_Interval            = int(11.25 // 1.25), # 11.25 ms
7639        NSE                     = 4,
7640        Max_PDU_C_To_P          = 200,
7641        Max_PDU_P_To_C          = 200,
7642        PHY_C_To_P              = 2,
7643        PHY_P_To_C              = 2,
7644        FT_C_To_P               = 3,
7645        FT_P_To_C               = 2,
7646        BN_C_To_P               = 3,
7647        BN_P_To_C               = 1,
7648    )
7649
7650    return cis_setup_response_procedure_peripheral(transport, upperTester, lowerTester, trace, params)
7651
7652
7653"""
7654    LL/CIS/PER/BV-22-C [CIS Request Event Not Set]
7655"""
7656def ll_cis_per_bv_22_c(transport, upper_tester, lower_tester, trace):
7657    # Initial Condition
7658    #
7659    # The Isochronous Channels (Host Support) FeatureSet bit is clear.
7660    success = set_isochronous_channels_host_support(transport, upper_tester, trace, 0)
7661    success = set_isochronous_channels_host_support(transport, lower_tester, trace, 1) and success
7662
7663    # An ACL connection has been established between the IUT and Lower Tester with the IUT acting as the Peripheral.
7664    s, advertiser, initiator = establish_acl_connection(transport, lower_tester, upper_tester, trace)
7665    success = s and success
7666    if not initiator:
7667        return success
7668
7669    # 1. The Lower Tester sends an LL_CIS_REQ to the IUT with the contents specified per Section 4.10.1.3 Default Values
7670    #    for Set CIG Parameters Commands.
7671    params = SetCIGParameters()
7672
7673    status, cig_id, cis_count, cis_conn_handle = \
7674        le_set_cig_parameters_test(transport, lower_tester, 0, *params.get_cig_parameters_test(), 100)
7675    success = getCommandCompleteEvent(transport, lower_tester, trace) and status == 0x00 and success
7676
7677    def lt_send_ll_cis_req(acl_conn_handle):
7678        status = le_create_cis(transport, lower_tester, cis_count, cis_conn_handle, [acl_conn_handle] * cis_count, 100)
7679        return verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and status == 0 and success
7680
7681    success = lt_send_ll_cis_req(initiator.handles[0]) and success
7682
7683    # 2. The IUT responds to the Lower Tester with an LL_REJECT_EXT_IND with error code Unsupported Remote Feature
7684    #    (0x1A).
7685    s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace)
7686    success = s and (event.decode()[0] == 0x1A) and success
7687
7688    # 3. The IUT disconnects the ACL connection from the Lower Tester.
7689    # TSE ID: 17099: Core does not mandate IUT to disconnect ACL when CIS Request has been rejected.
7690    #                The TS shall be clear that, it is Upper Tester initiated operation, not autonomous IUT operation.
7691    status = disconnect(transport, upper_tester, initiator.handles[1], 0x13, 200)
7692    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and (status == 0) \
7693              and success
7694
7695    s, event = verifyAndFetchEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
7696    status, handle, reason = event.decode()
7697    success = s and (status == 0x00) and handle == initiator.handles[0] and success
7698
7699    s, event = verifyAndFetchEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
7700    status, handle, reason = event.decode()
7701    success = s and (status == 0x00) and handle == initiator.handles[1] and success
7702
7703    # 4. The Upper Tester sends an HCI_LE_Set_Host_Feature command to the IUT with the Bit_Number set to 32 (Isochronous
7704    #    Channels) and the Bit_Value set to 0b1. The Upper Tester receives an HCI_Command_Complete event from the IUT.
7705    success = set_isochronous_channels_host_support(transport, upper_tester, trace, 1) and success
7706
7707    # 5. The IUT establishes an ACL connection with the Lower Tester as Peripheral.
7708    s, advertiser, initiator = establish_acl_connection(transport, lower_tester, upper_tester, trace)
7709    success = s and success
7710    if not initiator:
7711        return success
7712
7713    # 6. The Upper Tester sends an HCI_LE_Set_Event_Mask command with all events enabled except the HCI_LE_CIS_Request
7714    #    event. The IUT sends a successful HCI_Command_Complete in response.
7715    def ut_set_event_mask(event_mask):
7716        status = le_set_event_mask(transport, upper_tester, event_mask, 100)
7717        return getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x00
7718
7719    success = ut_set_event_mask([0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00]) and success
7720
7721    # 7. Repeat step 1.
7722    success = lt_send_ll_cis_req(initiator.handles[0]) and success
7723
7724    # 8. The IUT responds to the Lower Tester with an LL_REJECT_EXT_IND with a valid reason code.
7725    s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace)
7726    success = s and (event.decode()[0] != 0x00) and success
7727
7728    # 9. The Upper Tester does not receive an HCI_LE_CIS_Request event. Confirm for at least 5 seconds.
7729    s, _, _, _, _ = hasLeCisRequestMetaEvent(transport, upper_tester, trace, 5000)
7730    success = not s and success
7731
7732    # 10. The Upper Tester sends an HCI_LE_Set_Event_Mask command with all events enabled including the
7733    #     HCI_LE_CIS_Request event. The IUT sends a successful HCI_Command_Complete in response.
7734    success = ut_set_event_mask([0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00]) and success
7735
7736    # 11. Repeat step 1.
7737    success = lt_send_ll_cis_req(initiator.handles[0]) and success
7738
7739    # 12. The Upper Tester receives an HCI_LE_CIS_Request event.
7740    s, _, _, _, _ = hasLeCisRequestMetaEvent(transport, upper_tester, trace, 5000)
7741    success = s and success
7742
7743    ### TERMINATION ###
7744    success = initiator.disconnect(0x13) and success
7745
7746    return success
7747
7748
7749"""
7750    LL/CIS/PER/BV-23-C [CIS Setup Response Procedure, Peripheral]
7751"""
7752def ll_cis_per_bv_23_c(transport, upper_tester, lower_tester, trace):
7753    params = SetCIGParameters(
7754        SDU_Interval_C_To_P     = 11250,  # 11.25 ms
7755        SDU_Interval_P_To_C     = 11250,  # 11.25 ms
7756        ISO_Interval            = int(11.25 // 1.25),  # 11.25 ms
7757        NSE                     = 4,
7758        Max_PDU_C_To_P          = 100,
7759        Max_PDU_P_To_C          = 100,
7760        PHY_C_To_P              = 2,
7761        PHY_P_To_C              = 1,
7762        FT_C_To_P               = 3,
7763        FT_P_To_C               = 2,
7764        BN_C_To_P               = 3,
7765        BN_P_To_C               = 2,
7766    )
7767
7768    return cis_setup_response_procedure_peripheral(transport, upper_tester, lower_tester, trace, params)
7769
7770
7771"""
7772    LL/CIS/PER/BV-29-C [CIS Setup Response Procedure, Peripheral]
7773"""
7774def ll_cis_per_bv_29_c(transport, upper_tester, lower_tester, trace):
7775    params = SetCIGParameters(
7776        Max_PDU_C_To_P          = 128,
7777        Max_PDU_P_To_C          = 128,
7778        PHY_C_To_P              = 2,
7779        PHY_P_To_C              = 2,
7780        FT_C_To_P               = 1,
7781        FT_P_To_C               = 1,
7782        BN_C_To_P               = 1,
7783        BN_P_To_C               = 1,
7784    )
7785
7786    return cis_setup_response_procedure_peripheral(transport, upper_tester, lower_tester, trace, params)
7787
7788
7789"""
7790    LL/CIS/PER/BV-31-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG,
7791                        Peripheral, NSE=2]
7792"""
7793def ll_cis_per_bv_31_c(transport, upper_tester, lower_tester, trace):
7794    params = SetCIGParameters(
7795        SDU_Interval_C_To_P     = 50000,  # 50 ms
7796        SDU_Interval_P_To_C     = 50000,  # 50 ms
7797        FT_C_To_P               = 1,
7798        FT_P_To_C               = 1,
7799        ISO_Interval            = int(100 // 1.25),  # 100 ms
7800        Packing                 = 1,
7801        CIS_Count               = 2,
7802        NSE                     = 2,
7803        PHY_C_To_P              = 1,
7804        PHY_P_To_C              = 1,
7805        BN_C_To_P               = 2,
7806        BN_P_To_C               = 2,
7807    )
7808
7809    success = test_sending_and_receiving_data_in_multiple_cises(transport, lower_tester, upper_tester, trace, params, 2)
7810
7811    return success
7812
7813
7814"""
7815    LL/CIS/PER/BV-32-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Peripheral, BN=1]
7816"""
7817def ll_cis_per_bv_32_c(transport, upper_tester, lower_tester, trace):
7818    params = SetCIGParameters(
7819        SDU_Interval_C_To_P     = 50000,  # 50 ms
7820        SDU_Interval_P_To_C     = 50000,  # 50 ms
7821        FT_C_To_P               = 1,
7822        FT_P_To_C               = 1,
7823        ISO_Interval            = int(50 // 1.25),  # 50 ms
7824        Packing                 = 1,  # Interleaved
7825        CIS_Count               = 2,
7826        NSE                     = 1,
7827        PHY_C_To_P              = 1,
7828        PHY_P_To_C              = 1,
7829        BN_C_To_P               = 1,
7830        BN_P_To_C               = 1,
7831    )
7832
7833    success = test_sending_and_receiving_data_in_multiple_cises(transport, lower_tester, upper_tester, trace, params, 1)
7834
7835    return success
7836
7837
7838def test_sending_and_receiving_data_in_bidirectional_cis_bn_1(transport, central, peripheral, trace, enc_keys=None):
7839    params = SetCIGParameters(
7840        SDU_Interval_C_To_P     = 100000,  # 100 ms
7841        SDU_Interval_P_To_C     = 100000,  # 100 ms
7842        FT_C_To_P               = 1,
7843        FT_P_To_C               = 1,
7844        ISO_Interval            = int(100 // 1.25),  # 100 ms
7845        NSE                     = 1,
7846        PHY_C_To_P              = 1,
7847        PHY_P_To_C              = 1,
7848        BN_C_To_P               = 1,
7849        BN_P_To_C               = 1,
7850    )
7851
7852    success, initiator, (peripheral_cis_handle,), (central_cis_handle,) = \
7853        state_connected_isochronous_stream(transport, peripheral, central, trace, params, enc_keys=enc_keys)
7854    if not initiator:
7855        return success
7856
7857    # The SDU is equal for both devices
7858    assert params.Max_SDU_C_To_P[0] == params.Max_SDU_P_To_C[0]
7859
7860    iso_data_sdu = tuple([0xD7] * params.Max_SDU_C_To_P[0])
7861
7862    success = iso_send_payload_pdu(transport, peripheral, central, trace, peripheral_cis_handle,
7863                                   params.Max_SDU_P_To_C[0], params.SDU_Interval_P_To_C, 0, iso_data_sdu) and success
7864
7865    success = iso_send_payload_pdu(transport, central, peripheral, trace, central_cis_handle,
7866                                   params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, 0, iso_data_sdu) and success
7867
7868    ### TERMINATION ###
7869    success = initiator.disconnect(0x13) and success
7870
7871    return success
7872
7873
7874"""
7875    LL/CIS/PER/BV-35-C [Sending and Receiving Data in Bidirectional CIS, BN = 1]
7876"""
7877def ll_cis_per_bv_35_c(transport, upper_tester, lower_tester, trace):
7878    return test_sending_and_receiving_data_in_bidirectional_cis_bn_1(transport, lower_tester, upper_tester, trace)
7879
7880
7881"""
7882    LL/CIS/PER/BV-36-C [Sending and Receiving Data in Bidirectional CIS, BN = 1, Encrypted]
7883"""
7884def ll_cis_per_bv_36_c(transport, upper_tester, lower_tester, trace):
7885    return test_sending_and_receiving_data_in_bidirectional_cis_bn_1(transport, lower_tester, upper_tester, trace,
7886                                                                     ENC_KEYS)
7887
7888
7889"""
7890    LL/CIS/PER/BV-33-C [Sending Data in Unidirectional CIS, BN = 1, Peripheral]
7891"""
7892def ll_cis_per_bv_33_c(transport, upper_tester, lower_tester, trace):
7893    params = SetCIGParameters(
7894        SDU_Interval_C_To_P     = 100000,  # 100 ms
7895        SDU_Interval_P_To_C     = 100000,  # 100 ms
7896        FT_C_To_P               = 1,
7897        FT_P_To_C               = 1,
7898        ISO_Interval            = int(100 // 1.25),  # 100 ms
7899        CIS_Count               = 1,
7900        NSE                     = 1,
7901        Max_PDU_C_To_P          = 0,
7902        PHY_C_To_P              = 1,
7903        PHY_P_To_C              = 1,
7904        BN_C_To_P               = 0,
7905        BN_P_To_C               = 1,
7906    )
7907
7908    success, initiator, (cis_conn_handle,), _ = \
7909        state_connected_isochronous_stream(transport, upper_tester, lower_tester, trace, params)
7910    if not initiator:
7911        return success
7912
7913    success = iso_send_payload_pdu(transport, upper_tester, lower_tester, trace, cis_conn_handle,
7914                                   params.Max_SDU_P_To_C[0], params.SDU_Interval_P_To_C, 0) and success
7915
7916    ### TERMINATION ###
7917    success = initiator.disconnect(0x13) and success
7918
7919    return success
7920
7921
7922"""
7923    LL/CIS/PER/BV-34-C [Receiving Data in Unidirectional CIS, BN = 1, Peripheral]
7924"""
7925def ll_cis_per_bv_34_c(transport, upper_tester, lower_tester, trace):
7926    params = SetCIGParameters(
7927        SDU_Interval_C_To_P     = 100000,  # 100 ms
7928        SDU_Interval_P_To_C     = 100000,  # 100 ms
7929        FT_C_To_P               = 1,
7930        FT_P_To_C               = 1,
7931        ISO_Interval            = int(100 // 1.25),  # 100 ms
7932        CIS_Count               = 1,
7933        NSE                     = 1,
7934        Max_PDU_P_To_C          = 0,
7935        PHY_C_To_P              = 1,
7936        PHY_P_To_C              = 1,
7937        BN_C_To_P               = 1,
7938        BN_P_To_C               = 0,
7939    )
7940
7941    success, initiator, _, (cis_conn_handle,) = \
7942        state_connected_isochronous_stream(transport, upper_tester, lower_tester, trace, params)
7943    if not initiator:
7944        return success
7945
7946    success = iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, cis_conn_handle,
7947                                   params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, 0) and success
7948
7949    ### TERMINATION ###
7950    success = initiator.disconnect(0x13) and success
7951
7952    return success
7953
7954
7955"""
7956    LL/CIS/PER/BV-39-C [CIS Peripheral Accepts All Supported NSE Values]
7957"""
7958def ll_cis_per_bv_39_c(transport, upper_tester, lower_tester, trace):
7959    # Initial Condition
7960    #
7961    # The Isochronous Channels (Host Support) FeatureSet bit is set.
7962    success = set_isochronous_channels_host_support(transport, upper_tester, trace, 1)
7963    success = set_isochronous_channels_host_support(transport, lower_tester, trace, 1) and success
7964
7965    # An ACL connection has been established between the IUT and the Lower Tester with a valid Connection Handle.
7966    s, advertiser, initiator = establish_acl_connection(transport, lower_tester, upper_tester, trace)
7967    success = s and success
7968    if not initiator:
7969        return success
7970
7971    max_sdu_length = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_sdu_length"], 100)
7972    max_cis_bn = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_bn"], 100)
7973
7974    # 1. Test_BN represents the BN and NSE values for each round, and its initial value is 1.
7975    test_bn = 1
7976    while True:
7977        # 2. The Lower Tester sends an LL_CIS_REQ to the IUT with BN_C_To_P, BN_P_To_C, and NSE set to Test_BN.
7978        #    FT_C_To_P and FT_P_To_C are 1. ISO_Interval is a valid value and at least 200 ms. All other values are
7979        #    valid values, and Max_SDU_C_To_P and Max_SDU_P_To_C are no greater than TSPX_max_sdu_length.
7980        #    The parameters are configured such that each PDU contains a single SDU.
7981        max_pdu = min(64, max_sdu_length)
7982
7983        # BN = ceil(Max_SDU / Max_PDU) * (ISO_Interval / SDU_Interval), where Max_SDU == Max_PDU, thus
7984        iso_interval = 200
7985        r = iso_interval % test_bn
7986        if r != 0:
7987            iso_interval += (test_bn - r)
7988
7989        sdu_interval = int(iso_interval / test_bn)
7990
7991        params = SetCIGParameters(
7992            SDU_Interval_C_To_P = sdu_interval * 1000,
7993            SDU_Interval_P_To_C = sdu_interval * 1000,
7994            ISO_Interval        = int(iso_interval // 1.25),
7995            NSE                 = test_bn,  # NSE set to Test_BN
7996            Max_PDU_C_To_P      = max_pdu,
7997            Max_PDU_P_To_C      = max_pdu,
7998            FT_C_To_P           = 1,
7999            FT_P_To_C           = 1,
8000            BN_C_To_P           = test_bn,
8001            BN_P_To_C           = test_bn,
8002            Max_SDU_Supported   = max_pdu,  # Each PDU contains a single SDU
8003        )
8004
8005        # 3-10.
8006        s, (lower_tester_cis_handle,), (upper_tester_cis_handle,) = \
8007            establish_cis_connection(transport, lower_tester, upper_tester, trace, params, initiator.handles[0])
8008        success = s and success
8009        if not initiator:
8010            return success
8011
8012        def iso_send_and_receive_payload_pdu(pkt_seq_num):
8013            # 11. The Lower Tester sends data packets to the IUT. All data packets contain data , and there are no
8014            #     zero length data packets.
8015            # 12. The Upper Tester receives ISO data from the IUT.
8016            success = iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, lower_tester_cis_handle,
8017                                           params.Max_PDU_C_To_P[0], params.SDU_Interval_C_To_P, pkt_seq_num)
8018
8019            # 13. The Upper Tester sends ISO data to the IUT sufficient to ensure that all data PDUs contain data
8020            #     and there are no zero length PDUs.
8021            # 14. The Lower Tester receives ISO data from the IUT.
8022            return iso_send_payload_pdu(transport, upper_tester, lower_tester, trace, upper_tester_cis_handle,
8023                                        params.Max_PDU_P_To_C[0], params.SDU_Interval_P_To_C, pkt_seq_num) and success
8024
8025        # 15. Repeat steps 11–15 for 20 ISO intervals.
8026        for pkt_seq_num in range(20):
8027            success = iso_send_and_receive_payload_pdu(pkt_seq_num) and success
8028            if not success:
8029                break
8030
8031        # 16. The Lower Tester sends an LL_CIS_TERMINATE_IND PDU to the IUT and receives an Ack from
8032        # the IUT.
8033        # LT - Initiate CIS Disconnection and verify command status
8034        status = disconnect(transport, lower_tester, lower_tester_cis_handle, 0x13, 200)
8035        success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and (status == 0) \
8036                  and success
8037
8038        # LT - Verify HCI Disconnection Complete event parameters
8039        s, event = verifyAndFetchEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8040        status, handle, reason = event.decode()
8041        success = s and (status == 0x00) and handle == lower_tester_cis_handle and success
8042
8043        # 17. The Upper Tester receives an HCI_Disconnection_Complete event from the IUT.
8044        s, event = verifyAndFetchEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8045        status, handle, reason = event.decode()
8046        success = s and (status == 0x00) and handle == upper_tester_cis_handle and success
8047
8048        # Remove the CIG, since we are going to create the CIG with different parameters
8049        status, _ = le_remove_cig(transport, lower_tester, 0, 100)
8050        success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_COMPLETE, trace) and status == 0 \
8051                  and success
8052
8053        # 18. Test_BN is incremented by 1. If Test_BN exceeds TSPX_max_cis_bn, then the test is complete.
8054        #     If not, go to step 2 to execute the next round.
8055        test_bn += 1
8056        if test_bn > max_cis_bn or not success:
8057            break
8058
8059    ### TERMINATION ###
8060    success = initiator.disconnect(0x13) and success
8061
8062    return success
8063
8064
8065"""
8066    LL/CIS/PER/BV-40-C [CIS Setup Response Procedure, Peripheral]
8067"""
8068def ll_cis_per_bv_40_c(transport, upper_tester, lower_tester, trace):
8069    params = SetCIGParameters(
8070        SDU_Interval_C_To_P     = 7500,  # 7.5 ms
8071        SDU_Interval_P_To_C     = 7500,  # 7.5 ms
8072        ISO_Interval            = int(7.5 // 1.25),  # 7.5
8073        NSE                     = 2,
8074        Max_PDU_C_To_P          = 160,
8075        Max_PDU_P_To_C          = 0,
8076        PHY_C_To_P              = 1,
8077        PHY_P_To_C              = 1,
8078        FT_C_To_P               = 1,
8079        FT_P_To_C               = 1,
8080        BN_C_To_P               = 1,
8081        BN_P_To_C               = 0,
8082    )
8083
8084    return cis_setup_response_procedure_peripheral(transport, upper_tester, lower_tester, trace, params)
8085
8086
8087def cis_terminate_procedure_initiated(transport, upper_tester, lower_tester, trace, role, packets):
8088    assert role == "Peripheral" or role == "Central"
8089    params = SetCIGParameters(
8090            SDU_Interval_C_To_P     = 20000,
8091            SDU_Interval_P_To_C     = 20000,
8092            ISO_Interval            = int(20 // 1.25),
8093            NSE                     = 1,
8094            Max_SDU_C_To_P          = 130,
8095            Max_SDU_P_To_C          = 130,
8096            Max_PDU_C_To_P          = 130,
8097            Max_PDU_P_To_C          = 130,
8098            PHY_C_To_P              = 1,
8099            PHY_P_To_C              = 1,
8100            FT_C_To_P               = 1,
8101            FT_P_To_C               = 1,
8102            BN_C_To_P               = 1,
8103            BN_P_To_C               = 1,
8104    )
8105
8106    if role == "Peripheral":
8107        success, initiator, (upper_tester_cis_handle,), (lower_tester_cis_handle,) = \
8108            state_connected_isochronous_stream(transport, upper_tester, lower_tester, trace, params)
8109    else:
8110        success, initiator, (lower_tester_cis_handle,), (upper_tester_cis_handle,) = \
8111            state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params)
8112
8113    if not initiator:
8114        return success
8115
8116    # Test procedure
8117    # 1. A payload PDU and Ack is sent between the IUT and Lower Tester
8118    success = iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, lower_tester_cis_handle,
8119                                   params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, 0) and success
8120
8121    # 2. If IUT is Peripheral, skip to step 5.
8122    if role == "Central":
8123        # 3. The Upper Tester sends an HCI_LE_Remove_CIG command with the CIG_ID value obtained when the CIG was
8124        #       established.
8125        status, _ = le_remove_cig(transport, upper_tester, 0, 100)  # CIG_ID is hardcoded to 0
8126        # 4. The Upper Tester receives an HCI_Command_Complete event with error code Command Disallowed (0x0C).
8127        success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_COMPLETE, trace) and success
8128        success = status == 0x0C and success
8129
8130    # 5. The Upper Tester sends an HCI_Disconnect to the IUT and receives HCI_Command_status IUT.
8131    reason_code = 0x13
8132    status = disconnect(transport, upper_tester, upper_tester_cis_handle, reason_code, 200)
8133    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and (status == 0) and success
8134
8135    # 6. The Lower Tester receives an LL_CIS_TERMINATE_IND PDU from the IUT and the ErrorCode
8136    #        field in the CtrData field matches the Reason code value the Upper Tester sent in step 45.
8137    def check_ll_cis_terminate_ind():
8138        packet = packets.find('LL_CIS_TERMINATE_IND')
8139        return packet and packet.payload.CtrData.ErrorCode == reason_code
8140    # 7. The Lower Tester sends an Ack to the IUT.
8141
8142    # 8. The Upper Tester receives an HCI_Disconnection_Complete event from the IUT.
8143    s, event = verifyAndFetchEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8144    status, handle, reason = event.decode()
8145    success = s and (status == 0x00) and handle == upper_tester_cis_handle and success
8146
8147    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace) and success
8148
8149    # 9. If IUT is Central, proceed to step 10. If IUT is Peripheral, test is complete.
8150    if role == "Central":
8151        # 10. The Upper Tester sends an HCI_LE_Create_CIS command to the IUT with the CIS Connection_Handle in step 5
8152        #       and receives a successful HCI_Command_Status event from the IUT in response.
8153        success = le_create_cis(transport, upper_tester, 1, [upper_tester_cis_handle], [initiator.handles[0]], 100) == 0
8154        success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8155        # 11. The IUT sends an LL_CIS_REQ PDU to the Lower Tester with all fields set to valid values.
8156        # 12. The Lower Tester sends an LL_CIS_RSP PDU to the IUT.
8157        # 13. The IUT sends an LL_CIS_IND PDU to the Lower Tester.
8158        # 14. The IUT sends a Null ISO Data packet to the Lower Tester.
8159        # 15. The Lower Tester sends an LL ACK to the IUT.
8160        # LT: Wait for HCI_EVT_LE_CIS_REQUEST
8161        s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_REQUEST, trace)
8162        success = s and success
8163        lower_tester_cis_handle = event.decode()[1]
8164
8165        # LT: Accept CIS Request
8166        success = le_accept_cis_request(transport, lower_tester, lower_tester_cis_handle, 100) == 0 and success
8167        success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8168
8169        # 16. The IUT sends an HCI_LE_CIS_Established event to the Upper Tester with the CIS_Connection_Handle set to
8170        #       the value in step 10.
8171        s, event = verifyAndFetchMetaEvent(transport, upper_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace, 2000)
8172        success = s and (event.decode()[0] == 0x00) and (event.decode()[1] == upper_tester_cis_handle) and success
8173
8174        # LT: Wait for HCI_EVT_LE_CIS_ESTABLISHED
8175        s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace)
8176        success = s and (event.decode()[0] == 0x00) and success
8177
8178        # 17. The Upper Tester begins providing data to the IUT to send to the Lower Tester.
8179        # 18. The IUT sends the data to the Lower Tester.
8180        # 19. The Lower Tester sends isochronous data to the IUT.
8181        # 20. The IUT provides the Lower Tester’s isochronous data to the Upper Tester.
8182        success = iso_send_payload_pdu_parallel(transport, upper_tester, lower_tester, trace, upper_tester_cis_handle,
8183                                                lower_tester_cis_handle, params.Max_SDU_C_To_P[0],
8184                                                params.SDU_Interval_C_To_P, 0) and success
8185
8186    ### LL VERIFICATION ###
8187    success = check_ll_cis_terminate_ind() and success
8188
8189    ### TERMINATION ###
8190    success = initiator.disconnect(0x13) and success
8191
8192    return success
8193
8194
8195def ll_cis_per_bv_12_c(transport, upper_tester, lower_tester, trace, packets):
8196    """LL/CIS/PER/BV-12-C [Cis Terminate Procedure, Initiated - Peripheral]"""
8197    return cis_terminate_procedure_initiated(transport, upper_tester, lower_tester, trace, "Peripheral", packets)
8198
8199
8200def cis_terminate_procedure_accepting(transport, upper_tester, lower_tester, trace, role):
8201    assert role == "Peripheral" or role == "Central"
8202    params = SetCIGParameters(
8203        SDU_Interval_C_To_P     = 20000,  # 20 ms
8204        SDU_Interval_P_To_C     = 20000,  # 20 ms
8205        ISO_Interval            = int(20 // 1.25),  # 20 ms
8206        NSE                     = 1,
8207        Max_PDU_C_To_P          = 130,
8208        Max_PDU_P_To_C          = 130,
8209        PHY_C_To_P              = 1,
8210        PHY_P_To_C              = 1,
8211        FT_C_To_P               = 1,
8212        FT_P_To_C               = 1,
8213        BN_C_To_P               = 1,
8214        BN_P_To_C               = 1,
8215    )
8216
8217    if role == "Peripheral":
8218        success, initiator, (upper_tester_cis_handle,), (lower_tester_cis_handle,) = \
8219            state_connected_isochronous_stream(transport, upper_tester, lower_tester, trace, params)
8220    else:
8221        success, initiator, (lower_tester_cis_handle,), (upper_tester_cis_handle,) = \
8222            state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params)
8223
8224    if not initiator:
8225        return success
8226
8227    # Test Procedure
8228    # 1. A payload PDU and Ack is sent between the IUT and Lower Tester.
8229    success = iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, lower_tester_cis_handle,
8230                                   params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, 0) and success
8231
8232    # 2. The Lower Tester sends an LL_CIS_TERMINATE_IND PDU to the IUT and receives an Ack from the IUT.
8233    # LT - Initiate CIS Disconnection and verify command status
8234    status = disconnect(transport, lower_tester, lower_tester_cis_handle, 0x13, 200)
8235    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and (status == 0) \
8236              and success
8237
8238    # LT - Verify HCI Disconnection Complete event parameters
8239    s, event = verifyAndFetchEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8240    status, handle, reason = event.decode()
8241    success = s and (status == 0x00) and handle == lower_tester_cis_handle and success
8242
8243    # 3. The Upper Tester receives an HCI_Disconnection_Complete event from the IUT.
8244    s, event = verifyAndFetchEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8245    status, handle, reason = event.decode()
8246    success = s and (status == 0x00) and handle == upper_tester_cis_handle and success
8247
8248    # Pass verdict:
8249    # - In step 2, the IUT sends an Ack.
8250    # TODO: Verify Ack
8251
8252    # - In step 3, the IUT sends an HCI_Disconnection_Complete event to the Upper Tester.
8253    # PASS
8254
8255    # - The Lower Tester does not receive any payload PDUs from the IUT after step 3.
8256    success = not le_iso_data_ready(transport, lower_tester, 100) and success
8257
8258    ### TERMINATION ###
8259    success = initiator.disconnect(0x13) and success
8260
8261    return success
8262
8263
8264def ll_cis_per_bv_13_c(transport, upper_tester, lower_tester, trace):
8265    """LL/CIS/PER/BV-13-C [CIS Terminate Procedure, Accepting, Peripheral]"""
8266    return cis_terminate_procedure_accepting(transport, upper_tester, lower_tester, trace, "Peripheral")
8267
8268
8269def iso_test_mode_common_procedure(transport, transmitter, receiver, trace, transmitter_cis_handle, receiver_cis_handle,
8270                                   payload_type):
8271    # 1. The Transmitter sends the HCI_LE_ISO_Transmit_Test command with PayloadType as specified in Table and
8272    # receives a successful HCI_Command_Complete event from the IUT in response.
8273    status, conn_handle = hci_le_iso_transmit_test(transport, transmitter, transmitter_cis_handle, payload_type, 100)
8274    success = (conn_handle == transmitter_cis_handle)
8275
8276    success = getCommandCompleteEvent(transport, transmitter, trace) and success and status == 0x00
8277
8278    # 1.X The Receiver sends the HCI_LE_ISO_Receive_Test command to the IUT with Payload_Type as specified in Table
8279    # and receives a successful HCI_Command_Complete event from the IUT in response.
8280    status, conn_handle = hci_le_iso_receive_test(transport, receiver, receiver_cis_handle, payload_type, 100)
8281    success = (conn_handle == receiver_cis_handle) and success
8282
8283    success = getCommandCompleteEvent(transport, receiver, trace) and success and status == 0x00
8284
8285    # 2. The IUT sends isochronous data PDUs with Payload.
8286    # The controller generates and sends test payloads
8287
8288    # 3. Repeat step 2 for a total of 5 rounds of payloads.
8289    received_sdu_count = 0
8290    missed_sdu_count = 0
8291    failed_sdu_count = 0
8292    while ((received_sdu_count + missed_sdu_count + failed_sdu_count) < 5) and success:
8293        # The Receiver sends the HCI_LE_ISO_Read_Test_Counters command to the IUT.
8294        status, connection_handle, received_sdu_count, missed_sdu_count, failed_sdu_count = \
8295            hci_le_iso_read_test_counters_test(transport, receiver, receiver_cis_handle, 100)
8296        success = getCommandCompleteEvent(transport, receiver, trace) and success and status == 0x00
8297
8298        # Core Version Sydney r11 | | Vol 6, Part B
8299        # Because the transmitter and receiver do not enter test mode simultaneously, it is not possible to
8300        # determine whether the first test SDU received was the first one sent. As a consequence, at the moment the
8301        # first valid test SDU is received (indicated by either Received_SDU_Count or Failed_SDU_Count being
8302        # incremented), the value of Missed_SDU_Count is unpredictable. Once a valid test SDU has been received,
8303        # any further changes in Missed_SDU_Count will be correct.
8304        if received_sdu_count == 0 and failed_sdu_count == 0:
8305            missed_sdu_count = 0
8306
8307    success = received_sdu_count >= 5 and missed_sdu_count == 0 and failed_sdu_count == 0 and success
8308
8309    # 4. The Receiver sends the HCI_LE_ISO_Test_End command to the IUT and receives an HCI_Command_Status event
8310    # from the IUT with the Status field set to Success.
8311    status, connection_handle, _, _, _ = hci_le_iso_test_end(transport, receiver, receiver_cis_handle, 100)
8312    success = getCommandCompleteEvent(transport, receiver, trace) and success and status == 0x00
8313
8314    # 4.X The Transmitter sends the HCI_LE_ISO_Test_End command to the IUT and receives an HCI_Command_Status event
8315    # from the IUT with the Status field set to Success.
8316    status, connection_handle, _, _, _ = hci_le_iso_test_end(transport, transmitter, transmitter_cis_handle, 100)
8317    success = getCommandCompleteEvent(transport, transmitter, trace) and success and status == 0x00
8318
8319    return success, received_sdu_count, missed_sdu_count, failed_sdu_count
8320
8321
8322def iso_transmit_test_mode_cis(transport, upper_tester, lower_tester, trace, is_upper_tester_central):
8323    params = SetCIGParameters()
8324
8325    if is_upper_tester_central:
8326        success, initiator, (lower_tester_cis_handle,), (upper_tester_cis_handle,) = \
8327            state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params,
8328                                               setup_iso_data_path=False)
8329    else:
8330        success, initiator, (upper_tester_cis_handle,), (lower_tester_cis_handle,) = \
8331            state_connected_isochronous_stream(transport, upper_tester, lower_tester, trace, params,
8332                                               setup_iso_data_path=False)
8333    if not initiator:
8334        return success
8335
8336    testData = namedtuple('testData', 'Name, Payload_Type')
8337    rounds = [
8338        testData("Zero length payload", 0x00),
8339        testData("Variable length payload", 0x01),
8340        testData("Maximum length payload", 0x02),
8341    ]
8342    for name, payload_type in rounds:
8343        success, received_sdu_count, missed_sdu_count, failed_sdu_count = \
8344            iso_test_mode_common_procedure(transport, upper_tester, lower_tester, trace, upper_tester_cis_handle,
8345                                           lower_tester_cis_handle, payload_type)
8346
8347        trace.trace(5, "%s done, received_sdu_count=%d missed_sdu_count=%d failed_sdu_count=%d" %
8348                    (name, received_sdu_count, missed_sdu_count, failed_sdu_count))
8349
8350    ### TERMINATION ###
8351    success = initiator.disconnect(0x13) and success
8352
8353    return success
8354
8355
8356def ll_ist_per_bv_01_c(transport, upper_tester, lower_tester, trace):
8357    """LL/IST/PER/BV-01-C [ISO Transmit Test Mode, CIS]"""
8358    return iso_transmit_test_mode_cis(transport, upper_tester, lower_tester, trace, False)
8359
8360
8361def iso_receive_test_mode_cis(transport, upper_tester, lower_tester, trace, is_upper_tester_central):
8362    def establish_acl_and_cis(framing):
8363        params = SetCIGParameters(
8364            Framing                 = framing,
8365            SDU_Interval_C_To_P     = 400000,  # 400 ms
8366            SDU_Interval_P_To_C     = 400000,  # 400 ms
8367            ISO_Interval            = int(400 // 1.25),  # 400 ms
8368        )
8369
8370        if is_upper_tester_central:
8371            success, initiator, (lower_tester_cis_handle,), (upper_tester_cis_handle,) = \
8372                state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params,
8373                                                   setup_iso_data_path=False)
8374        else:
8375            success, initiator, (upper_tester_cis_handle,), (lower_tester_cis_handle,) = \
8376                state_connected_isochronous_stream(transport, upper_tester, lower_tester, trace, params,
8377                                                   setup_iso_data_path=False)
8378
8379        return success and initiator, initiator, upper_tester_cis_handle, lower_tester_cis_handle
8380
8381    testData = namedtuple('testData', 'Name, Framing, Payload_Type')
8382    rounds = [
8383        testData("Zero length payload unframed", 0, 0x00),
8384        testData("Variable length payload unframed", 0, 0x01),
8385        testData("Maximum length payload unframed", 0, 0x02),
8386        testData("Maximum length payload framed", 1, 0x02),
8387        testData("Variable length payload framed", 1, 0x01),
8388    ]
8389    previous = rounds[0]
8390    success, initiator, upper_tester_cis_handle, lower_tester_cis_handle = establish_acl_and_cis(previous.Framing)
8391    for current in rounds:
8392        # When Framing is changing between rounds, Isochronous link needs to be terminated and re-established with
8393        # correct Framing, as framing cannot be changed after creation.
8394        if current.Framing != previous.Framing:
8395            success = initiator.disconnect(0x13) and success
8396
8397            if is_upper_tester_central:
8398                status, _ = le_remove_cig(transport, upper_tester, 0, 100)
8399                success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x00 and success
8400            else:
8401                status, _ = le_remove_cig(transport, lower_tester, 0, 100)
8402                success = getCommandCompleteEvent(transport, lower_tester, trace) and status == 0x00 and success
8403
8404            s, initiator, upper_tester_cis_handle, lower_tester_cis_handle = establish_acl_and_cis(current.Framing)
8405            success = s and success
8406
8407        s, received_sdu_count, missed_sdu_count, failed_sdu_count = \
8408            iso_test_mode_common_procedure(transport, lower_tester, upper_tester, trace, lower_tester_cis_handle,
8409                                           upper_tester_cis_handle, current.Payload_Type)
8410        success = s and success
8411
8412        previous = current
8413
8414        trace.trace(5, "%s done, received_sdu_count=%d missed_sdu_count=%d failed_sdu_count=%d" %
8415                    (current.Name, received_sdu_count, missed_sdu_count, failed_sdu_count))
8416
8417    ### TERMINATION ###
8418    success = initiator.disconnect(0x13) and success
8419
8420    return success
8421
8422
8423def ll_ist_per_bv_03_c(transport, upper_tester, lower_tester, trace):
8424    """LL/IST/PER/BV-03-C [ISO Receive Test Mode, CIS]"""
8425    return iso_receive_test_mode_cis(transport, upper_tester, lower_tester, trace, False)
8426
8427
8428def cis_setup_procedure_central_initiated(transport, upper_tester, lower_tester, trace, params):
8429    success, initiator, (cis_handle,), _ = \
8430        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params)
8431
8432    def lt_send_data_packet(pkt_seq_num):
8433        return iso_send_payload_pdu(transport, upper_tester, lower_tester, trace, cis_handle,
8434                                    params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, pkt_seq_num)
8435
8436    for j in range(50 // params.BN_C_To_P[0]):
8437        success = lt_send_data_packet(j) and success
8438
8439    ### TERMINATION ###
8440    success = initiator.disconnect(0x13) and success
8441
8442    return success
8443
8444
8445def ll_cis_cen_bv_01_c(transport, upper_tester, lower_tester, trace):
8446    """LL/CIS/CEN/BV-01-C [CIS Setup Procedure, Central Initiated]"""
8447    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
8448    params = SetCIGParameters(
8449        PHY_C_To_P              = 1,
8450        BN_C_To_P               = 2,
8451        FT_C_To_P               = 1,
8452        Max_PDU_C_To_P          = 130,
8453        PHY_P_To_C              = 1,
8454        BN_P_To_C               = 2,
8455        FT_P_To_C               = 1,
8456        Max_PDU_P_To_C          = 130,
8457        NSE                     = min(4, max_cis_nse),
8458        SDU_Interval_C_To_P     = 0x2710,  # 10 ms
8459        SDU_Interval_P_To_C     = 0x2710,  # 10 ms
8460        ISO_Interval            = 0x10,  # 20 ms
8461    )
8462
8463    return cis_setup_procedure_central_initiated(transport, upper_tester, lower_tester, trace, params)
8464
8465
8466def ll_cis_cen_bv_02_c(transport, upper_tester, lower_tester, trace):
8467    """LL/CIS/CEN/BV-02-C [CIS Setup Procedure, Central Initiated]"""
8468    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
8469    params = SetCIGParameters(
8470        PHY_C_To_P              = 2,
8471        BN_C_To_P               = 2,
8472        FT_C_To_P               = 2,
8473        Max_PDU_C_To_P          = 251,
8474        PHY_P_To_C              = 2,
8475        BN_P_To_C               = 2,
8476        FT_P_To_C               = 1,
8477        Max_PDU_P_To_C          = 251,
8478        NSE                     = min(4, max_cis_nse),
8479        SDU_Interval_C_To_P     = 0x4E20,  # 20 ms
8480        SDU_Interval_P_To_C     = 0x2710,  # 10 ms
8481        ISO_Interval            = 0x10,  # 20 ms
8482    )
8483
8484    return cis_setup_procedure_central_initiated(transport, upper_tester, lower_tester, trace, params)
8485
8486
8487def ll_cis_cen_bv_31_c(transport, upper_tester, lower_tester, trace):
8488    """LL/CIS/CEN/BV-31-C [CIS Setup Procedure, Central Initiated]"""
8489    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
8490    params = SetCIGParameters(
8491        PHY_C_To_P              = 2,
8492        BN_C_To_P               = 2,
8493        FT_C_To_P               = 1,
8494        Max_PDU_C_To_P          = 130,
8495        PHY_P_To_C              = 1,
8496        BN_P_To_C               = 2,
8497        FT_P_To_C               = 1,
8498        Max_PDU_P_To_C          = 130,
8499        NSE                     = min(4, max_cis_nse),
8500        SDU_Interval_C_To_P     = 0x2710,  # 10 ms
8501        SDU_Interval_P_To_C     = 0x2710,  # 10 ms
8502        ISO_Interval            = 0x10,  # 20 ms
8503    )
8504
8505    return cis_setup_procedure_central_initiated(transport, upper_tester, lower_tester, trace, params)
8506
8507
8508def ll_cis_cen_bv_39_c(transport, upper_tester, lower_tester, trace):
8509    """LL/CIS/CEN/BV-39-C [CIS Setup Procedure, Central Initiated]"""
8510    params = SetCIGParameters(
8511        PHY_C_To_P              = 2,
8512        BN_C_To_P               = 1,
8513        FT_C_To_P               = 1,
8514        Max_PDU_C_To_P          = 130,
8515        PHY_P_To_C              = 2,
8516        BN_P_To_C               = 1,
8517        FT_P_To_C               = 1,
8518        Max_PDU_P_To_C          = 50,
8519        NSE                     = 1,
8520        SDU_Interval_C_To_P     = 0x4E20,  # 20 ms
8521        SDU_Interval_P_To_C     = 0x4E20,  # 20 ms
8522        ISO_Interval            = 0x10,  # 20 ms
8523    )
8524
8525    return cis_setup_procedure_central_initiated(transport, upper_tester, lower_tester, trace, params)
8526
8527
8528def ll_cis_cen_bv_03_c(transport, upper_tester, lower_tester, trace):
8529    """LL/CIS/CEN/BV-03-C [CIS Setup Procedure, Central Initiated, Rejected]"""
8530    return cis_setup_peripheral_rejected(transport, lower_tester, upper_tester, trace)
8531
8532
8533def ll_cis_cen_bv_04_c(transport, upper_tester, lower_tester, trace):
8534    """LL/CIS/CEN/BV-04-C [New Channel Map]"""
8535    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
8536    return test_cis_map_update(transport, lower_tester, upper_tester, trace, 2, min(3, max_cis_nse), 100000)
8537
8538
8539def ll_cis_cen_bv_40_c(transport, upper_tester, lower_tester, trace):
8540    """LL/CIS/CEN/BV-40-C [New Channel Map]"""
8541    return test_cis_map_update(transport, lower_tester, upper_tester, trace, 1, 1, 200000)
8542
8543
8544def ll_cis_cen_bv_07_c(transport, upper_tester, lower_tester, trace):
8545    """LL/CIS/CEN/BV-07-C [Sending and Receiving Data in Bidirectional CIS]"""
8546    return test_sending_and_receiving_data_in_bidirectional_cis(transport, upper_tester, lower_tester, trace)
8547
8548
8549def ll_cis_cen_bv_35_c(transport, upper_tester, lower_tester, trace):
8550    """LL/CIS/CEN/BV-35-C [Sending and Receiving Data in Bidirectional CIS, Encryption]"""
8551    return test_sending_and_receiving_data_in_bidirectional_cis(transport, upper_tester, lower_tester, trace, ENC_KEYS)
8552
8553
8554def ll_cis_cen_bv_47_c(transport, upper_tester, lower_tester, trace):
8555    """LL/CIS/CEN/BV-47-C [Sending and Receiving Data in Bidirectional CIS, BN = 1]"""
8556    return test_sending_and_receiving_data_in_bidirectional_cis_bn_1(transport, upper_tester, lower_tester, trace)
8557
8558
8559def ll_cis_cen_bv_48_c(transport, upper_tester, lower_tester, trace):
8560    """LL/CIS/CEN/BV-48-C [Sending and Receiving Data in Bidirectional CIS, BN = 1, Encryption]"""
8561    return test_sending_and_receiving_data_in_bidirectional_cis_bn_1(transport, upper_tester, lower_tester, trace,
8562                                                                     ENC_KEYS)
8563
8564
8565def ll_cis_cen_bv_45_c(transport, upper_tester, lower_tester, trace):
8566    """LL/CIS/CEN/BV-45-C [Sending Data in Unidirectional CIS, BN = 1]"""
8567    params = SetCIGParameters(
8568        SDU_Interval_C_To_P     = 0x186A0,  # 100 ms
8569        SDU_Interval_P_To_C     = 0x186A0,  # 100 ms
8570        FT_C_To_P               = 1,
8571        FT_P_To_C               = 1,
8572        ISO_Interval            = 0x50,  # 100 ms
8573        CIS_Count               = 1,
8574        NSE                     = 1,
8575        Max_PDU_C_To_P          = 251,
8576        Max_PDU_P_To_C          = 0,
8577        PHY_C_To_P              = 1,
8578        PHY_P_To_C              = 1,
8579        BN_C_To_P               = 1,
8580        BN_P_To_C               = 0,
8581    )
8582
8583    success, initiator, _, (cis_conn_handle,) = \
8584        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params)
8585    if not initiator:
8586        return success
8587
8588    success = iso_send_payload_pdu(transport, upper_tester, lower_tester, trace, cis_conn_handle,
8589                                   params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, 0) and success
8590
8591    ### TERMINATION ###
8592    success = initiator.disconnect(0x13) and success
8593
8594    return success
8595
8596
8597def ll_cis_cen_bv_06_c(transport, upper_tester, lower_tester, trace):
8598    """LL/CIS/CEN/BV-06-C [Receiving Data in Unidirectional CIS]"""
8599    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
8600    params = SetCIGParameters(
8601        SDU_Interval_C_To_P     = 0xC350,  # 50 ms
8602        SDU_Interval_P_To_C     = 0xC350,  # 50 ms
8603        FT_C_To_P               = 1,
8604        FT_P_To_C               = 1,
8605        ISO_Interval            = 0x50,  # 100 ms
8606        CIS_Count               = 1,
8607        NSE                     = min(4, max_cis_nse),
8608        Max_PDU_C_To_P          = 0,
8609        # Max_PDU_P_To_C          = default,
8610        PHY_C_To_P              = 1,
8611        PHY_P_To_C              = 1,
8612        BN_C_To_P               = 0,
8613        BN_P_To_C               = 2,
8614    )
8615
8616    success, initiator, (cis_conn_handle,), _ = \
8617        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params)
8618    if not initiator:
8619        return success
8620
8621    for seq_num in range(2):
8622        success = iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, cis_conn_handle,
8623                                       params.Max_SDU_P_To_C[0], params.SDU_Interval_P_To_C, seq_num) and success
8624
8625    ### TERMINATION ###
8626    success = initiator.disconnect(0x13) and success
8627
8628    return success
8629
8630
8631def ll_cis_cen_bv_46_c(transport, upper_tester, lower_tester, trace):
8632    """LL/CIS/CEN/BV-46-C [Receiving Data in Unidirectional CIS, BN = 1]"""
8633    params = SetCIGParameters(
8634        SDU_Interval_C_To_P     = 0x186A0,  # 100 ms
8635        SDU_Interval_P_To_C     = 0x186A0,  # 100 ms
8636        FT_C_To_P               = 1,
8637        FT_P_To_C               = 1,
8638        ISO_Interval            = 0x50,  # 100 ms
8639        CIS_Count               = 1,
8640        NSE                     = 1,
8641        Max_PDU_C_To_P          = 0,
8642        Max_PDU_P_To_C          = 251,
8643        PHY_C_To_P              = 1,
8644        PHY_P_To_C              = 1,
8645        BN_C_To_P               = 0,
8646        BN_P_To_C               = 1,
8647    )
8648
8649    success, initiator, (cis_conn_handle,), _ = \
8650        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params)
8651    if not initiator:
8652        return success
8653
8654    success = iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, cis_conn_handle,
8655                                   params.Max_SDU_P_To_C[0], params.SDU_Interval_P_To_C, 0) and success
8656
8657    ### TERMINATION ###
8658    success = initiator.disconnect(0x13) and success
8659
8660    return success
8661
8662
8663def central_send_and_receive_data_in_multi_cises_single_cig_single_conn_interleaved(transport, central, peripheral,
8664                                                                                    trace, bn, sdu_interval, nse,
8665                                                                                    adjust_conn_interval=False):
8666    params = SetCIGParameters(
8667        SDU_Interval_C_To_P     = sdu_interval,
8668        SDU_Interval_P_To_C     = sdu_interval,
8669        FT_C_To_P               = 1,
8670        FT_P_To_C               = 1,
8671        ISO_Interval            = 0x50,  # 100 ms
8672        Packing                 = 1,  # Interleaved
8673        CIS_Count               = 2,
8674        NSE                     = nse,
8675        PHY_C_To_P              = 1,
8676        PHY_P_To_C              = 1,
8677        BN_C_To_P               = bn,
8678        BN_P_To_C               = bn,
8679    )
8680
8681    return test_sending_and_receiving_data_in_multiple_cises(transport, central, peripheral, trace, params, 1,
8682                                                             adjust_conn_interval=adjust_conn_interval)
8683
8684
8685def ll_cis_cen_bv_08_c(transport, upper_tester, lower_tester, trace):
8686    """LL/CIS/CEN/BV-08-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG,
8687     Central]"""
8688    return central_send_and_receive_data_in_multi_cises_single_cig_single_conn_interleaved(
8689        transport, upper_tester, lower_tester, trace, 2, 0xC350, 4, adjust_conn_interval=True)
8690
8691
8692def ll_cis_cen_bv_43_c(transport, upper_tester, lower_tester, trace):
8693    """LL/CIS/CEN/BV-43-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG,
8694     Central]"""
8695    return central_send_and_receive_data_in_multi_cises_single_cig_single_conn_interleaved(
8696        transport, upper_tester, lower_tester, trace, 1, 0x186A0, 1)
8697
8698
8699def ll_cis_cen_bv_44_c(transport, upper_tester, lower_tester, trace):
8700    """LL/CIS/CEN/BV-44-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG,
8701     Central, BN > 1, NSE = 2]"""
8702    return central_send_and_receive_data_in_multi_cises_single_cig_single_conn_interleaved(
8703        transport, upper_tester, lower_tester, trace, 2, 0x0C350, 2)
8704
8705
8706def ll_cis_cen_bv_09_c(transport, upper_tester, lower_tester, trace):
8707    """LL/CIS/CEN/BV-09-C [Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Sequential,
8708     Central]"""
8709    max_cis_nse = get_ixit_value(transport, upper_tester, IXITS["TSPX_max_cis_nse"], 100)
8710    params = SetCIGParameters(
8711        SDU_Interval_C_To_P     = 0x0C350,  # 50 ms
8712        SDU_Interval_P_To_C     = 0x186A0,  # 100 ms
8713        FT_C_To_P               = 1,
8714        FT_P_To_C               = 1,
8715        ISO_Interval            = 0x50,  # 100 ms
8716        Packing                 = 0,  # Sequential
8717        CIS_Count               = 2,
8718        NSE                     = min(max_cis_nse, 4),
8719        PHY_C_To_P              = 1,
8720        PHY_P_To_C              = 1,
8721        BN_C_To_P               = 2,
8722        BN_P_To_C               = 1,
8723    )
8724
8725    return test_sending_and_receiving_data_in_multiple_cises(transport, upper_tester, lower_tester, trace, params, 2,
8726                                                             adjust_conn_interval=True)
8727
8728
8729def ll_cis_cen_bv_24_c(transport, upper_tester, lower_tester, trace):
8730    """LL/CIS/CEN/BV-24-C [CIS Updating Peer Clock Accuracy]"""
8731    return cis_updating_peer_clock_accuracy(transport, upper_tester, lower_tester, trace, "Central")
8732
8733
8734def ll_cis_cen_bv_15_c(transport, upper_tester, lower_tester, trace, packets):
8735    """LL/CIS/CEN/BV-15-C [CIS Terminate Procedure, Initiated]"""
8736    return cis_terminate_procedure_initiated(transport, upper_tester, lower_tester, trace, "Central", packets)
8737
8738
8739def ll_cis_cen_bv_16_c(transport, upper_tester, lower_tester, trace):
8740    """LL/CIS/CEN/BV-16-C [CIS Terminate Procedure, Accepting]"""
8741    return cis_terminate_procedure_accepting(transport, upper_tester, lower_tester, trace, "Central")
8742
8743
8744def ll_cis_cen_bv_30_c(transport, upper_tester, lower_tester, trace):
8745    """LL/CIS/CEN/BV-30-C [Isochronous Channels Host Support Feature Bit]"""
8746    params = SetCIGParameters()
8747    success = set_isochronous_channels_host_support(transport, lower_tester, trace, 0b1)
8748
8749    # 1. The Upper Tester sends an HCI_LE_Set_Host_Feature with Bit_Number set to 30 (not a host controlled feature bit)
8750    #       and Bit_Value set to 0b1. The Upper Tester receives an HCI_Command_Complete response with an error code
8751    #       Unsupported Feature or Parameter Value (0x11).
8752    status = le_set_host_feature(transport, upper_tester, FeatureSupport.ISOCHRONOUS_BROADCASTER, 0b1, 100)
8753    success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x11 and success
8754
8755    # 2. The IUT establishes an ACL connection with the Lower Tester as Peripheral.
8756    s, _, initiator = establish_acl_connection(transport, upper_tester, lower_tester, trace)
8757    success = s and success
8758    if not initiator:
8759        return False
8760
8761    # 3. The Upper Tester sends an HCI_LE_Set_Host_Feature with Bit_Number set to 32 (Isochronous Channels feature bit)
8762    #       and Bit_Value set to 0b1. The Upper Tester receives an HCI_Command_Complete response with an error code
8763    #       Command Disallowed (0x0C).
8764    status = le_set_host_feature(transport, upper_tester, FeatureSupport.ISOCHRONOUS_CHANNELS, 0b1, 100)
8765    success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x0C and success
8766
8767    # 4. The IUT disconnects the ACL connection from the Lower Tester.
8768    success = initiator.disconnect(0x13) and success
8769
8770    testData = namedtuple('testData', 'Set_Feature_Enable, Bit_Value, CIS_Created')
8771    table = [
8772        testData(False, None, False),
8773        testData(True, 0b1, True),
8774        testData(True, 0b0, False),
8775    ]
8776
8777    # 5. Repeat steps 6–13 for each round specified in Table
8778    for set_feature_enable, bit_value, cis_created in table:
8779        # 6. If the table indicates “Set Feature Enable” is true for this round, then the Upper Tester sends an
8780        #       HCI_LE_Set_Host_Feature command to the IUT with the Bit_Number set to 32 (Isochronous Channels) and the
8781        #       Bit_Value set to the value specified in the table. The Upper Tester receives an HCI_Command_Complete
8782        #       event from the IUT.
8783        if set_feature_enable:
8784            status = le_set_host_feature(transport, upper_tester, FeatureSupport.ISOCHRONOUS_CHANNELS, bit_value, 100)
8785            success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x00 and success
8786
8787        # 7. The IUT establishes an ACL connection with the Lower Tester as Peripheral.
8788        s, _, initiator = establish_acl_connection(transport, upper_tester, lower_tester, trace)
8789        success = s and success
8790        if not initiator:
8791            return False
8792
8793        # 8. The Upper Tester sends an HCI_LE_Set_CIG_Parameters command to the IUT using the default parameters
8794        #       specified in Section 4.10.1.3 Default Values for Set CIG Parameters Commands and receives a successful
8795        #       HCI_Command_Complete event.
8796        status, cig_id, cis_count, cis_handles = le_set_cig_parameters_test(transport, upper_tester, 0,
8797                                                                            *params.get_cig_parameters_test(), 100)
8798        success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x00 and success
8799
8800        # 9. The Upper Tester sends an HCI_LE_Create_CIS command with the ACL_Connection_Handle of the established ACL
8801        #       and valid Connection_Handle
8802        status = le_create_cis(transport, upper_tester, cis_count, cis_handles, cis_count * [initiator.handles[0]], 100)
8803        success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8804
8805        if cis_created:
8806           # 10. The Upper Tester receives a successful HCI_Command_Status event.
8807           success = status == 0x00 and success
8808
8809           # 11. The IUT establishes a CIS with the Lower Tester.
8810           s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_REQUEST, trace)
8811           success = s and success
8812
8813           status = le_accept_cis_request(transport, lower_tester, event.decode()[1], 100)
8814           s = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace)
8815           success = status == 0 and s and success
8816
8817           s, event = verifyAndFetchMetaEvent(transport, upper_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace,
8818                                              2000)
8819           success = s and (event.decode()[0] == 0x00) and success
8820
8821           s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace)
8822           success = s and (event.decode()[0] == 0x00) and success
8823        else:
8824            # 10. The Upper Tester receives an HCI_Command_Status event with the status set to error code Command
8825            #       Disallowed (0x0C).
8826            success = status == 0x0C and success
8827
8828        # 12. The IUT disconnects the ACL connection from the Lower Tester.
8829        success = initiator.disconnect(0x13) and success
8830
8831        # 13. If the table indicates that a CIS is not created this round, then the Upper Tester sends an
8832        #       HCI_LE_Remove_CIG command to the IUT with the CIG_ID set to the CIG_ID in step 8 and receives
8833        #       a successful HCI_Command_Complete event.
8834        if not cis_created:
8835            status, _ = le_remove_cig(transport, upper_tester, 0, 100)
8836            success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x00 and success
8837
8838    return success
8839
8840
8841def ll_cis_cen_bv_20_c(transport, upper_tester, lower_tester, trace):
8842    """LL/CIS/CEN/BV-20-C [Set Encryption After CIS Established]"""
8843    params = SetCIGParameters(
8844        SDU_Interval_C_To_P     = 0x4E20,  # 20 ms
8845        SDU_Interval_P_To_C     = 0x4E20,  # 20 ms
8846        FT_C_To_P               = 1,
8847        FT_P_To_C               = 1,
8848        ISO_Interval            = 0x10,  # 20 ms
8849        CIS_Count               = 1,
8850        NSE                     = 1,
8851        Max_PDU_C_To_P          = 130,
8852        Max_PDU_P_To_C          = 130,
8853        PHY_C_To_P              = 1,
8854        PHY_P_To_C              = 1,
8855        BN_C_To_P               = 1,
8856        BN_P_To_C               = 1,
8857    )
8858
8859    success, initiator, _, _ = \
8860        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params,
8861                                           setup_iso_data_path=False, enc_keys=None)
8862    if not initiator:
8863        return False
8864
8865    rand, ediv, ltk = ENC_KEYS
8866    status = le_start_encryption(transport, upper_tester, initiator.handles[0], rand, ediv, ltk, 100)
8867    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace, 1000) and status == 0x0C
8868
8869    ### TERMINATION ###
8870    success = initiator.disconnect(0x13) and success
8871
8872    return success
8873
8874
8875def ll_cis_cen_bv_51_c(transport, upper_tester, lower_tester, trace):
8876    """LL/CIS/CEN/BV-51-C [CIS Setup Procedure, Central Initiated, CIG ID Reuse]"""
8877    params = SetCIGParameters(
8878        CIS_Count               = 2,
8879    )
8880
8881    success, initiator, _, (connection_handle_1, connection_handle_2) = \
8882        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params)
8883
8884    if not initiator:
8885        return False
8886
8887    # 2. The Upper Tester sends an HCI_Disconnect command to the IUT with Connection_Handle_1 and Reason Code set to
8888    #       any valid value.
8889    # 3. The IUT sends a successful HCI_Command_Status event to the Upper Tester.
8890    # 4. The IUT sends an LL_CIS_TERMINATE_IND PDU to the Lower Tester with the ErrorCode field in the CtrData field
8891    #       set to match the Reason Code value in step 2.
8892    # 5. The Lower Tester sends an Ack to the IUT.
8893    success = disconnect(transport, upper_tester, connection_handle_1, 0x13, 200) == 0 and success
8894    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8895
8896    # 6. The IUT sends a successful HCI_Disconnection_Complete event to the Upper Tester with Connection_Handle_1
8897    #       and Reason Code set to Connection Terminated by Local Host (0x16).
8898    s, event = verifyAndFetchEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8899    status, handle, reason = event.decode()
8900    success = s and status == 0x00 and handle == connection_handle_1 and success and reason == 0x16
8901
8902    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace) and success
8903
8904    # 8. The IUT sends an LL_CIS_REQ PDU to the Lower Tester with CIG_ID set to CIG_ID_1 and CIS_ID set to CIS_ID_1.
8905    #       The re-created CIS may be different from the CIS disconnected previously using Connection_Handle_1,
8906    #       but it still complies with the Default Values for Set CIG Parameters Commands.
8907    status = le_create_cis(transport, lower_tester, 1, [connection_handle_1], [initiator.handles[0]], 100)
8908    success = status == 0 and success
8909    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8910
8911    # 9. The Lower Tester sends an LL_CIS_RSP PDU to the IUT.
8912    # 10. The IUT sends an LL_CIS_IND PDU to the Lower Tester. The Access Address provided in CtrData is different from
8913    #       AA_1. The new Access Address is identified as AA_1new.
8914    # 11. The IUT sends an ISO Data Packet to the Lower Tester.
8915    # 12. The Lower Tester sends an LL Ack to the IUT.
8916    # 13. The IUT sends an HCI_LE_CIS_Established event to the Upper Tester with Status set to 0x00 and
8917    #       Connection_Handle set to Connection_Handle_1.
8918    s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_REQUEST, trace)
8919    success = s and success
8920
8921    status = le_accept_cis_request(transport, lower_tester, event.decode()[1], 100)
8922    s = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace)
8923    success = status == 0 and s and success
8924
8925    s, event = verifyAndFetchMetaEvent(transport, upper_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace,
8926                                       2000)
8927    success = s and (event.decode()[0] == 0x00) and success
8928
8929    s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace)
8930    success = s and (event.decode()[0] == 0x00) and success
8931
8932    # 14. The Upper Tester sends an HCI_Disconnect command to the IUT with Connection_Handle_1 and Reason Code set to
8933    #       any valid value.
8934    # 15. The IUT sends a successful HCI_Command_Status event to the Upper Tester.
8935    success = disconnect(transport, upper_tester, connection_handle_1, 0x13, 200) == 0 and success
8936    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8937
8938    # 16. The IUT sends an LL_CIS_TERMINATE_IND PDU to the Lower Tester with the ErrorCode field in the CtrData field
8939    #       set to match the Reason Code value in step 14.
8940    # 17. The Lower Tester sends an Ack to the IUT.
8941    # 18. The IUT sends a successful HCI_Disconnection_Complete event to the Upper Tester with Connection_Handle_1 and
8942    #       Reason Code set to Connection Terminated by Local Host (0x16).
8943    s, event = verifyAndFetchEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8944    status, handle, reason = event.decode()
8945    success = s and status == 0x00 and handle == connection_handle_1 and reason == 0x16 and success
8946
8947    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace) and success
8948
8949    # 19. The Upper Tester sends an HCI_Disconnect command to the IUT with Connection_Handle_2 and Reason Code set to
8950    #       any valid value.
8951    # 20. The IUT sends a successful HCI_Command_Status event to the Upper Tester.
8952    success = disconnect(transport, upper_tester, connection_handle_2, 0x13, 200) == 0 and success
8953    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8954
8955    # 21. The IUT sends an LL_CIS_TERMINATE_IND PDU to the Lower Tester with the ErrorCode field in the CtrData field
8956    #       set to match the Reason code value the Upper Tester sent in step 19.
8957    # 22. The Lower Tester sends an Ack to the IUT.
8958    # 23. The IUT sends a successful HCI_Disconnection_Complete event to the Upper Tester with Connection_Handle_2 and
8959    #       Reason Code set to Connection Terminated by Local Host (0x16).
8960    s, event = verifyAndFetchEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace)
8961    status, handle, reason = event.decode()
8962    success = s and status == 0x00 and handle == connection_handle_2 and success and reason == 0x16
8963
8964    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace) and success
8965
8966    # 24. The Upper Tester sends an HCI_LE_Remove_CIG command to the IUT with CIG_ID set to the value of CIG_ID_1
8967    #       and receives a successful HCI_Command_Complete event from the IUT in response.
8968    status, _ = le_remove_cig(transport, upper_tester, 0, 100)
8969    success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x00 and success
8970
8971    # 25. The Upper Tester sends an HCI_LE_Set_CIG_Parameters command to the IUT with values as specified in Section 4.10.1.3, Default Values for Set CIG Parameters Commands. The CIG_ID is
8972    # to be set to CIG_ID_1 in step 1, CIS_ID is set to CIS_ID_1.
8973    params = SetCIGParameters()
8974    status, cig_id, cis_count, (connection_handle_3,) = \
8975        le_set_cig_parameters_test(transport, lower_tester, 0, *params.get_cig_parameters_test(), 100)
8976
8977    # 26. The IUT sends a successful HCI_Command_Complete event to the Upper Tester with CIG_ID set to CIG_ID_1,
8978    #       CIS_Count set to 1, and the connection handle for CIS_ID_1, which is saved and referenced as
8979    #       Connection_Handle_3 in the following steps.
8980    success = cig_id == 0 and cis_count == 1 and success
8981    success = getCommandCompleteEvent(transport, lower_tester, trace) and status == 0x00 and success
8982
8983    # 27. The Upper Tester sends an HCI_LE_Create_CIS command to the IUT with CIS_Count set to 1 and Connection_Handle
8984    #       set to Connection_Handle_3 from step 26, and it receives a successful HCI_Command_Status in response.
8985    status = le_create_cis(transport, lower_tester, 1, [connection_handle_3], [initiator.handles[0]], 100)
8986    success = status == 0 and success
8987    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
8988
8989    # 28. The IUT sends an LL_CIS_REQ PDU to the Lower Tester with CIG_ID set to CIG_ID_1 and CIS_ID set to CIS_ID_3.
8990    # 29. The Lower Tester sends an LL_CIS_RSP PDU to the IUT.
8991    # 30. The IUT sends an LL_CIS_IND PDU to the Lower Tester. The Access Address provided in CtrData is different from
8992    #       AA_1, AA_1new, and AA_2.
8993    # 31. The IUT sends an ISO Data Packet to the Lower Tester.
8994    # 32. The Lower Tester sends an LL Ack to the IUT.
8995    # 33. The IUT sends an HCI_LE_CIS_Established event to the Upper Tester with Status set to 0x00 and
8996    #       Connection_Handle set to Connection_Handle_3.
8997    s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_REQUEST, trace)
8998    success = s and success
8999
9000    status = le_accept_cis_request(transport, lower_tester, event.decode()[1], 100)
9001    s = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace)
9002    success = status == 0 and s and success
9003
9004    s, event = verifyAndFetchMetaEvent(transport, upper_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace,
9005                                       2000)
9006    success = s and (event.decode()[0] == 0x00) and success
9007
9008    s, event = verifyAndFetchMetaEvent(transport, lower_tester, MetaEvents.BT_HCI_EVT_LE_CIS_ESTABLISHED, trace)
9009    success = s and (event.decode()[0] == 0x00) and success
9010
9011    if connection_handle_3 == connection_handle_1:
9012        # Alternative 34A (The value of Connection_Handle_3 equals the value of Connection_Handle_1):
9013        # 34A.1. The Upper Tester sends an HCI_LE_Create_CIS command to the IUT with CIS_Count set to 1,
9014        #       ACL_Connection_Handle set to the current ACL Connection Handle value, and CIS_Connection_Handle set to
9015        #       Connection_Handle_2.
9016        status = le_create_cis(transport, lower_tester, 1, [connection_handle_2], [initiator.handles[0]], 100)
9017        success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
9018
9019        # 34A.2. The IUT sends an HCI_Command_Status event to the Upper Tester with Status set to Unknown Connection
9020        #       Identifier (0x02).
9021        success = status == 0x02 and success
9022    elif connection_handle_3 == connection_handle_2:
9023        # Alternative 34B (The value of Connection_Handle_3 equals the value of Connection_Handle_2):
9024        # 34B.1. The Upper Tester sends an HCI_LE_Create_CIS command to the IUT with CIS_Count set to 1,
9025        #       ACL_Connection_Handle set to the current ACL Connection Handle value, and CIS_Connection_Handle set to
9026        #       the value of Connection_Handle_1.
9027        status = le_create_cis(transport, lower_tester, 1, [connection_handle_1], [initiator.handles[0]], 100)
9028        success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
9029
9030        # 34B.2 The IUT sends an HCI_Command_Status event to the Upper Tester with Status set to Unknown Connection
9031        #       Identifier (0x02).
9032        success = status == 0x02 and success
9033    else:
9034        # Alternative 34C (The value of Connection_Handle is different than Connection_Handle_1 or Connection_Handle_2):
9035        # 34C.1 The test ends with a Pass verdict.
9036        pass
9037
9038    # TODO: Verify CIS Access Addresses
9039
9040    ### TERMINATION ###
9041    success = initiator.disconnect(0x13) and success
9042
9043    return success
9044
9045
9046def connected_isochronous_stream_using_non_test_command(transport, upper_tester, lower_tester, trace, packets, phy,
9047                                                        max_transport_latency):
9048    params = SetCIGParameters(
9049        Framing                         = 1,
9050        PHY_C_To_P                      = phy,
9051        PHY_P_To_C                      = phy,
9052        Max_Transport_Latency_C_To_P    = max_transport_latency,
9053        Max_Transport_Latency_P_To_C    = max_transport_latency,
9054        Max_SDU_C_To_P                  = 16,
9055        Max_SDU_P_To_C                  = 16,
9056    )
9057
9058    start_time = transport.get_time()
9059
9060    success, initiator, _, (cis_handle_upper_tester,) = \
9061        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params, use_test_cmd=False)
9062    if not initiator:
9063        return False
9064
9065    for seq_num in range(3):
9066        success = iso_send_payload_pdu(transport, upper_tester, lower_tester, trace, cis_handle_upper_tester,
9067                                       params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, seq_num) and success
9068
9069    success = disconnect(transport, upper_tester, cis_handle_upper_tester, 0x13, 200) == 0 and success
9070    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_CMD_STATUS, trace) and success
9071    success = verifyAndShowEvent(transport, upper_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace) and success
9072    success = verifyAndShowEvent(transport, lower_tester, Events.BT_HCI_EVT_DISCONN_COMPLETE, trace) and success
9073
9074    status, cig_id = le_remove_cig(transport, upper_tester, 0, 100)
9075    success = getCommandCompleteEvent(transport, upper_tester, trace) and status == 0x00 and cig_id == 0 and success
9076
9077    params = SetCIGParameters(
9078        Framing                         = 1,
9079        PHY_C_To_P                      = phy,
9080        PHY_P_To_C                      = phy,
9081        Max_Transport_Latency_C_To_P    = max_transport_latency,
9082        Max_Transport_Latency_P_To_C    = max_transport_latency,
9083        Max_SDU_C_To_P                  = 0,
9084        Max_SDU_P_To_C                  = 16,
9085    )
9086
9087    s, _, (cis_handle_lower_tester,) = establish_cis_connection(transport, upper_tester, lower_tester, trace, params,
9088                                                                initiator.handles[0], use_test_cmd=False)
9089    success = s and success
9090
9091    for seq_num in range(50):
9092        success = iso_send_payload_pdu(transport, lower_tester, upper_tester, trace, cis_handle_lower_tester,
9093                                       params.Max_SDU_P_To_C[0], params.SDU_Interval_P_To_C, seq_num) and success
9094
9095
9096    ### TERMINATION ###
9097    success = initiator.disconnect(0x13) and success
9098
9099    trace.trace(4, "Host verification " + ("PASS" if success else "FAIL"))
9100
9101    ### LL VERIFICATION ###
9102    isoc_framed_pdu_num = 0
9103    for packet in packets.fetch(packet_filter=('LL_CIS_REQ', 'ISOC_FRAMED_PDU')):
9104        if packet.ts/1000 < start_time:
9105            trace.trace(4, "Drop %s" % str(packet))
9106        elif packet.type.name == 'LL_CIS_REQ':
9107            success = packet.payload.CtrData.Framed == 1 and success
9108        elif packet.payload.SegmentationHeader.CMPLT == 1:
9109            isoc_framed_pdu_num += 1
9110
9111    success = isoc_framed_pdu_num == 53 and success
9112
9113    trace.trace(4, "LL verification " + ("PASS" if success else "FAIL"))
9114
9115    return success
9116
9117
9118def ll_cis_cen_bv_26_c(transport, upper_tester, lower_tester, trace, packets):
9119    """LL/CIS/CEN/BV-26-C [Connected Isochronous Stream Using Non-Test Command, Central Initiated]"""
9120    return connected_isochronous_stream_using_non_test_command(transport, upper_tester, lower_tester, trace, packets,
9121                                                               1, 60)
9122
9123
9124def ll_cis_cen_bv_27_c(transport, upper_tester, lower_tester, trace, packets):
9125    """LL/CIS/CEN/BV-27-C [Connected Isochronous Stream Using Non-Test Command, Central Initiated]"""
9126    return connected_isochronous_stream_using_non_test_command(transport, upper_tester, lower_tester, trace, packets,
9127                                                               2, 60)
9128
9129
9130def connected_isochronous_stream_using_non_test_command_force_framed_pdus(transport, upper_tester, lower_tester, trace,
9131                                                                          packets, phy):
9132    params = SetCIGParameters(
9133        SDU_Interval_C_To_P             = 10884,  # 10.884 ms
9134        SDU_Interval_P_To_C             = 10884,  # 10.884 ms
9135        Max_SDU_C_To_P                  = 0x20,
9136        Max_SDU_P_To_C                  = 0x20,
9137        RTN_C_To_P                      = 0x03,
9138        RTN_P_To_C                      = 0x03,
9139        Max_Transport_Latency_C_To_P    = 40,
9140        Max_Transport_Latency_P_To_C    = 40,
9141        Framing                         = 0,  # Unframed
9142        PHY_C_To_P                      = phy,
9143        PHY_P_To_C                      = phy,
9144    )
9145
9146    start_time = transport.get_time()
9147
9148    success, initiator, _, (cis_handle_upper_tester,) = \
9149        state_connected_isochronous_stream(transport, lower_tester, upper_tester, trace, params, use_test_cmd=False)
9150    if not initiator:
9151        return False
9152
9153    for seq_num in range(3):
9154        success = iso_send_payload_pdu(transport, upper_tester, lower_tester, trace, cis_handle_upper_tester,
9155                                       params.Max_SDU_C_To_P[0], params.SDU_Interval_C_To_P, seq_num) and success
9156
9157    ### TERMINATION ###
9158    success = initiator.disconnect(0x13) and success
9159
9160    trace.trace(4, "Host verification " + ("PASS" if success else "FAIL"))
9161
9162    ### LL VERIFICATION ###
9163    isoc_framed_pdu_num = 0
9164    for packet in packets.fetch(packet_filter=('LL_CIS_REQ', 'ISOC_FRAMED_PDU')):
9165        if packet.ts/1000 < start_time:
9166            trace.trace(4, "Drop %s" % str(packet))
9167        elif packet.type.name == 'LL_CIS_REQ':
9168            success = packet.payload.CtrData.Framed == 1 and success
9169        elif packet.payload.SegmentationHeader.CMPLT == 1:
9170            isoc_framed_pdu_num += 1
9171
9172    success = isoc_framed_pdu_num == 3 and success
9173
9174    trace.trace(4, "LL verification " + ("PASS" if success else "FAIL"))
9175
9176    return success
9177
9178
9179def ll_cis_cen_bv_36_c(transport, upper_tester, lower_tester, trace, packets):
9180    """LL/CIS/CEN/BV-36-C [Connected Isochronous Stream Using Non-Test Command, Force Framed PDUs]"""
9181    return connected_isochronous_stream_using_non_test_command_force_framed_pdus(transport, upper_tester, lower_tester,
9182                                                                                 trace, packets, 1)
9183
9184
9185def ll_cis_cen_bv_37_c(transport, upper_tester, lower_tester, trace, packets):
9186    """LL/CIS/CEN/BV-37-C [Connected Isochronous Stream Using Non-Test Command, Force Framed PDUs]"""
9187    return connected_isochronous_stream_using_non_test_command_force_framed_pdus(transport, upper_tester, lower_tester,
9188                                                                                 trace, packets, 2)
9189
9190
9191def ll_ist_cen_bv_01_c(transport, upper_tester, lower_tester, trace):
9192    """LL/IST/CEN/BV-01-C [ISO Transmit Test Mode, CIS]"""
9193    return iso_transmit_test_mode_cis(transport, upper_tester, lower_tester, trace, True)
9194
9195
9196def ll_ist_cen_bv_03_c(transport, upper_tester, lower_tester, trace):
9197    """LL/IST/CEN/BV-03-C [ISO Receive Test Mode, CIS]"""
9198    return iso_receive_test_mode_cis(transport, upper_tester, lower_tester, trace, True)
9199
9200# Implements LL/TIM/ADV/BV-03-C, LL/TIM/ADV/BV-04-C, LL/TIM/ADV/BV-05-C and LL/TIM/ADV/BV-07-C
9201# (only difference is PHY and the timing of the AUX_SCAN_REQ)
9202def do_ll_tim_adv_bv_03_04_05_07_c(transport, upperTester, lowerTester, trace, packets, phy, timing_offset):
9203
9204    advInterval = 0x20 # 32 x 0.625 ms = 20.00 ms
9205    Handle          = 0
9206    Properties      = 0x0002
9207    PrimMinInterval = toArray(advInterval, 3)
9208    PrimMaxInterval = toArray(advInterval, 3)
9209    PrimChannelMap  = 0x07  # Advertise on all three channels (#37, #38 and #39)
9210    OwnAddrType     = SimpleAddressType.PUBLIC
9211    PeerAddrType    = SimpleAddressType.PUBLIC
9212    PeerAddress     = toArray(0x456789ABCDEF, 6)
9213    FilterPolicy    = AdvertisingFilterPolicy.FILTER_NONE
9214    TxPower         = 0
9215    PrimAdvPhy      = PhysicalChannel.LE_1M
9216    SecAdvMaxSkip   = 0
9217    SecAdvPhy       = phy
9218    Sid             = 0
9219    ScanReqNotifyEnable = 0
9220
9221    success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval,
9222                                                      PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower,
9223                                                      PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace)
9224    if not success:
9225        return success
9226
9227    advData = [ 0xAA ]
9228    success = success and preamble_ext_scan_response_data_set(transport, upperTester, Handle, FragmentOperation.COMPLETE_FRAGMENT, 0, advData, trace)
9229    if not success:
9230        return False
9231
9232    success = success and preamble_ext_advertise_enable(transport, upperTester, Advertise.ENABLE, [Handle], [0], [0], trace)
9233    if not success:
9234        return False
9235
9236    responses = 0
9237
9238    for i in range(100):
9239        auxAdvIndPacket = wait_for_AUX_ADV_IND_end(transport, packets)
9240
9241        # Transmit a AUX_SCAN_REQ
9242        packetData = (0b0011 + (12 << 8)).to_bytes(2, 'little', signed=False) # header - PDU Type 0b0101, ChSel, TxAdd and RxAdd all 0, length 12
9243        packetData = b''.join([packetData, 0x456789ABCDEF.to_bytes(6, 'little', signed=False)]) # ScanA
9244        packetData = b''.join([packetData, 0x123456789ABC.to_bytes(6, 'little', signed=False)]) # AdvA
9245        CRC = calcBLECRC(0x555555, packetData)
9246        packetData = b''.join([packetData, CRC.to_bytes(3, 'little', signed=False)])
9247
9248        # Calculate transmit timestamp (T_IFS + timing_offset from end of AUX_ADV_IND)
9249        transmitTime = auxAdvIndPacket.ts + get_packet_air_time(auxAdvIndPacket) + 150 + timing_offset
9250
9251        transport.low_level_device.tx(channel_num_to_index(auxAdvIndPacket.channel_num), auxAdvIndPacket.phy, auxAdvIndPacket.aa, transmitTime, packetData)
9252
9253        # Wait a ms for a response
9254        transport.wait(1)
9255
9256        lastAuxScanResp = packets.findLast(packet_filter=('AUX_SCAN_RSP'))
9257
9258        if lastAuxScanResp:
9259            # Check timing - should be T_IFS (plus or minus 2 μsecs) after the AUX_SCAN_REQ
9260            reqAirTime = math.ceil(((2 if lastAuxScanResp.phy == '2M' else 1) + 4 + 2 + 12 + 3)*8/(2 if lastAuxScanResp.phy == '2M' else 1))
9261            targetTime = transmitTime + reqAirTime + 150
9262            if lastAuxScanResp.ts <= targetTime + 2 and lastAuxScanResp.ts >= targetTime - 2:
9263                responses += 1
9264
9265    # Check: The time between a PDU containing an AuxPtr field and the PDU to which it refers shall be greater than or equal to T_MAFS
9266    for packet in packets.fetch(packet_filter=('AUX_ADV_IND')):
9267        for superiorPacket in packet.payload['SuperiorPackets']:
9268            # Packet air length is: pre-amble + AA + header + payload + CRC
9269            packetLength = (2 if superiorPacket.phy == '2M' else 1) + 4 + 2 + len(superiorPacket) + 3
9270            packetAirtime = math.ceil(8*packetLength/(2 if superiorPacket.phy == '2M' else 1))
9271            success = success and packet.ts >= superiorPacket.ts + packetAirtime + 300
9272
9273    # The IUT responds to at least 95 percent of the AUX_SCAN_REQ packets sent by the Lower Tester
9274    success = success and responses >= 95
9275
9276    return success
9277
9278"""
9279    LL/TIM/ADV/BV-03-C [Extended Advertising, Secondary Channel, Earliest Transmission to Advertiser - LE 1M PHY]
9280"""
9281def ll_tim_adv_bv_03_c(transport, upperTester, lowerTester, trace, packets):
9282    # Note: BabbleSim only supports whole microsecond timings, so using -2 instead of -1.5
9283    # It should not affect the test, since 1.5 us is only used to account for lower tester timing inaccuracies anyway
9284    return do_ll_tim_adv_bv_03_04_05_07_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_1M, -2)
9285
9286"""
9287    LL/TIM/ADV/BV-04-C [Extended Advertising, Secondary Channel, Latest Transmission to Advertiser - LE 1M PHY]
9288"""
9289def ll_tim_adv_bv_04_c(transport, upperTester, lowerTester, trace, packets):
9290    # Note: BabbleSim only supports whole microsecond timings, so using 2 instead of 1.5
9291    # It should not affect the test, since 1.5 us is only used to account for lower tester timing inaccuracies anyway
9292    return do_ll_tim_adv_bv_03_04_05_07_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_1M, 2)
9293
9294"""
9295    LL/TIM/ADV/BV-05-C [Extended Advertising, Secondary Channel, Earliest Transmission to Advertiser - LE 2M PHY]
9296"""
9297def ll_tim_adv_bv_05_c(transport, upperTester, lowerTester, trace, packets):
9298    # Note: BabbleSim only supports whole microsecond timings, so using -2 instead of -1.5
9299    # It should not affect the test, since 1.5 us is only used to account for lower tester timing inaccuracies anyway
9300    return do_ll_tim_adv_bv_03_04_05_07_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_2M, -2)
9301
9302"""
9303    LL/TIM/ADV/BV-07-C [Extended Advertising, Secondary Channel, Latest Transmission to Advertiser - LE 2M PHY]
9304"""
9305def ll_tim_adv_bv_07_c(transport, upperTester, lowerTester, trace, packets):
9306    # Note: BabbleSim only supports whole microsecond timings, so using 2 instead of 1.5
9307    # It should not affect the test, since 1.5 us is only used to account for lower tester timing inaccuracies anyway
9308    return do_ll_tim_adv_bv_03_04_05_07_c(transport, upperTester, lowerTester, trace, packets, PhysicalChannel.LE_2M, 2)
9309
9310LowLevelDeviceRequired = "LowLevelDeviceRequired"
9311__tests__ = {
9312    "LL/CON/ADV/BV-01-C": [ ll_con_adv_bv_01_c, "Accepting Connection Request" ],
9313    "LL/CON/ADV/BV-04-C": [ ll_con_adv_bv_04_c, "Accepting Connection Request after Directed Advertising" ],
9314    "LL/CON/ADV/BV-05-C": [ ll_con_adv_bv_05_c, "Extended Advertising, Accepting Connections; LE 1M PHY", LowLevelDeviceRequired ],
9315    "LL/CON/ADV/BV-06-C": [ ll_con_adv_bv_06_c, "Extended Advertising, Legacy PDUs, Accepting Connections", LowLevelDeviceRequired ],
9316    "LL/CON/ADV/BV-09-C": [ ll_con_adv_bv_09_c, "Accepting Connection Request using Channel Selection Algorithm #2" ],
9317    "LL/CON/ADV/BV-10-C": [ ll_con_adv_bv_10_c, "Accepting Connection Request after Directed Advertising using Channel Selection Algorithm #2" ],
9318    "LL/CON/ADV/BV-12-C": [ ll_con_adv_bv_12_c, "Extended Advertising, Accepting Connections; LE 2M PHY", LowLevelDeviceRequired ],
9319    "LL/CON/ADV/BV-14-C": [ ll_con_adv_bv_14_c, "Extended Advertising, Accepting Connections with Random address; LE 1M PHY" ],
9320    "LL/CON/ADV/BV-15-C": [ ll_con_adv_bv_15_c, "Extended Advertising, Accepting Connections with Random address; LE 2M PHY" ],
9321    "LL/CON/INI/BV-01-C": [ ll_con_ini_bv_01_c, "Connection Initiation rejects Address change" ],
9322    "LL/CON/INI/BV-02-C": [ ll_con_ini_bv_02_c, "Connecting to Advertiser using Directed Advertising Packets" ],
9323    "LL/CON/INI/BV-06-C": [ ll_con_ini_bv_06_c, "Filtered Connection to Advertiser using Undirected Advertising Packets" ],
9324    "LL/CON/INI/BV-07-C": [ ll_con_ini_bv_07_c, "Filtered Connection to Advertiser using Directed Advertising Packets" ],
9325    "LL/CON/INI/BV-08-C": [ ll_con_ini_bv_08_c, "Connecting to Connectable Undirected Advertiser with Network Privacy" ],
9326    "LL/CON/INI/BV-09-C": [ ll_con_ini_bv_09_c, "Connecting to Connectable Undirected Advertiser with Network Privacy thru Resolving List" ],
9327    "LL/CON/INI/BV-10-C": [ ll_con_ini_bv_10_c, "Connecting to Directed Advertiser with Network Privacy thru Resolving List" ],
9328    "LL/CON/INI/BV-11-C": [ ll_con_ini_bv_11_c, "Connecting to Directed Advertiser using  wrong address with Network Privacy thru Resolving List " ],
9329    "LL/CON/INI/BV-12-C": [ ll_con_ini_bv_12_c, "Connecting to Directed Advertiser using Identity address with Network Privacy thru Resolving List" ],
9330    "LL/CON/INI/BV-16-C": [ ll_con_ini_bv_16_c, "Connecting to Advertiser with Channel Selection Algorithm #2" ],
9331    "LL/CON/INI/BV-17-C": [ ll_con_ini_bv_17_c, "Connecting to Directed Advertiser with Channel Selection Algorithm #2" ],
9332    "LL/CON/INI/BV-18-C": [ ll_con_ini_bv_18_c, "Don't connect to Advertiser using Identity address with Network Privacy thru Resolving List" ],
9333    "LL/CON/INI/BV-19-C": [ ll_con_ini_bv_19_c, "Don't connect to Directed Advertiser using Identity address with Network Privacy thru Resolving List" ],
9334    "LL/CON/INI/BV-20-C": [ ll_con_ini_bv_20_c, "Connect to Advertiser using Identity address with Device Privacy thru Resolving List" ],
9335    "LL/CON/INI/BV-21-C": [ ll_con_ini_bv_21_c, "Connect to Directed Advertiser using Identity address with Device Privacy thru Resolving List" ],
9336    "LL/CON/INI/BV-23-C": [ ll_con_ini_bv_23_c, "Network Privacy - Connection Establishment using filterallowlist and resolving list with address resolution disabled" ],
9337    "LL/CON/INI/BV-24-C": [ ll_con_ini_bv_24_c, "Network Privacy - Connection Establishment using resolving list with address resolution disabled" ],
9338    "LL/CON/CEN/BI-06-C": [ ll_con_cen_bi_06_c, "Central responds to Connection Parameter Request - illegal parameters" ],
9339    "LL/CON/CEN/BV-03-C": [ ll_con_cen_bv_03_c, "Central sending Data packets to Peripheral" ],
9340    "LL/CON/CEN/BV-04-C": [ ll_con_cen_bv_04_c, "Central receiving Data packets from Peripheral" ],
9341    "LL/CON/CEN/BV-05-C": [ ll_con_cen_bv_05_c, "Central sending and receiving Data packets to and form Peripheral" ],
9342    "LL/CON/CEN/BV-07-C": [ ll_con_cen_bv_07_c, "Central requests Connection Parameter Update" ],
9343    "LL/CON/CEN/BV-08-C": [ ll_con_cen_bv_08_c, "Central Terminating Connection" ],
9344    "LL/CON/CEN/BV-09-C": [ ll_con_cen_bv_09_c, "Central accepting Connection Termination" ],
9345    "LL/CON/CEN/BV-13-C": [ ll_con_cen_bv_13_c, "Central requests Feature Setup procedure" ],
9346    "LL/CON/CEN/BV-20-C": [ ll_con_cen_bv_20_c, "Central requests Version Exchange procedure" ],
9347    "LL/CON/CEN/BV-21-C": [ ll_con_cen_bv_21_c, "Central responds to Version Exchange procedure" ],
9348    "LL/CON/CEN/BV-23-C": [ ll_con_cen_bv_23_c, "Central responds to Feature Exchange procedure" ],
9349    "LL/CON/CEN/BV-24-C": [ ll_con_cen_bv_24_c, "Central requests Connection Parameters - Peripheral Accepts" ],
9350    "LL/CON/CEN/BV-25-C": [ ll_con_cen_bv_25_c, "Central requests Connection Parameters - Peripheral Rejects" ],
9351    "LL/CON/CEN/BV-26-C": [ ll_con_cen_bv_26_c, "Central requests Connection Parameters - same procedure collision" ],
9352    "LL/CON/CEN/BV-27-C": [ ll_con_cen_bv_27_c, "Central requests Connection Parameters - Channel Map Update procedure collision" ],
9353    "LL/CON/CEN/BV-29-C": [ ll_con_cen_bv_29_c, "Central requests Connection Parameters - Peripheral unsupported" ],
9354    "LL/CON/CEN/BV-30-C": [ ll_con_cen_bv_30_c, "Central responds to Connection Parameters request - no Preferred_Periodicity" ],
9355    "LL/CON/CEN/BV-34-C": [ ll_con_cen_bv_34_c, "Central responds to Connection Parameters request - event masked" ],
9356    "LL/CON/CEN/BV-35-C": [ ll_con_cen_bv_35_c, "Central responds to Connection Parameters request - Host rejects" ],
9357    "LL/CON/CEN/BV-41-C": [ ll_con_cen_bv_41_c, "Central requests PHY Update procedure" ],
9358    "LL/CON/CEN/BV-43-C": [ ll_con_cen_bv_43_c, "Central responds to PHY Update procedure" ],
9359    "LL/CON/CEN/BV-73-C": [ ll_con_cen_bv_73_c, "Central Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 1M PHY" ],
9360    "LL/CON/CEN/BV-74-C": [ ll_con_cen_bv_74_c, "Central Packet Data Length Update - Initiating Packet Data Length Update Procedure; LE 1M PHY" ],
9361    "LL/CON/CEN/BV-76-C": [ ll_con_cen_bv_76_c, "Central Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 2M PHY" ],
9362    "LL/CON/CEN/BV-77-C": [ ll_con_cen_bv_77_c, "Central Packet Data Length Update - Initiating Packet Data Length Update Procedure; LE 2M PHY" ],
9363    "LL/CON/PER/BI-08-C": [ ll_con_per_bi_08_c, "Peripheral responds to Connection Parameters request - Illegal Parameters" ],
9364    "LL/CON/PER/BV-04-C": [ ll_con_per_bv_04_c, "Connection where Peripheral sends data to Central" ],
9365    "LL/CON/PER/BV-05-C": [ ll_con_per_bv_05_c, "Connection where Peripheral receives data from Central" ],
9366    "LL/CON/PER/BV-06-C": [ ll_con_per_bv_06_c, "Connection where Peripheral sends and receives data to and from Central" ],
9367    "LL/CON/PER/BV-10-C": [ ll_con_per_bv_10_c, "Peripheral accepting Connection Parameter Update from Central" ],
9368    "LL/CON/PER/BV-11-C": [ ll_con_per_bv_11_c, "Peripheral sending Termination to Central" ],
9369    "LL/CON/PER/BV-12-C": [ ll_con_per_bv_12_c, "Peripheral accepting Termination from Central" ],
9370#   "LL/CON/PER/BV-13-C": [ ll_con_per_bv_13_c, "Peripheral Terminating Connection on Supervision Timer" ],
9371    "LL/CON/PER/BV-14-C": [ ll_con_per_bv_14_c, "Peripheral performs Feature Setup procedure" ],
9372    "LL/CON/PER/BV-19-C": [ ll_con_per_bv_19_c, "Peripheral requests Version Exchange procedure" ],
9373    "LL/CON/PER/BV-20-C": [ ll_con_per_bv_20_c, "Peripheral responds to Version Exchange procedure" ],
9374    "LL/CON/PER/BV-22-C": [ ll_con_per_bv_22_c, "Peripheral requests Feature Exchange procedure" ],
9375    "LL/CON/PER/BV-24-C": [ ll_con_per_bv_24_c, "Peripheral requests Connection Parameters - Central Accepts" ],
9376    "LL/CON/PER/BV-25-C": [ ll_con_per_bv_25_c, "Peripheral requests Connection Parameters - Central Rejects" ],
9377    "LL/CON/PER/BV-26-C": [ ll_con_per_bv_26_c, "Peripheral requests Connection Parameters - same procedure collision" ],
9378    "LL/CON/PER/BV-27-C": [ ll_con_per_bv_27_c, "Peripheral requests Connection Parameters - channel map update procedure collision" ],
9379    "LL/CON/PER/BV-29-C": [ ll_con_per_bv_29_c, "Peripheral responds to Connection Parameters - Central no Preferred Periodicity" ],
9380    "LL/CON/PER/BV-33-C": [ ll_con_per_bv_33_c, "Peripheral responds to Connection Parameters request - event masked" ],
9381    "LL/CON/PER/BV-34-C": [ ll_con_per_bv_34_c, "Peripheral responds to Connection Parameters request - Host rejects" ],
9382    "LL/CON/PER/BV-40-C": [ ll_con_per_bv_40_c, "Peripheral requests PHY Update procedure" ],
9383    "LL/CON/PER/BV-42-C": [ ll_con_per_bv_42_c, "Peripheral responds to PHY Update procedure" ],
9384    "LL/CON/PER/BV-77-C": [ ll_con_per_bv_77_c, "Peripheral Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 1M PHY" ],
9385    "LL/CON/PER/BV-78-C": [ ll_con_per_bv_78_c, "Peripheral requests Packet Data Length Update procedure; LE 1M PHY" ],
9386    "LL/CON/PER/BV-80-C": [ ll_con_per_bv_80_c, "Peripheral Packet Data Length Update - Responding to Packet Data Length Update Procedure; LE 2M PHY" ],
9387    "LL/CON/PER/BV-81-C": [ ll_con_per_bv_81_c, "Peripheral requests Packet Data Length Update procedure; LE 2M PHY" ],
9388    "LL/DDI/ADV/BI-05-C": [ ll_ddi_adv_bi_05_c, "Disallow Extended Advertising PDU sizes for Legacy Advertising when advertising enabled" ],
9389    "LL/DDI/ADV/BI-06-C": [ ll_ddi_adv_bi_06_c, "Disallow Extended Advertising PDU sizes for Scannable Legacy Advertising when advertising enabled" ],
9390    "LL/DDI/ADV/BV-01-C": [ ll_ddi_adv_bv_01_c, "Non-Connectable Advertising Packets on one channel" ],
9391    "LL/DDI/ADV/BV-02-C": [ ll_ddi_adv_bv_02_c, "Undirected Advertising Packets on one channel" ],
9392    "LL/DDI/ADV/BV-03-C": [ ll_ddi_adv_bv_03_c, "Non-Connectable Advertising Packets on all channels" ],
9393    "LL/DDI/ADV/BV-04-C": [ ll_ddi_adv_bv_04_c, "Undirected Advertising with Data on all channels " ],
9394    "LL/DDI/ADV/BV-05-C": [ ll_ddi_adv_bv_05_c, "Undirected Connectable Advertising with Scan Request/Response " ],
9395    "LL/DDI/ADV/BV-06-C": [ ll_ddi_adv_bv_06_c, "Stop Advertising on Connection Request" ],
9396    "LL/DDI/ADV/BV-07-C": [ ll_ddi_adv_bv_07_c, "Scan Request/Response followed by Connection Request" ],
9397    "LL/DDI/ADV/BV-08-C": [ ll_ddi_adv_bv_08_c, "Advertiser Filtering Scan requests" ],
9398    "LL/DDI/ADV/BV-09-C": [ ll_ddi_adv_bv_09_c, "Advertiser Filtering Connection requests" ],
9399    "LL/DDI/ADV/BV-11-C": [ ll_ddi_adv_bv_11_c, "High Duty Cycle Connectable Directed Advertising on all channels" ],
9400    "LL/DDI/ADV/BV-15-C": [ ll_ddi_adv_bv_15_c, "Discoverable Undirected Advertising on all channels" ],
9401    "LL/DDI/ADV/BV-16-C": [ ll_ddi_adv_bv_16_c, "Discoverable Undirected Advertising with Data on all channels" ],
9402    "LL/DDI/ADV/BV-17-C": [ ll_ddi_adv_bv_17_c, "Discoverable Undirected Advertising with Scan Request/Response" ],
9403    "LL/DDI/ADV/BV-18-C": [ ll_ddi_adv_bv_18_c, "Discoverable Undirected Advertiser Filtering Scan requests " ],
9404    "LL/DDI/ADV/BV-19-C": [ ll_ddi_adv_bv_19_c, "Low Duty Cycle Directed Advertising on all channels" ],
9405    "LL/DDI/ADV/BV-20-C": [ ll_ddi_adv_bv_20_c, "Advertising on the LE 1M PHY on all channels" ],
9406    "LL/DDI/ADV/BV-21-C": [ ll_ddi_adv_bv_21_c, "Non-Connectable Extended Legacy Advertising with Data on all channels" ],
9407    "LL/DDI/ADV/BV-22-C": [ ll_ddi_adv_bv_22_c, "Extended Advertising, Legacy PDUs, Undirected, CSA #2" ],
9408    "LL/DDI/ADV/BV-27-C": [ ll_ddi_adv_bv_27_c, "Extended Advertising, Host Modifying Data and ADI" ],
9409    "LL/DDI/ADV/BV-28-C": [ ll_ddi_adv_bv_28_c, "Extended Advertising, Overlapping Extended Advertising Events" ],
9410    "LL/DDI/ADV/BV-45-C": [ ll_ddi_adv_bv_45_c, "Extended Advertising, Scannable - ADI allowed in scan response", LowLevelDeviceRequired ],
9411    "LL/DDI/ADV/BV-47-C": [ ll_ddi_adv_bv_47_c, "Extended Advertising, Non-Connectable - LE 1M PHY" ],
9412    "LL/DDI/ADV/BV-49-C": [ ll_ddi_adv_bv_49_c, "Extended Advertising, Non-Connectable - LE 2M PHY" ],
9413    "LL/DDI/ADV/BV-52-C": [ ll_ddi_adv_bv_52_c, "Extended Advertising, Scannable - ADI allowed in scan response - LE 2M PHY", LowLevelDeviceRequired ],
9414    "LL/DDI/SCN/BV-01-C": [ ll_ddi_scn_bv_01_c, "Passive Scanning of Non-Connectable Advertising Packets" ],
9415    "LL/DDI/SCN/BV-02-C": [ ll_ddi_scn_bv_02_c, "Filtered Passive Scanning of Non-Connectable Advertising Packets" ],
9416    "LL/DDI/SCN/BV-03-C": [ ll_ddi_scn_bv_03_c, "Active Scanning of Connectable Undirected Advertising Packets" ],
9417    "LL/DDI/SCN/BV-04-C": [ ll_ddi_scn_bv_04_c, "Filtered Active Scanning of Connectable Undirected Advertising Packets" ],
9418    "LL/DDI/SCN/BV-05-C": [ ll_ddi_scn_bv_05_c, "Scanning for different Advertiser types with and without Data" ],
9419    "LL/DDI/SCN/BV-10-C": [ ll_ddi_scn_bv_10_c, "Passive Scanning for Undirected Advertising Packets with Data" ],
9420    "LL/DDI/SCN/BV-11-C": [ ll_ddi_scn_bv_11_c, "Passive Scanning for Directed Advertising Packets" ],
9421    "LL/DDI/SCN/BV-12-C": [ ll_ddi_scn_bv_12_c, "Passive Scanning for Discoverable Undirected Advertising Packets" ],
9422    "LL/DDI/SCN/BV-13-C": [ ll_ddi_scn_bv_13_c, "Passive Scanning for Non-Connectable Advertising Packets using Network Privacy" ],
9423    "LL/DDI/SCN/BV-14-C": [ ll_ddi_scn_bv_14_c, "Passive Scanning for Connectable Directed Advertising Packets using Network Privacy" ],
9424    "LL/DDI/SCN/BV-15-C": [ ll_ddi_scn_bv_15_c, "Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with no Local or Peer IRK" ],
9425    "LL/DDI/SCN/BV-16-C": [ ll_ddi_scn_bv_16_c, "Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with Local and no Peer IRK" ],
9426    "LL/DDI/SCN/BV-17-C": [ ll_ddi_scn_bv_17_c, "Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with no Local and a Peer IRK" ],
9427    "LL/DDI/SCN/BV-18-C": [ ll_ddi_scn_bv_18_c, "Active Scanning for Scannable Undirected Advertising Packets using Network Privacy with both Local and Peer IRKs" ],
9428    "LL/DDI/SCN/BV-26-C": [ ll_ddi_scn_bv_26_c, "Passive Scanning for Non-Connectable Advertising Packets using Network Privacy" ],
9429    "LL/DDI/SCN/BV-28-C": [ ll_ddi_scn_bv_28_c, "Passive Scanning for Non-Connectable Advertising Packets using Device Privacy" ],
9430#   "LL/SEC/ADV/BV-01-C": [ ll_sec_adv_bv_01_c, "Changing Static Address while Advertising" ],
9431    "LL/SEC/ADV/BV-02-C": [ ll_sec_adv_bv_02_c, "Non Connectable Undirected Advertising with non-resolvable private address" ],
9432    "LL/SEC/ADV/BV-03-C": [ ll_sec_adv_bv_03_c, "Non Connectable Undirected Advertising with resolvable private address" ],
9433    "LL/SEC/ADV/BV-04-C": [ ll_sec_adv_bv_04_c, "Scannable Undirected Advertising with non-resolvable private address" ],
9434    "LL/SEC/ADV/BV-05-C": [ ll_sec_adv_bv_05_c, "Scannable Undirected Advertising with resolvable private address" ],
9435    "LL/SEC/ADV/BV-06-C": [ ll_sec_adv_bv_06_c, "Connecting with Undirected Connectable Advertiser using non-resolvable private address" ],
9436#   "LL/SEC/ADV/BV-07-C": [ ll_sec_adv_bv_07_c, "Connecting with Undirected Connectable Advertiser with Local IRK but no Peer IRK" ],
9437    "LL/SEC/ADV/BV-08-C": [ ll_sec_adv_bv_08_c, "Connecting with Undirected Connectable Advertiser with both Local and Peer IRK" ],
9438    "LL/SEC/ADV/BV-09-C": [ ll_sec_adv_bv_09_c, "Connecting with Undirected Connectable Advertiser with no Local IRK but peer IRK" ],
9439    "LL/SEC/ADV/BV-10-C": [ ll_sec_adv_bv_10_c, "Connecting with Undirected Connectable Advertiser where no match for Peer Device Identity" ],
9440    "LL/SEC/ADV/BV-11-C": [ ll_sec_adv_bv_11_c, "Connecting with Directed Connectable Advertiser using local and remote IRK" ],
9441    "LL/SEC/ADV/BV-12-C": [ ll_sec_adv_bv_12_c, "Connecting with Directed Connectable Advertising with local IRK but without remote IRK" ],
9442    "LL/SEC/ADV/BV-13-C": [ ll_sec_adv_bv_13_c, "Directed Connectable Advertising without local IRK but with remote IRK" ],
9443    "LL/SEC/ADV/BV-14-C": [ ll_sec_adv_bv_14_c, "Directed Connectable Advertising using Resolving List and Peer Device Identity not in the List" ],
9444    "LL/SEC/ADV/BV-15-C": [ ll_sec_adv_bv_15_c, "Scannable Advertising with resolvable private address, no Scan Response to Identity Address" ],
9445    "LL/SEC/ADV/BV-16-C": [ ll_sec_adv_bv_16_c, "Undirected Connectable Advertising with resolvable private address; no Connection to Identity Address" ],
9446    "LL/SEC/ADV/BV-17-C": [ ll_sec_adv_bv_17_c, "Directed Connectable Advertising using local and remote IRK, Ignore Identity Address" ],
9447    "LL/SEC/ADV/BV-18-C": [ ll_sec_adv_bv_18_c, "Scannable Advertising with resolvable private address, accept Identity Address" ],
9448#   "LL/SEC/ADV/BV-19-C": [ ll_sec_adv_bv_19_c, "Undirected Connectable Advertising with Local IRK and Peer IRK, accept Identity Address" ],
9449    "LL/SEC/ADV/BV-20-C": [ ll_sec_adv_bv_20_c, "Directed Connectable Advertising with resolvable private address; Connect to Identity Address" ],
9450    "LL/SEC/SCN/BV-01-C": [ ll_sec_scn_bv_01_c, "Changing Static Address while Scanning" ],
9451    "LL/CIS/CEN/BV-01-C": [ ll_cis_cen_bv_01_c, "CIS Setup Procedure, Central Initiated" ],
9452    "LL/CIS/CEN/BV-02-C": [ ll_cis_cen_bv_02_c, "CIS Setup Procedure, Central Initiated" ],
9453    "LL/CIS/CEN/BV-31-C": [ ll_cis_cen_bv_31_c, "CIS Setup Procedure, Central Initiated" ],
9454    "LL/CIS/CEN/BV-39-C": [ ll_cis_cen_bv_39_c, "CIS Setup Procedure, Central Initiated" ],
9455    "LL/CIS/CEN/BV-03-C": [ ll_cis_cen_bv_03_c, "CIS Setup Procedure, Central Initiated, Rejected" ],
9456    "LL/CIS/CEN/BV-04-C": [ ll_cis_cen_bv_04_c, "New Channel Map" ],
9457    "LL/CIS/CEN/BV-40-C": [ ll_cis_cen_bv_40_c, "New Channel Map" ],
9458    "LL/CIS/CEN/BV-20-C": [ ll_cis_cen_bv_20_c, "Set Encryption After CIS Established" ],
9459    "LL/CIS/CEN/BV-26-C": [ ll_cis_cen_bv_26_c, "Connected Isochronous Stream Using Non-Test Command, Central Initiated" ],
9460    "LL/CIS/CEN/BV-27-C": [ ll_cis_cen_bv_27_c, "Connected Isochronous Stream Using Non-Test Command, Central Initiated" ],
9461    "LL/CIS/CEN/BV-30-C": [ ll_cis_cen_bv_30_c, "Isochronous Channels Host Support Feature Bit" ],
9462    "LL/CIS/CEN/BV-08-C": [ ll_cis_cen_bv_08_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG, Central" ],
9463    "LL/CIS/CEN/BV-43-C": [ ll_cis_cen_bv_43_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG, Central" ],
9464    "LL/CIS/CEN/BV-09-C": [ ll_cis_cen_bv_09_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Sequential, Central" ],
9465    "LL/CIS/CEN/BV-36-C": [ ll_cis_cen_bv_36_c, "Connected Isochronous Stream Using Non-Test Command, Force Framed PDUs" ],
9466    "LL/CIS/CEN/BV-37-C": [ ll_cis_cen_bv_37_c, "Connected Isochronous Stream Using Non-Test Command, Force Framed PDUs" ],
9467    "LL/CIS/CEN/BV-44-C": [ ll_cis_cen_bv_44_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG, Central, BN > 1, NSE = 2" ],
9468    # "LL/CIS/CEN/BV-51-C": [ ll_cis_cen_bv_51_c, "CIS Setup Procedure, Central Initiated, CIG ID Reuse" ],
9469    "LL/CIS/CEN/BV-06-C": [ ll_cis_cen_bv_06_c, "Receiving data in Unidirectional CIS" ],
9470    "LL/CIS/CEN/BV-07-C": [ ll_cis_cen_bv_07_c, "Sending and Receiving Data in Bidirectional CIS" ],
9471    "LL/CIS/CEN/BV-35-C": [ ll_cis_cen_bv_35_c, "Sending and Receiving Data in Bidirectional CIS, Encryption" ],
9472    # "LL/CIS/CEN/BV-15-C": [ ll_cis_cen_bv_15_c, "CIS Terminate Procedure, Initiated" ],
9473    "LL/CIS/CEN/BV-16-C": [ ll_cis_cen_bv_16_c, "CIS Terminate Procedure, Accepting" ],
9474    "LL/CIS/CEN/BV-24-C": [ ll_cis_cen_bv_24_c, "CIS Updating Peer Clock Accuracy" ],
9475    "LL/CIS/CEN/BV-45-C": [ ll_cis_cen_bv_45_c, "Sending Data in Unidirectional CIS, BN = 1" ],
9476    "LL/CIS/CEN/BV-46-C": [ ll_cis_cen_bv_46_c, "Receiving Data in Unidirectional CIS, BN = 1" ],
9477    "LL/CIS/CEN/BV-47-C": [ ll_cis_cen_bv_47_c, "Sending and Receiving Data in Bidirectional CIS, BN = 1" ],
9478    "LL/CIS/CEN/BV-48-C": [ ll_cis_cen_bv_48_c, "Sending and Receiving Data in Bidirectional CIS, BN = 1, Encryption" ],
9479    "LL/CIS/PER/BV-01-C": [ ll_cis_per_bv_01_c, "CIS Setup Response Procedure, Peripheral" ],
9480    "LL/CIS/PER/BV-02-C": [ ll_cis_per_bv_02_c, "CIS Setup Response Procedure, Peripheral, Reject Response" ],
9481    "LL/CIS/PER/BV-03-C": [ ll_cis_per_bv_03_c, "CIS Map Update" ],
9482    "LL/CIS/PER/BV-05-C": [ ll_cis_per_bv_05_c, "Receiving data in Unidirectional CIS" ],
9483    "LL/CIS/PER/BV-06-C": [ ll_cis_per_bv_06_c, "Sending and Receiving Data in Bidirectional CIS" ],
9484#   "LL/CIS/PER/BV-07-C": [ ll_cis_per_bv_07_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG, Peripheral" ],  # https://github.com/EDTTool/packetcraft/issues/12, https://github.com/EDTTool/packetcraft/issues/15
9485#   "LL/CIS/PER/BV-08-C": [ ll_cis_per_bv_08_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Sequential, Peripheral" ],  # https://github.com/EDTTool/EDTT-le-audio/issues/72
9486    "LL/CIS/PER/BV-18-C": [ ll_cis_per_bv_18_c, "CIS Updating Peer Clock Accuracy" ],
9487    "LL/CIS/PER/BV-19-C": [ ll_cis_per_bv_19_c, "CIS Setup Response Procedure, Peripheral" ],
9488    "LL/CIS/PER/BV-22-C": [ ll_cis_per_bv_22_c, "CIS Request Event Not Set" ],
9489    "LL/CIS/PER/BV-23-C": [ ll_cis_per_bv_23_c, "CIS Setup Response Procedure, Peripheral" ],
9490#   "LL/CIS/PER/BV-27-C": [ ll_cis_per_bv_27_c, "Sending and Receiving Data in Bidirectional CIS, Encryption" ],  # https://github.com/EDTTool/EDTT-le-audio/issues/75
9491    "LL/CIS/PER/BV-29-C": [ ll_cis_per_bv_29_c, "CIS Setup Response Procedure, Peripheral" ],
9492    "LL/CIS/PER/BV-31-C": [ ll_cis_per_bv_31_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Interleaved CIG, Peripheral, NSE=2" ],
9493    "LL/CIS/PER/BV-32-C": [ ll_cis_per_bv_32_c, "Sending and Receiving Data in Multiple CISes, Single CIG, Single Connection, Peripheral, BN=1" ],
9494    "LL/CIS/PER/BV-33-C": [ ll_cis_per_bv_33_c, "Sending Data in Unidirectional CIS, BN = 1" ],
9495    "LL/CIS/PER/BV-34-C": [ ll_cis_per_bv_34_c, "Receiving Data in Unidirectional CIS, BN = 1" ],
9496    "LL/CIS/PER/BV-35-C": [ ll_cis_per_bv_35_c, "Sending and Receiving Data in Bidirectional CIS, BN = 1" ],
9497    "LL/CIS/PER/BV-36-C": [ ll_cis_per_bv_36_c, "Sending and Receiving Data in Bidirectional CIS, BN = 1, Encryption "],
9498    "LL/CIS/PER/BV-37-C": [ ll_cis_per_bv_37_c, "CIS Map Update" ],
9499#   "LL/CIS/PER/BV-39-C": [ ll_cis_per_bv_39_c, "CIS Peripheral Accepts All Supported NSE Values" ],  # https://github.com/EDTTool/EDTT-le-audio/issues/84
9500#   "LL/CIS/PER/BV-40-C": [ ll_cis_per_bv_40_c, "CIS Setup Response Procedure, Peripheral" ],  # https://github.com/EDTTool/EDTT-le-audio/issues/85
9501    "LL/CIS/PER/BV-12-C": [ ll_cis_per_bv_12_c, "CIS Terminate Procedure, Initiated - Peripheral" ],
9502    "LL/CIS/PER/BV-13-C": [ ll_cis_per_bv_13_c, "CIS Terminate Procedure, Accepting, Peripheral" ],
9503#   "LL/IST/CEN/BV-01-C": [ ll_ist_cen_bv_01_c, "ISO Transmit Test Mode, CIS" ],  # https://github.com/EDTTool/EDTT-le-audio/issues/86
9504#   "LL/IST/PER/BV-01-C": [ ll_ist_per_bv_01_c, "ISO Transmit Test Mode, CIS" ],  # https://github.com/EDTTool/EDTT-le-audio/issues/86
9505#   "LL/IST/CEN/BV-03-C": [ ll_ist_cen_bv_03_c, "ISO Receive Test Mode, CIS" ],  # https://github.com/EDTTool/packetcraft/issues/10
9506#   "LL/IST/PER/BV-03-C": [ ll_ist_per_bv_03_c, "ISO Receive Test Mode, CIS" ],  # https://github.com/EDTTool/packetcraft/issues/10
9507    "LL/TIM/ADV/BV-03-C": [ ll_tim_adv_bv_03_c, "Extended Advertising, Secondary Channel, Earliest Transmission to Advertiser - LE 1M PHY", LowLevelDeviceRequired],
9508    "LL/TIM/ADV/BV-04-C": [ ll_tim_adv_bv_04_c, "Extended Advertising, Secondary Channel, Latest Transmission to Advertiser - LE 1M PHY", LowLevelDeviceRequired],
9509    "LL/TIM/ADV/BV-05-C": [ ll_tim_adv_bv_05_c, "Extended Advertising, Secondary Channel, Earliest Transmission to Advertiser - LE 2M PHY", LowLevelDeviceRequired],
9510    "LL/TIM/ADV/BV-07-C": [ ll_tim_adv_bv_07_c, "Extended Advertising, Secondary Channel, Latest Transmission to Advertiser - LE 2M PHY", LowLevelDeviceRequired],
9511};
9512
9513_maxNameLength = max([ len(key) for key in __tests__ ]);
9514
9515_spec = {key: TestSpec(name=key, number_devices=2, description="#[" + __tests__[key][1] + "]",
9516                       test_private=__tests__[key][0],
9517                       require_low_level_device=len(__tests__[key]) >= 3 and __tests__[key][2] == LowLevelDeviceRequired) for key in __tests__}
9518
9519"""
9520    Return the test spec which contains info about all the tests
9521    this test module provides
9522"""
9523def get_tests_specs():
9524    return _spec;
9525
9526def preamble(transport, trace):
9527    global lowerIRK, upperIRK, ENC_KEYS
9528
9529    ok = success = preamble_standby(transport, 0, trace);
9530    trace.trace(4, "preamble Standby " + ("PASS" if success else "FAIL"));
9531    success = preamble_standby(transport, 1, trace);
9532    ok = ok and success;
9533    trace.trace(4, "preamble Standby " + ("PASS" if success else "FAIL"));
9534    success, upperIRK, tests.test_utils.upperRandomAddress = preamble_device_address_set(transport, 0, trace);
9535    trace.trace(4, "preamble Device Address Set " + ("PASS" if success else "FAIL"));
9536    ok = ok and success;
9537    success, lowerIRK, tests.test_utils.lowerRandomAddress = preamble_device_address_set(transport, 1, trace);
9538    trace.trace(4, "preamble Device Address Set " + ("PASS" if success else "FAIL"));
9539    ok = ok and success
9540    success, *ENC_KEYS = preamble_encryption_keys_calculated(transport, 1, trace)
9541    trace.trace(4, "preamble Encryption Keys Calculated " + ("PASS" if success else "FAIL"))
9542    return ok and success;
9543
9544"""
9545    Run a test given its test_spec
9546"""
9547def run_a_test(args, transport, trace, test_spec, device_dumps):
9548    try:
9549        success = preamble(transport, trace);
9550    except Exception as e:
9551        trace.trace(3, "Preamble generated exception: %s" % str(e));
9552        success = False;
9553
9554    trace.trace(2, "%-*s %s test started..." % (_maxNameLength, test_spec.name, test_spec.description[1:]));
9555    if not success:
9556        trace.trace(3, "Preamble failed, actual test function will not run" );
9557    test_f = test_spec.test_private;
9558    try:
9559        if test_spec.require_low_level_device and not transport.low_level_device:
9560            trace.trace(1, "Error: Test case requires a low level device, but transport does not have one!")
9561            success = False
9562        elif test_f.__code__.co_argcount > 4:
9563            success = success and test_f(transport, 0, 1, trace, device_dumps);
9564        elif test_f.__code__.co_argcount > 3:
9565            success = success and test_f(transport, 0, 1, trace);
9566        else:
9567            success = success and test_f(transport, 0, trace);
9568    except Exception as e:
9569        import traceback
9570        traceback.print_exc()
9571        trace.trace(3, "Test generated exception: %s" % str(e));
9572        success = False;
9573
9574    return not success
9575
9576