1# -*- coding: utf-8 -*- 2# Copyright 2019 Oticon A/S 3# SPDX-License-Identifier: Apache-2.0 4 5from numpy import random; 6import os; 7import math; 8from enum import IntEnum; 9from components.utils import *; 10from components.basic_commands import *; 11from components.address import *; 12from components.events import *; 13from components.resolvable import *; 14from components.advertiser import *; 15from components.scanner import *; 16from components.initiator import *; 17from components.preambles import *; 18from components.test_spec import TestSpec; 19 20global lowerIRK, upperIRK, lowerRandomAddress, upperRandomAddress; 21 22class Role(IntEnum): 23 CENTRAL = 0 24 PERIPHERAL = 1 25 26def __check_command_complete_event(transport, idx, trace): 27 event = get_event(transport, idx, 100); 28 trace.trace(7, str(event)); 29 return event.isCommandComplete(); 30 31def __check_unknown_command_rsp_event(transport, idx, trace, status): 32 event = get_event(transport, idx, 100); 33 trace.trace(7, str(event)); 34 return status == 1 and (event.isCommandComplete() or event.isCommandStatus()) 35 36""" 37 HCI/GEV/BV-01-C [Status return for Unsupported Commands] 38""" 39def hci_gev_bv_01_c(transport, idx, trace): 40 41 NumRsp, length, lap = 0, 1, toArray(0x9E8B00, 3); 42 43 status = inquire(transport, idx, lap, length, NumRsp, 100); 44 success = __check_unknown_command_rsp_event(transport, idx, trace, status); 45 46 status = read_buffer_size(transport, idx, 100); 47 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 48 49 le, simul = 0, 0; 50 51 status = write_le_host_support(transport, idx, le, simul, 100); 52 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 53 54 handle, props, PrimChannelMap, OwnAddrType, PeerAddrType = 0, 0, 0, 0, 0; 55 PrimMinInterval = [0 for _ in range(3)]; 56 PrimMaxInterval = [0 for _ in range(3)]; 57 AVal = [0 for _ in range(6)]; 58 FilterPolicy, TxPower, PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, sid, ScanReqNotifyEnable = 0, 0, 0, 0, 0, 0, 0; 59 60 status = le_set_extended_advertising_parameters(transport, idx, handle, props, PrimMinInterval, PrimMaxInterval, PrimChannelMap, \ 61 OwnAddrType, PeerAddrType, AVal, FilterPolicy, TxPower, PrimAdvPhy, SecAdvMaxSkip, \ 62 SecAdvPhy, sid, ScanReqNotifyEnable, 100); 63 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 64 65 handle, op, FragPref = 0, 0, 0; 66 data = []; 67 68 status = le_set_extended_advertising_data(transport, idx, handle, op, FragPref, data, 100); 69 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 70 71 handle, op, FragPref = 0, 0, 0; 72 data = []; 73 74 status = le_set_extended_scan_response_data(transport, idx, handle, op, FragPref, data, 100); 75 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 76 77 enable, SetNum = 0, 0; 78 SHandle = [0 for i in range(SetNum)]; 79 SDuration = [0 for i in range(SetNum)]; 80 SMaxExtAdvEvts = [0 for i in range(SetNum)]; 81 82 status = le_set_extended_advertising_enable(transport, idx, enable, SetNum, SHandle, SDuration, SMaxExtAdvEvts, 100); 83 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 84 85 status = le_read_maximum_advertising_data_length(transport, idx, 100); 86 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 87 88 status = le_read_number_of_supported_advertising_sets(transport, idx, 100); 89 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 90 91 handle = 0; 92 93 status = le_remove_advertising_set(transport, idx, handle, 100); 94 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 95 96 status = le_clear_advertising_sets(transport, idx, 100); 97 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 98 99 handle, MinInterval, MaxInterval, props = 0, 0, 0, 0; 100 101 status = le_set_periodic_advertising_parameters(transport, idx, handle, MinInterval, MaxInterval, props, 100); 102 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 103 104 handle, op, dataLength = 0, 0, 251; 105 data = [0 for i in range(dataLength)]; 106 107 status = le_set_periodic_advertising_data(transport, idx, handle, op, dataLength, data, 100); 108 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 109 110 handle, enable = 0, 0; 111 112 status = le_set_periodic_advertising_enable(transport, idx, enable, handle, 100); 113 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 114 115 OwnAddrType, FilterPolicy, phys = 0, 0, 0; 116 PType = [0 for i in range(phys)]; 117 PInterval = [0 for i in range(phys)]; 118 PWindow = [0 for i in range(phys)]; 119 120 status = le_set_extended_scan_parameters(transport, idx, OwnAddrType, FilterPolicy, phys, PType, PInterval, PWindow, 100); 121 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 122 123 enable, FilterDup, duration, period = 0, 0, 0, 0; 124 125 status = le_set_extended_scan_enable(transport, idx, enable, FilterDup, duration, period, 100); 126 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 127 128 FilterPolicy, OwnAddrType, PeerAddrType, phys = 0, 0, 0, 0; 129 AVal = [0 for i in range(6)]; 130 PInterval = [0 for i in range(phys)]; 131 PWindow = [0 for i in range(phys)]; 132 PConnIntervalMin = [0 for i in range(phys)]; 133 PConnIntervalMax = [0 for i in range(phys)]; 134 PConnLatency = [0 for i in range(phys)]; 135 PSupervisionTimeout = [0 for i in range(phys)]; 136 PMinCeLen = [0 for i in range(phys)]; 137 PMaxCeLen = [0 for i in range(phys)]; 138 139 status = le_extended_create_connection(transport, idx, FilterPolicy, OwnAddrType, PeerAddrType, AVal, phys, PInterval, PWindow, \ 140 PConnIntervalMin, PConnIntervalMax, PConnLatency, PSupervisionTimeout, PMinCeLen, PMaxCeLen, 100); 141 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 142 143 FilterPolicy, sid, AddrType, skip, SyncTimeout, unused = 0, 0, 0, 0, 0, 0; 144 AVal = [0 for i in range(6)]; 145 146 status = le_periodic_advertising_create_sync(transport, idx, FilterPolicy, sid, AddrType, AVal, skip, SyncTimeout, unused, 100); 147 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 148 149 status = le_periodic_advertising_create_sync_cancel(transport, idx, 100); 150 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 151 152 handle = 0; 153 154 status = le_periodic_advertising_terminate_sync(transport, idx, handle, 100); 155 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 156 157 AddrType, sid = 0, 0; 158 AVal = [0 for i in range(6)]; 159 160 status = le_add_device_to_periodic_advertiser_list(transport, idx, AddrType, AVal, sid, 100); 161 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 162 163 AddrType, sid = 0, 0; 164 AVal = [0 for i in range(6)]; 165 166 status = le_remove_device_from_periodic_advertiser_list(transport, idx, AddrType, AVal, sid, 100); 167 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 168 169 status = le_clear_periodic_advertiser_list(transport, idx, 100); 170 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 171 172 status = le_read_periodic_advertiser_list_size(transport, idx, 100); 173 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 174 175 status = le_read_rf_path_compensation(transport, idx, 100); 176 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 177 178 TxPathComp, RxPathComp = 0, 0; 179 180 status = le_write_rf_path_compensation(transport, idx, TxPathComp, RxPathComp, 100); 181 success = __check_unknown_command_rsp_event(transport, idx, trace, status) and success; 182 183 return success; 184 185""" 186 HCI/CFC/BV-02-C [Reported Buffer Size] 187""" 188def hci_cfc_bv_02_c(transport, idx, trace): 189 190 status, LeMaxLen, LeMaxNum = le_read_buffer_size(transport, idx, 100); 191 trace.trace(6, "LE Read Buffer Size Command returns status: 0x%02X" % status); 192 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 193 194 if LeMaxLen == 0 and LeMaxNum == 0: 195 status, AclMaxLen, ScoMaxLen, AclMaxNum, ScoMaxNum = read_buffer_size(transport, idx, 100); 196 trace.trace(6, "Read Buffer Size Command returns status: 0x%02X" % status); 197 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 198 199 return success; 200 201""" 202 HCI/CIN/BV-01-C [Features returned by Read Local Supported Features Command] 203""" 204def hci_cin_bv_01_c(transport, idx, trace): 205 206 status, features = read_local_supported_features(transport, idx, 100); 207 trace.trace(6, "Read Local Supported Features Command returns status: 0x%02X" % status); 208 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 209 if success: 210 showFeatures(features, trace); 211 212 return success; 213 214""" 215 HCI/CIN/BV-03-C [Supported Commands returned by Read Local Supported Commands Command] 216""" 217def hci_cin_bv_03_c(transport, idx, trace): 218 219 status, commands = read_local_supported_commands(transport, idx, 100); 220 trace.trace(6, "Read Local Supported Commands Command returns status: 0x%02X" % status); 221 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 222 if success: 223 showCommands(commands, trace); 224 225 return success; 226 227""" 228 HCI/CIN/BV-04-C [Versions returned by Read Local Version Information Command] 229""" 230def hci_cin_bv_04_c(transport, idx, trace): 231 232 status, HCIVersion, HCIRevision, LMPVersion, manufacturer, LMPSubversion = read_local_version_information(transport, idx, 100); 233 trace.trace(6, "Read Local Version Information Command returns status: 0x%02X" % status); 234 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 235 if success: 236 trace.trace(6, "HCI Version: %i" % HCIVersion); 237 trace.trace(6, "HCI Revision: 0x%04X" % HCIRevision); 238 trace.trace(6, "LMP Version: %i" % LMPVersion); 239 trace.trace(6, "LMP Subversion: 0x%04X" % LMPSubversion); 240 trace.trace(6, "Manufacturer: 0x%04X" % manufacturer); 241 242 return success; 243 244""" 245 HCI/CIN/BV-06-C [Reported Filter Accept List Size] 246""" 247def hci_cin_bv_06_c(transport, idx, trace): 248 249 status = le_clear_filter_accept_list(transport, idx, 100); 250 trace.trace(6, "LE Clear Filter Accept List Command returns status: 0x%02X" % status); 251 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 252 253 status, FalSize = le_read_filter_accept_list_size(transport, idx, 100); 254 trace.trace(6, "LE Read Filter Accept List Size Command returns status: 0x%02X list size: %i" % (status, FalSize)); 255 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 256 257 for n in range(FalSize+1): 258 AddrType = 0; 259 AVal = [random.randint(0,255) for _ in range(6)]; 260 if n < FalSize: 261 lastAVal = AVal 262 status = le_add_device_to_filter_accept_list(transport, idx, AddrType, AVal, 100); 263 trace.trace(6, "LE Add Device to Filter Accept List Command returns status: 0x%02X" % status); 264 success = success and __check_command_complete_event(transport, idx, trace) and ((status == 0) if n < FalSize else (status == 7)); 265 266 status = le_remove_device_from_filter_accept_list(transport, idx, AddrType, lastAVal, 100); 267 trace.trace(6, "LE Remove Device from Filter Accept List Command returns status: 0x%02X" % status); 268 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 269 270 status = le_add_device_to_filter_accept_list(transport, idx, AddrType, lastAVal, 100); 271 trace.trace(6, "LE Add Device to Filter Accept List Command returns status: 0x%02X" % status); 272 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 273 274 return success; 275 276""" 277 HCI/CIN/BV-09-C [Feature Bits returned by Read LE Public Key Validation Feature Bit] 278""" 279def hci_cin_bv_09_c(transport, idx, trace): 280 281 status, features = le_read_local_supported_features(transport, idx, 100); 282 trace.trace(6, "LE Read Local Supported Features Command returns status: 0x%02X" % status); 283 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 284 if success: 285 showLEFeatures(features, trace); 286 287 return success; 288 289""" 290 HCI/CCO/BV-07-C [BR/EDR Commands Not Supported on LE Device] 291""" 292def hci_cco_bv_07_c(transport, idx, trace): 293 294 status = inquire(transport, idx, toArray(0x9E8B00, 3), 1, 1, 100); 295 trace.trace(6, "Inquire Command returns status: 0x%02X" % status); 296 success = status == 1; # Unknown HCI Command (0x01) 297 event = get_event(transport, idx, 100); 298 success = success and (event.isCommandStatus() or event.isCommandComplete()); 299 trace.trace(7, str(event)); 300 301 return success; 302 303""" 304 HCI/CCO/BV-09-C [Handling LE Set Data Length Command] 305 306 Note: Requires that CONFIG_BT_CTLR_DATA_LENGTH_MAX=60 is set in the prj.conf file for the ptt_app. 307""" 308def hci_cco_bv_09_c(transport, upperTester, lowerTester, trace): 309 310 ownAddress = Address( ExtendedAddressType.PUBLIC ); 311 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 312 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 313 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 314 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 315 initiatorAddress = Address( ExtendedAddressType.PUBLIC ); 316 initiator = Initiator(transport, upperTester, lowerTester, trace, initiatorAddress, Address( ExtendedAddressType.PUBLIC, 0x456789ABCDEF )); 317 success = advertiser.enable(); 318 319 connected = initiator.connect(); 320 success = success and connected; 321 322 if connected: 323 TxOctets, TxTime = 60, 592; 324 status, handle = le_set_data_length(transport, upperTester, initiator.handles[0], TxOctets, TxTime, 100); 325 trace.trace(6, "LE Set Data Length Command returns status: 0x%02X handle: 0x%04X" % (status, handle)); 326 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 327 """ 328 If parameters have changed - both upper- and lower-Tester will receive a LE Data Length Change event 329 """ 330 if has_event(transport, upperTester, 200)[0]: 331 event = get_event(transport, upperTester, 100); 332 success = success and (event.subEvent == MetaEvents.BT_HCI_EVT_LE_DATA_LEN_CHANGE); 333 trace.trace(7, str(event)); 334 335 if has_event(transport, lowerTester, 200)[0]: 336 event = get_event(transport, lowerTester, 100); 337 success = success and (event.subEvent == MetaEvents.BT_HCI_EVT_LE_DATA_LEN_CHANGE); 338 trace.trace(7, str(event)); 339 """ 340 Note: Disconnect can generate another LE Data Length Change event... 341 """ 342 success = success and initiator.disconnect(0x13); 343 344 else: 345 advertiser.disable(); 346 347 return success; 348 349""" 350 HCI/CCO/BV-10-C [Handling LE Read Suggested Default Data Length Command] 351""" 352def hci_cco_bv_10_c(transport, idx, trace): 353 354 status, maxTxOctets, maxTxTime = le_read_suggested_default_data_length(transport, idx, 100); 355 trace.trace(6, "LE Read Suggested Default Data Length Command returns status: 0x%02X" % status); 356 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 357 358 trace.trace(6, "Maximum number of transmitted payload octets: 0x%04X (%d)" % (maxTxOctets, maxTxOctets)); 359 trace.trace(6, "Maximum packet transmission time: 0x%04X (%d) microseconds" % (maxTxTime, maxTxTime)); 360 361 return success; 362 363""" 364 HCI/CCO/BV-11-C [Handling LE Write Suggested Default Data Length Command] 365""" 366def hci_cco_bv_11_c(transport, idx, trace): 367 368 maxTxOctetsIn, maxTxTimeIn = (0x001B + 0x00FB)//2, (0x0148 + 0x4290)//2; 369 status = le_write_suggested_default_data_length(transport, idx, maxTxOctetsIn, maxTxTimeIn, 100); 370 trace.trace(6, "LE Write Suggested Default Data Length Command returns status: 0x%02X" % status); 371 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 372 373 trace.trace(6, "Maximum number of transmitted payload octets: 0x%04X (%d)" % (maxTxOctetsIn, maxTxOctetsIn)); 374 trace.trace(6, "Maximum packet transmission time: 0x%04X (%d) microseconds" % (maxTxTimeIn, maxTxTimeIn)); 375 376 status, maxTxOctetsOut, maxTxTimeOut = le_read_suggested_default_data_length(transport, idx, 100); 377 trace.trace(6, "LE Read Suggested Default Data Length Command returns status: 0x%02X" % status); 378 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 379 380 trace.trace(6, "Maximum number of transmitted payload octets: 0x%04X (%d)" % (maxTxOctetsOut, maxTxOctetsOut)); 381 trace.trace(6, "Maximum packet transmission time: 0x%04X (%d) microseconds" % (maxTxTimeOut, maxTxTimeOut)); 382 383 success = success and (maxTxOctetsOut == maxTxOctetsIn) and (maxTxTimeOut == maxTxTimeIn); 384 385 return success; 386 387""" 388 HCI/CCO/BV-12-C [Handling LE Remove Device From Resolving List Command] 389""" 390def hci_cco_bv_12_c(transport, idx, trace): 391 392 peerAddress = Address(SimpleAddressType.PUBLIC, 0x123456789ABC); 393 status = le_add_device_to_resolving_list(transport, idx, peerAddress.type, peerAddress.address, lowerIRK, upperIRK, 100); 394 trace.trace(6, "LE Add Device to Resolving List Command returns status: 0x%02X" % status); 395 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 396 397 status = le_remove_device_from_resolving_list(transport, idx, peerAddress.type, peerAddress.address, 100); 398 trace.trace(6, "LE Remove Device from Resolving List Command returns status: 0x%02X" % status); 399 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 400 401 return success; 402 403""" 404 HCI/CCO/BV-13-C [Handling LE Clear Resolving List Command] 405""" 406def hci_cco_bv_13_c(transport, idx, trace): 407 408 peerAddress = Address(SimpleAddressType.PUBLIC, 0x456789ABCDEF); 409 status = le_add_device_to_resolving_list(transport, idx, peerAddress.type, peerAddress.address, lowerIRK, upperIRK, 100); 410 trace.trace(6, "LE Add Device to Resolving List Command returns status: 0x%02X" % status); 411 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 412 413 status = le_clear_resolving_list(transport, idx, 100); 414 trace.trace(6, "LE Clear Resolving List Command returns status: 0x%02X" % status); 415 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 416 417 return success; 418 419""" 420 HCI/CCO/BV-14-C [Handling LE Read Resolving List Size Command] 421""" 422def hci_cco_bv_14_c(transport, idx, trace): 423 424 status, listSize = le_read_resolving_list_size(transport, idx, 100); 425 trace.trace(6, "LE Read Resolving List Size Command returns status: 0x%02X" % status); 426 success = __check_command_complete_event(transport, idx, trace) and (status == 0) and (listSize > 0); 427 trace.trace(6, "Resolving List Size returned: %d" % listSize); 428 429 return success; 430 431""" 432 HCI/CCO/BV-15-C [Handling LE Set Default PHY Command] 433""" 434def hci_cco_bv_15_c(transport, idx, trace): 435 436 status = le_set_default_phy(transport, idx, 3, 0, 0, 100); 437 trace.trace(6, "LE Set Default PHY Command returns status: 0x%02X" % status); 438 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 439 440 return success; 441 442""" 443 HCI/CCO/BV-16-C [Handling LE Read Periodic Advertiser List Size Command] 444""" 445def hci_cco_bv_16_c(transport, idx, trace): 446 447 status, listSize = le_read_periodic_advertiser_list_size(transport, idx, 100); 448 trace.trace(6, "LE Read Periodic Advertiser List Size Command returns status: 0x%02X" % status); 449 success = __check_command_complete_event(transport, idx, trace) and (status == 0) and (listSize > 0); 450 trace.trace(6, "Periodic Advertiser List Size returned: %d" % listSize); 451 452 return success; 453 454""" 455 HCI/CCO/BV-17-C [Handling Add, Remove and Clear Periodic Advertiser List Commands] 456""" 457def hci_cco_bv_17_c(transport, idx, trace): 458 459 status = le_clear_periodic_advertiser_list(transport, idx, 100); 460 trace.trace(6, "LE Clear Periodic Advertiser List Command returns status: 0x%02X" % status); 461 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 462 463 peerAddress = Address(SimpleAddressType.PUBLIC, 0x123456789ABC); 464 status = le_add_device_to_periodic_advertiser_list(transport, idx, peerAddress.type, peerAddress.address, 1, 100); 465 trace.trace(6, "LE Add Device to Periodic Advertiser List Command returns status: 0x%02X" % status); 466 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 467 468 status = le_remove_device_from_periodic_advertiser_list(transport, idx, peerAddress.type, peerAddress.address, 1, 100); 469 trace.trace(6, "LE Remove Device from Periodic Advertiser List Command returns status: 0x%02X" % status); 470 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 471 472 status = le_remove_device_from_periodic_advertiser_list(transport, idx, peerAddress.type, peerAddress.address, 1, 100); 473 trace.trace(6, "LE Remove Device from Periodic Advertiser List Command returns status: 0x%02X" % status); 474 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0x42); 475 476 status = le_add_device_to_periodic_advertiser_list(transport, idx, peerAddress.type, peerAddress.address, 1, 100); 477 trace.trace(6, "LE Add Device to Periodic Advertiser List Command returns status: 0x%02X" % status); 478 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 479 480 status = le_clear_periodic_advertiser_list(transport, idx, 100); 481 trace.trace(6, "LE Clear Periodic Advertiser List Command returns status: 0x%02X" % status); 482 success = success and __check_command_complete_event(transport, idx, trace) and (status == 0); 483 484 return success; 485 486""" 487 HCI/CCO/BV-18-C [Handling LE Read Transmit Power Command] 488""" 489def hci_cco_bv_18_c(transport, idx, trace): 490 491 status, minTxPower, maxTxPower = le_read_transmit_power(transport, idx, 100); 492 trace.trace(6, "LE Read Transmit Power Command returns status: 0x%02X" % status); 493 success = __check_command_complete_event(transport, idx, trace) and (status == 0); 494 success = success and (-127 <= minTxPower) and (minTxPower <= 126) and (-127 <= maxTxPower) and (maxTxPower <= 126) and (minTxPower <= maxTxPower); 495 trace.trace(6, "LE Read Transmit Power Command returned range: [%d, %d] dBm." % (minTxPower, maxTxPower)); 496 497 return success; 498 499""" 500 HCI/DDI/BV-03-C [Disable Advertising with Set Advertising Enable Command] 501""" 502def hci_ddi_bv_03_c(transport, upperTester, lowerTester, trace): 503 504 ownAddress = Address( SimpleAddressType.PUBLIC ); 505 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 506 advertiser = Advertiser(transport, upperTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 507 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 508 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 509 ownAddress = Address( SimpleAddressType.PUBLIC ); 510 scanner = Scanner(transport, lowerTester, trace, ScanType.PASSIVE, AdvertisingReport.ADV_IND, ownAddress, ScanningFilterPolicy.FILTER_NONE, 5); 511 512 success = advertiser.enable(); 513 514 success = success and scanner.enable(); 515 scanner.monitor(); 516 success = success and scanner.disable(); 517 success = success and scanner.qualifyReports( 5 ); 518 519 success = success and advertiser.disable(); 520 success = success and scanner.enable(); 521 scanner.monitor(); 522 success = success and scanner.disable(); 523 success = success and not scanner.qualifyReports( 1 ); 524 525 return success; 526 527""" 528 HCI/DDI/BV-04-C [Disable Scanning with Set Scan Enable Command] 529""" 530def hci_ddi_bv_04_c(transport, upperTester, lowerTester, trace): 531 532 ownAddress = Address( SimpleAddressType.PUBLIC ); 533 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 534 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 535 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 536 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 537 ownAddress = Address( SimpleAddressType.PUBLIC ); 538 scanner = Scanner(transport, upperTester, trace, ScanType.PASSIVE, AdvertisingReport.ADV_IND, ownAddress, ScanningFilterPolicy.FILTER_NONE, 5); 539 540 success = advertiser.enable(); 541 542 success = success and scanner.enable(); 543 scanner.monitor(); 544 success = success and scanner.disable(); 545 success = success and scanner.qualifyReports( 5 ); 546 547 scanner.monitor(); 548 success = success and not scanner.qualifyReports( 1 ); 549 550 success = success and advertiser.disable(); 551 552 return success; 553 554""" 555 HCI/DDI/BI-02-C [Rejecting invalid Advertising Parameters] 556""" 557def hci_ddi_bi_02_c(transport, upperTester, trace): 558 559 ownAddress = Address( SimpleAddressType.PUBLIC ); 560 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 561 advertiser = Advertiser(transport, upperTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.NON_CONNECTABLE_UNDIRECTED, \ 562 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 563 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 564 565 advertiser.minInterval, advertiser.maxInterval = 32-2, 32-1; 566 567 successA = not advertiser.enable(); 568 success = successA and (advertiser.status == 0x12); 569 570 if not successA: 571 advertiser.disable(); 572 573 return success; 574 575""" 576 HCI/DDI/BI-63-C [Reject Set Extended Advertising Data Command, Data Too Long, LE 1M PHY] 577""" 578def hci_ddi_bi_63_c(transport, upperTester, lowerTester, trace): 579 580 Handle = 0; 581 Properties = 0; 582 PrimMinInterval = toArray(0x0140, 3); # Minimum Advertise Interval = 320 x 0.625 ms = 200.00 ms 583 PrimMaxInterval = toArray(0x0140, 3); # Maximum Advertise Interval = 320 x 0.625 ms = 200.00 ms 584 PrimChannelMap = 0x07; # Advertise on all three channels (#37, #38 and #39) 585 OwnAddrType = SimpleAddressType.PUBLIC; 586 PeerAddrType = 0; 587 PeerAddress = toArray(0, 6); 588 FilterPolicy = AdvertisingFilterPolicy.FILTER_NONE; 589 TxPower = 0; 590 PrimAdvPhy = PhysicalChannel.LE_1M; # Primary advertisement PHY is LE 1M 591 SecAdvMaxSkip = 0; # AUX_ADV_IND shall be sent prior to the next advertising event 592 SecAdvPhy = PhysicalChannel.LE_1M; 593 Sid = 0; 594 ScanReqNotifyEnable = 0; # Scan request notifications disabled 595 596 success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval, \ 597 PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower, \ 598 PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace); 599 600 if not success: 601 return False; 602 603 # Get maximum advertising data size 604 status, maxADSize = le_read_maximum_advertising_data_length(transport, upperTester, 100); 605 if status != 0: 606 return False 607 608 FragPref = 0; # The Controller may fragment all Host advertising data 609 610 # Set fragments of advertising data until we hit maxADSize - 1 611 fragmentCount = 7; 612 fragmentSize = math.ceil((maxADSize-1)/(fragmentCount)); 613 fragmentData = random.randint(0, 256, fragmentSize); 614 615 count = 0; 616 while (count < fragmentCount): 617 618 op = FragmentOperation.FIRST_FRAGMENT 619 if (count > 0): 620 op = FragmentOperation.INTERMEDIATE_FRAGMENT; 621 if count == fragmentCount - 1: 622 # Adjust size of last fragment to hit maxADSize - 1 exactly 623 fragmentData = fragmentData[:(maxADSize - 1 - fragmentSize*6)] 624 625 status = le_set_extended_advertising_data(transport, upperTester, Handle, op, FragPref, fragmentData, 100); 626 if status != 0: 627 return False; 628 629 count += 1; 630 631 # Now setting another fragment of two bytes should fail 632 status = le_set_extended_advertising_data(transport, upperTester, Handle, FragmentOperation.INTERMEDIATE_FRAGMENT, FragPref, random.randint(0, 256, 2), 100); 633 return status == 0x07; # Memory Capacity Exceeded expected 634 635""" 636 HCI/DDI/BI-65-C [Reject Set Extended Scan Response Data Command, Data Too Long, LE 1M PHY] 637""" 638def hci_ddi_bi_65_c(transport, upperTester, lowerTester, trace): 639 640 Handle = 0; 641 Properties = 0x02; # Scannable 642 PrimMinInterval = toArray(0x0140, 3); # Minimum Advertise Interval = 320 x 0.625 ms = 200.00 ms 643 PrimMaxInterval = toArray(0x0140, 3); # Maximum Advertise Interval = 320 x 0.625 ms = 200.00 ms 644 PrimChannelMap = 0x07; # Advertise on all three channels (#37, #38 and #39) 645 OwnAddrType = SimpleAddressType.PUBLIC; 646 PeerAddrType = 0; 647 PeerAddress = toArray(0, 6); 648 FilterPolicy = AdvertisingFilterPolicy.FILTER_NONE; 649 TxPower = 0; 650 PrimAdvPhy = PhysicalChannel.LE_1M; # Primary advertisement PHY is LE 1M 651 SecAdvMaxSkip = 0; # AUX_ADV_IND shall be sent prior to the next advertising event 652 SecAdvPhy = PhysicalChannel.LE_1M; 653 Sid = 0; 654 ScanReqNotifyEnable = 0; # Scan request notifications disabled 655 656 success = preamble_ext_advertising_parameters_set(transport, upperTester, Handle, Properties, PrimMinInterval, PrimMaxInterval, \ 657 PrimChannelMap, OwnAddrType, PeerAddrType, PeerAddress, FilterPolicy, TxPower, \ 658 PrimAdvPhy, SecAdvMaxSkip, SecAdvPhy, Sid, ScanReqNotifyEnable, trace); 659 660 if not success: 661 return False; 662 663 # Get maximum advertising data size 664 status, maxADSize = le_read_maximum_advertising_data_length(transport, upperTester, 100); 665 if status != 0: 666 return False; 667 668 FragPref = 0; # The Controller may fragment all Host advertising data 669 670 # Set fragments of advertising data until we hit maxADSize - 1 671 fragmentCount = 7; 672 fragmentSize = math.ceil((maxADSize-1)/(fragmentCount)); 673 fragmentData = random.randint(0, 256, fragmentSize); 674 675 count = 0; 676 while (count < fragmentCount): 677 678 op = FragmentOperation.FIRST_FRAGMENT 679 if (count > 0): 680 op = FragmentOperation.INTERMEDIATE_FRAGMENT; 681 if count == fragmentCount - 1: 682 # Adjust size of last fragment to hit maxADSize - 1 exactly 683 fragmentData = fragmentData[:(maxADSize - 1 - fragmentSize*6)] 684 685 status = le_set_extended_scan_response_data(transport, upperTester, Handle, op, FragPref, fragmentData, 100); 686 if status != 0: 687 return False; 688 689 count += 1; 690 691 # Now setting another fragment of two bytes should fail 692 status = le_set_extended_scan_response_data(transport, upperTester, Handle, FragmentOperation.INTERMEDIATE_FRAGMENT, FragPref, random.randint(0, 256, 2), 100); 693 return status == 0x07; # Memory Capacity Exceeded expected 694 695""" 696 HCI/HFC/BV-04-C [Events enabled by LE Set Event Mask Command] 697""" 698def hci_hfc_bv_04_c(transport, upperTester, lowerTester, trace): 699 700 """ Bit: 5 4 4 3 2 1 0 0 701 6 8 0 2 4 6 8 0 702 0x20 00 00 00 00 00 80 10 ~ Bits 4, 15, 61 (Disconnection Complete Event, Hardware Error Event, LE Meta Event) 703 """ 704 events = [0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20]; 705 706 status = set_event_mask(transport, upperTester, events, 100); 707 trace.trace(6, "Set Event Mask Command returns status: 0x%02X" % status); 708 success = __check_command_complete_event(transport, upperTester, trace) and (status == 0); 709 710 """ Bit: 5 4 4 3 2 1 0 0 711 6 8 0 2 4 6 8 0 712 0x00 00 00 00 00 07 FF FD ~ All except 'LE Channel Selection Algorithm Event and LE Advertising Report Event' 713 """ 714 events = [0xFD, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00]; 715 716 status = le_set_event_mask(transport, upperTester, events, 100); 717 trace.trace(6, "LE Set Event Mask Command returns status: 0x%02X" % status); 718 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 719 720 """ 721 status = le_set_event_mask(transport, lowerTester, events, 100); 722 trace.trace(6, "LE Set Event Mask Command returns status: 0x%02X" % status); 723 success = success and __check_command_complete_event(transport, lowerTester, trace) and (status == 0); 724 """ 725 726 ownAddress = Address( SimpleAddressType.PUBLIC ); 727 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 728 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 729 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 730 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 731 ownAddress = Address( SimpleAddressType.PUBLIC ); 732 scanner = Scanner(transport, upperTester, trace, ScanType.ACTIVE, AdvertisingReport.ADV_IND, ownAddress, ScanningFilterPolicy.FILTER_NONE, 5, 5); 733 initiatorAddress = Address( ExtendedAddressType.PUBLIC ); 734 initiator = Initiator(transport, upperTester, lowerTester, trace, initiatorAddress, Address( ExtendedAddressType.PUBLIC, 0x456789ABCDEF )); 735 736 success = advertiser.enable(); 737 738 success = success and scanner.enable(); 739 scanner.monitor(); 740 success = success and scanner.disable(); 741 success = success and not scanner.qualifyResponses( 5 ); 742 success = success and not scanner.qualifyReports( 5 ); 743 744 transport.wait(100); 745 746 connected = initiator.connect(); 747 success = success and connected; 748 749 transport.wait(500); 750 751 if connected: 752 success = success and initiator.disconnect(0x13); 753 754 return success; 755 756""" 757 HCI/CM/BV-01-C [Handling LE Read Peer Resolvable Address Command] 758""" 759def hci_cm_bv_01_c(transport, upperTester, lowerTester, trace): 760 761 """ 762 Add Public address of lowerTester and upperTester to the Resolving List 763 """ 764 RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ]; 765 ownAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 766 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 767 success = RPAs[upperTester].clear() and RPAs[lowerTester].clear(); 768 success = success and RPAs[upperTester].add( peerAddress, lowerIRK ); 769 success = success and RPAs[lowerTester].add( ownAddress, upperIRK ); 770 771 """ 772 Set resolvable private address timeout in seconds ( sixty seconds ) 773 """ 774 success = success and RPAs[upperTester].timeout(60) and RPAs[lowerTester].timeout(60); 775 success = success and RPAs[upperTester].enable() and RPAs[lowerTester].enable(); 776 777 for iutRole in [ Role.CENTRAL, Role.PERIPHERAL ]: 778 ownAddress = Address( ExtendedAddressType.RESOLVABLE_OR_PUBLIC, 0x456789ABCDEF if iutRole is Role.CENTRAL else 0x123456789ABC); 779 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC if iutRole is Role.CENTRAL else 0x456789ABCDEF); 780 if iutRole == Role.CENTRAL: 781 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_LDC_DIRECTED, ownAddress, peerAddress); 782 else: 783 advertiser = Advertiser(transport, upperTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_LDC_DIRECTED, ownAddress, peerAddress); 784 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 785 786 initiatorAddress = Address( ExtendedAddressType.RESOLVABLE_OR_PUBLIC ); 787 if iutRole == Role.CENTRAL: 788 initiator = Initiator(transport, upperTester, lowerTester, trace, initiatorAddress, Address( IdentityAddressType.PUBLIC_IDENTITY, toNumber(ownAddress.address) )); 789 else: 790 initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, Address( IdentityAddressType.PUBLIC_IDENTITY, toNumber(ownAddress.address) )); 791 success = success and advertiser.enable(); 792 793 connected = initiator.connect(); 794 success = success and connected; 795 796 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 797 status, RPA = le_read_peer_resolvable_address(transport, upperTester, peerAddress.type, peerAddress.address, 100); 798 trace.trace(6, "LE Read Peer Resolvable Address Command returns status: 0x%02X RPA: %s" % (status, formatAddress(RPA))); 799 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 800 801 if iutRole == Role.CENTRAL: 802 success = success and (initiator.peerRPA() == RPA); 803 if initiator.peerRPA() != RPA: 804 print((initiator.peerRPA())); 805 print(RPA); 806 trace.trace(5, "Expected: %s Received: %s" % (Address(None, initiator.peerRPA()), Address(None, RPA))); 807 else: 808 success = success and (initiator.localRPA() == RPA); 809 if initiator.localRPA() != RPA: 810 trace.trace(5, "Expected: %s Received: %s" % (Address(None, initiator.localRPA()), Address(None, RPA))); 811 812 transport.wait(200); 813 814 if connected: 815 connected = not initiator.disconnect(0x13); 816 success = success and not connected; 817 818 return success; 819 820""" 821 HCI/CM/BV-02-C [Handling LE Read Local Resolvable Address Command] 822""" 823def hci_cm_bv_02_c(transport, upperTester, lowerTester, trace): 824 825 """ 826 Add Public address of lowerTester and upperTester to the Resolving List 827 """ 828 RPAs = [ ResolvableAddresses( transport, upperTester, trace, upperIRK ), ResolvableAddresses( transport, lowerTester, trace, lowerIRK ) ]; 829 ownAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 830 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 831 success = RPAs[upperTester].clear() and RPAs[lowerTester].clear(); 832 success = success and RPAs[upperTester].add( peerAddress, lowerIRK ); 833 success = success and RPAs[lowerTester].add( ownAddress, upperIRK ); 834 835 """ 836 Set resolvable private address timeout in seconds ( sixty seconds ) 837 """ 838 success = success and RPAs[upperTester].timeout(60) and RPAs[lowerTester].timeout(60); 839 success = success and RPAs[upperTester].enable() and RPAs[lowerTester].enable(); 840 841 for iutRole in [ Role.CENTRAL, Role.PERIPHERAL ]: 842 ownAddress = Address( ExtendedAddressType.RESOLVABLE_OR_PUBLIC, 0x456789ABCDEF if iutRole is Role.CENTRAL else 0x123456789ABC); 843 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC if iutRole is Role.CENTRAL else 0x456789ABCDEF); 844 if iutRole == Role.CENTRAL: 845 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_LDC_DIRECTED, ownAddress, peerAddress); 846 else: 847 advertiser = Advertiser(transport, upperTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_LDC_DIRECTED, ownAddress, peerAddress); 848 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 849 850 initiatorAddress = Address( ExtendedAddressType.RESOLVABLE_OR_PUBLIC ); 851 if iutRole == Role.CENTRAL: 852 initiator = Initiator(transport, upperTester, lowerTester, trace, initiatorAddress, Address( IdentityAddressType.PUBLIC_IDENTITY, toNumber(ownAddress.address) )); 853 else: 854 initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, Address( IdentityAddressType.PUBLIC_IDENTITY, toNumber(ownAddress.address) )); 855 success = success and advertiser.enable(); 856 857 connected = initiator.connect(); 858 success = success and connected; 859 860 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 861 status, RPA = le_read_local_resolvable_address(transport, upperTester, peerAddress.type, peerAddress.address, 100); 862 trace.trace(6, "LE Read Local Resolvable Address Command returns status: 0x%02X RPA: %s" % (status, formatAddress(RPA))); 863 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 864 865 if iutRole == Role.CENTRAL: 866 success = success and (initiator.localRPA() == RPA); 867 else: 868 success = success and (initiator.peerRPA() == RPA); 869 870 transport.wait(200); 871 872 if connected: 873 connected = not initiator.disconnect(0x13); 874 success = success and not connected; 875 876 return success; 877 878""" 879 HCI/CM/BV-03-C [Handling LE Read PHY Command] 880""" 881def hci_cm_bv_03_c(transport, upperTester, lowerTester, trace): 882 883 ownAddress = Address( ExtendedAddressType.PUBLIC ); 884 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 885 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 886 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 887 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 888 initiatorAddress = Address( ExtendedAddressType.PUBLIC ); 889 initiator = Initiator(transport, upperTester, lowerTester, trace, initiatorAddress, Address( ExtendedAddressType.PUBLIC, 0x456789ABCDEF )); 890 success = advertiser.enable(); 891 892 connected = initiator.connect(); 893 success = success and connected; 894 895 if success: 896 status, handle, TxPhy, RxPhy = le_read_phy(transport, upperTester, initiator.handles[0], 100); 897 trace.trace(6, "LE Read PHY Command returns status: 0x%02X handle: 0x%04X TxPHY: %d RxPHY: %d" % (status, handle, TxPhy, RxPhy)); 898 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 899 900 if connected: 901 connected = not initiator.disconnect(0x13); 902 success = success and not connected; 903 904 return success; 905 906""" 907 HCI/DSU/BV-02-C [Reset Command received in Advertising State] 908""" 909def hci_dsu_bv_02_c(transport, upperTester, lowerTester, trace): 910 911 ownAddress = Address( SimpleAddressType.PUBLIC ); 912 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 913 advertiser = Advertiser(transport, upperTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 914 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 915 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 916 ownAddress = Address( SimpleAddressType.PUBLIC ); 917 scanner = Scanner(transport, lowerTester, trace, ScanType.PASSIVE, AdvertisingReport.ADV_IND, ownAddress, ScanningFilterPolicy.FILTER_NONE, 5); 918 919 success = advertiser.enable(); 920 921 success = success and scanner.enable(); 922 scanner.monitor(); 923 success = success and scanner.disable(); 924 success = success and scanner.qualifyReports( 5 ); 925 926 status = reset(transport, upperTester, 100); 927 trace.trace(6, "Reset Command returns status: 0x%02X" % status); 928 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 929 930 """ 931 Verify that the IUT has stopped Advertising 932 """ 933 success = success and scanner.enable(); 934 scanner.monitor(); 935 success = success and scanner.disable(); 936 success = success and not scanner.qualifyReports( 5 ); 937 938 return success; 939 940""" 941 HCI/DSU/BV-03-C [Reset Command received in Peripheral Role] 942""" 943def hci_dsu_bv_03_c(transport, upperTester, lowerTester, trace): 944 945 ownAddress = Address( ExtendedAddressType.PUBLIC ); 946 peerAddress = Address( SimpleAddressType.PUBLIC, 0x456789ABCDEF ); 947 advertiser = Advertiser(transport, upperTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 948 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 949 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 950 initiatorAddress = Address( ExtendedAddressType.PUBLIC ); 951 initiator = Initiator(transport, lowerTester, upperTester, trace, initiatorAddress, Address( ExtendedAddressType.PUBLIC, 0x123456789ABC )); 952 success = advertiser.enable(); 953 954 success = success and initiator.connect(); 955 956 transport.wait(200); 957 958 status = reset(transport, upperTester, 100); 959 trace.trace(6, "Reset Command returns status: 0x%02X" % status); 960 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 961 962 """ 963 There might be pending disconnect events lying around... 964 """ 965 while has_event(transport, lowerTester, 200)[0]: 966 event = get_event(transport, lowerTester, 100); 967 trace.trace(7, str(event)); 968 if event.event == Events.BT_HCI_EVT_DISCONN_COMPLETE: 969 status, handle, reason = event.decode(); 970 success = success and (reason == 0x08); # Connection Timeout 971 972 while has_event(transport, upperTester, 200)[0]: 973 event = get_event(transport, upperTester, 100); 974 trace.trace(7, str(event)); 975 if event.event == Events.BT_HCI_EVT_DISCONN_COMPLETE: 976 status, handle, reason = event.decode(); 977 success = success and (reason == 0x08); # Connection Timeout 978 979 return success; 980 981""" 982 HCI/DSU/BV-04-C [Reset Command received in Scanning State] 983""" 984def hci_dsu_bv_04_c(transport, upperTester, lowerTester, trace): 985 986 ownAddress = Address( SimpleAddressType.PUBLIC ); 987 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 988 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 989 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 990 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 991 ownAddress = Address( SimpleAddressType.PUBLIC ); 992 scanner = Scanner(transport, upperTester, trace, ScanType.PASSIVE, AdvertisingReport.ADV_IND, ownAddress, ScanningFilterPolicy.FILTER_NONE, 5); 993 994 success = advertiser.enable(); 995 996 success = success and scanner.enable(); 997 scanner.monitor(); 998 success = success and scanner.disable(); 999 success = success and scanner.qualifyReports( 5 ); 1000 1001 status = reset(transport, upperTester, 100); 1002 trace.trace(6, "Reset Command returns status: 0x%02X" % status); 1003 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 1004 1005 """ 1006 Verify that the IUT has stopped Advertising 1007 """ 1008 success = success and scanner.enable(); 1009 scanner.monitor(); 1010 success = success and scanner.disable(); 1011 success = success and not scanner.qualifyReports( 5 ); 1012 1013 return success; 1014 1015""" 1016 HCI/DSU/BV-05-C [Reset Command received in Initiating State] 1017""" 1018def hci_dsu_bv_05_c(transport, upperTester, lowerTester, trace): 1019 1020 ownAddress = Address( ExtendedAddressType.PUBLIC ); 1021 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 1022 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 1023 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 1024 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 1025 initiatorAddress = Address( ExtendedAddressType.PUBLIC ); 1026 initiator = Initiator(transport, upperTester, lowerTester, trace, initiatorAddress, Address( ExtendedAddressType.PUBLIC, 0x456789ABCDEF )); 1027 1028 success = initiator.preConnect(); 1029 1030 status = reset(transport, upperTester, 100); 1031 trace.trace(6, "Reset Command returns status: 0x%02X" % status); 1032 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 1033 1034 success = success and advertiser.enable(); 1035 success = success and not initiator.postConnect(); 1036 success = success and advertiser.disable(); 1037 1038 return success; 1039 1040""" 1041 HCI/DSU/BV-06-C [Reset Command received in Central Role] 1042""" 1043def hci_dsu_bv_06_c(transport, upperTester, lowerTester, trace): 1044 1045 ownAddress = Address( ExtendedAddressType.PUBLIC ); 1046 peerAddress = Address( SimpleAddressType.PUBLIC, 0x123456789ABC ); 1047 advertiser = Advertiser(transport, lowerTester, trace, AdvertiseChannel.ALL_CHANNELS, Advertising.CONNECTABLE_UNDIRECTED, \ 1048 ownAddress, peerAddress, AdvertisingFilterPolicy.FILTER_NONE); 1049 advertiser.responseData = [ 0x04, 0x09 ] + [ ord(char) for char in "IUT" ]; 1050 initiatorAddress = Address( ExtendedAddressType.PUBLIC ); 1051 initiator = Initiator(transport, upperTester, lowerTester, trace, initiatorAddress, Address( ExtendedAddressType.PUBLIC, 0x456789ABCDEF )); 1052 success = advertiser.enable(); 1053 1054 success = success and initiator.connect(); 1055 1056 transport.wait(200); 1057 1058 status = reset(transport, upperTester, 100); 1059 trace.trace(6, "Reset Command returns status: 0x%02X" % status); 1060 success = success and __check_command_complete_event(transport, upperTester, trace) and (status == 0); 1061 1062 return success; 1063 1064__tests__ = { 1065 "HCI/CCO/BV-07-C": [ hci_cco_bv_07_c, 'BR/EDR Commands Not Supported on LE Device' ], 1066 "HCI/CCO/BV-09-C": [ hci_cco_bv_09_c, 'Handling LE Set Data Length Command' ], 1067 "HCI/CCO/BV-10-C": [ hci_cco_bv_10_c, 'Handling LE Read Suggested Default Data Length Command' ], 1068 "HCI/CCO/BV-11-C": [ hci_cco_bv_11_c, 'Handling LE Write Suggested Default Data Length Command' ], 1069 "HCI/CCO/BV-12-C": [ hci_cco_bv_12_c, 'Handling LE Remove Device From Resolving List Command' ], 1070 "HCI/CCO/BV-13-C": [ hci_cco_bv_13_c, 'Handling LE Clear Resolving List Command' ], 1071 "HCI/CCO/BV-14-C": [ hci_cco_bv_14_c, 'Handling LE Read Resolving List Size Command' ], 1072 "HCI/CCO/BV-15-C": [ hci_cco_bv_15_c, 'Handling LE Set Default PHY Command' ], 1073# "HCI/CCO/BV-16-C": [ hci_cco_bv_17_c, 'Handling LE Read Periodic Advertiser List Size Command' ], 1074# "HCI/CCO/BV-17-C": [ hci_cco_bv_17_c, 'Handling Add, Remove and Clear Periodic Advertiser List Commands' ], 1075 "HCI/CCO/BV-18-C": [ hci_cco_bv_18_c, 'Handling LE Read Transmit Power Command' ], 1076 "HCI/CFC/BV-02-C": [ hci_cfc_bv_02_c, 'Reported Buffer Size' ], 1077 "HCI/CIN/BV-01-C": [ hci_cin_bv_01_c, 'Features returned by Read Local Supported Features Command' ], 1078 "HCI/CIN/BV-03-C": [ hci_cin_bv_03_c, 'Supported Commands returned by Read Local Supported Commands Command' ], 1079 "HCI/CIN/BV-04-C": [ hci_cin_bv_04_c, 'Versions returned by Read Local Version Information Command' ], 1080 "HCI/CIN/BV-06-C": [ hci_cin_bv_06_c, 'Reported Filter Accept List Size' ], 1081 "HCI/CIN/BV-09-C": [ hci_cin_bv_09_c, 'Feature Bits returned by Read LE Public Key Validation Feature Bit' ], 1082 "HCI/CM/BV-01-C": [ hci_cm_bv_01_c, 'Handling LE Read Peer Resolvable Address Command' ], 1083 "HCI/CM/BV-02-C": [ hci_cm_bv_02_c, 'Handling LE Read Local Resolvable Address Command' ], 1084 "HCI/CM/BV-03-C": [ hci_cm_bv_03_c, 'Handling LE Read PHY Command' ], 1085 "HCI/DDI/BI-02-C": [ hci_ddi_bi_02_c, 'Rejecting invalid Advertising Parameters' ], 1086 "HCI/DDI/BI-63-C": [ hci_ddi_bi_63_c, 'Reject Set Extended Advertising Data Command, Data Too Long, LE 1M PHY' ], 1087 "HCI/DDI/BI-65-C": [ hci_ddi_bi_65_c, 'Reject Set Extended Scan Response Data Command, Data Too Long, LE 1M PHY' ], 1088 "HCI/DDI/BV-03-C": [ hci_ddi_bv_03_c, 'Disable Advertising with Set Advertising Enable Command' ], 1089 "HCI/DDI/BV-04-C": [ hci_ddi_bv_04_c, 'Disable Scanning with Set Scan Enable Command' ], 1090 "HCI/DSU/BV-02-C": [ hci_dsu_bv_02_c, 'Reset Command received in Advertising State' ], 1091 "HCI/DSU/BV-03-C": [ hci_dsu_bv_03_c, 'Reset Command received in Peripheral Role' ], 1092 "HCI/DSU/BV-04-C": [ hci_dsu_bv_04_c, 'Reset Command received in Scanning State' ], 1093 "HCI/DSU/BV-05-C": [ hci_dsu_bv_05_c, 'Reset Command received in Initiating State' ], 1094 "HCI/DSU/BV-06-C": [ hci_dsu_bv_06_c, 'Reset Command received in Central Role' ], 1095 "HCI/GEV/BV-01-C": [ hci_gev_bv_01_c, 'Status return for Unsupported Commands' ], 1096 "HCI/HFC/BV-04-C": [ hci_hfc_bv_04_c, 'Events enabled by LE Set Event Mask Command' ] 1097}; 1098 1099_maxNameLength = max([ len(key) for key in __tests__ ]); 1100 1101_spec = { key: TestSpec(name = key, number_devices = 2, description = "#[" + __tests__[key][1] + "]", test_private = __tests__[key][0]) for key in __tests__ }; 1102 1103""" 1104 Return the test spec which contains info about all the tests 1105 this test module provides 1106""" 1107def get_tests_specs(): 1108 return _spec; 1109 1110def preamble(transport, trace): 1111 global lowerIRK, upperIRK, lowerRandomAddress, upperRandomAddress; 1112 1113 ok = success = preamble_standby(transport, 0, trace); 1114 trace.trace(4, "preamble Standby " + ("PASS" if success else "FAIL")); 1115 success = preamble_standby(transport, 1, trace); 1116 ok = ok and success; 1117 trace.trace(4, "preamble Standby " + ("PASS" if success else "FAIL")); 1118 success, upperIRK, upperRandomAddress = preamble_device_address_set(transport, 0, trace); 1119 trace.trace(4, "preamble Device Address Set " + ("PASS" if success else "FAIL")); 1120 ok = ok and success; 1121 success, lowerIRK, lowerRandomAddress = preamble_device_address_set(transport, 1, trace); 1122 trace.trace(4, "preamble Device Address Set " + ("PASS" if success else "FAIL")); 1123 return ok and success; 1124 1125""" 1126 Run a test given its test_spec 1127""" 1128def run_a_test(args, transport, trace, test_spec, device_dumps): 1129 try: 1130 success = preamble(transport, trace); 1131 except Exception as e: 1132 trace.trace(3, "Preamble generated exception: %s" % str(e)); 1133 success = False; 1134 1135 trace.trace(2, "%-*s %s test started..." % (_maxNameLength, test_spec.name, test_spec.description[1:])); 1136 test_f = test_spec.test_private; 1137 try: 1138 if test_f.__code__.co_argcount > 4: 1139 success = success and test_f(transport, 0, 1, trace, device_dumps); 1140 elif test_f.__code__.co_argcount > 3: 1141 success = success and test_f(transport, 0, 1, trace); 1142 else: 1143 success = success and test_f(transport, 0, trace); 1144 except Exception as e: 1145 import traceback 1146 traceback.print_exc() 1147 trace.trace(3, "Test generated exception: %s" % str(e)); 1148 success = False; 1149 1150 return not success 1151