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