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