1# -*- coding: utf-8 -*- 2# Copyright 2019 Oticon A/S 3# SPDX-License-Identifier: Apache-2.0 4 5from numpy import random; 6import statistics; 7import os; 8import numpy; 9from enum import IntEnum; 10from components.utils import *; 11from components.basic_commands import *; 12from components.address import *; 13from components.events import *; 14from components.resolvable import *; 15from components.advertiser import *; 16from components.scanner import *; 17from components.initiator import *; 18from components.preambles import *; 19from components.addata import *; 20from components.attdata import *; 21from components.smpdata import *; 22from components.pairing import *; 23from components.gattdata import *; 24from components.test_spec import TestSpec; 25 26global lowerIRK, upperIRK, lowerRandomAddress, upperRandomAddress; 27 28""" 29 Send an ATT Profile request... 30""" 31def attRequest(transport, initiator, txData, trace): 32 status = le_data_write(transport, initiator.initiator, initiator.handles[0], 0, 0, txData, 100); 33 trace.trace(10, "LE Data Write Command returns status: 0x%02X" % status); 34 success = status == 0; 35 dataSent = False; 36 37 while success and not dataSent: 38 dataSent = has_event(transport, initiator.initiator, 200)[0]; 39 success = success and dataSent; 40 if dataSent: 41 event = get_event(transport, initiator.initiator, 100); 42 trace.trace(7, str(event)); 43 dataSent = event.event == Events.BT_HCI_EVT_NUM_COMPLETED_PACKETS; 44 45 return dataSent; 46 47""" 48 Receive an ATT Profile response... 49""" 50def attResponse(transport, initiator, trace, timeout=100): 51 success, rxData, cid = True, [], None; 52 53 while success: 54 dataReady = le_data_ready(transport, initiator.initiator, timeout); 55 timeout = 99; 56 success = success and dataReady; 57 if dataReady: 58 rxPBFlags, rxBCFlags, rxDataPart = le_data_read(transport, initiator.initiator, 100)[2:]; 59 trace.trace(10, "LE Data Read Command returns PB=%d BC=%d - %2d data bytes: %s" % \ 60 (rxPBFlags, rxBCFlags, len(rxDataPart), formatArray(rxDataPart))); 61 if rxPBFlags & 0x2: 62 cid = struct.unpack("<H", bytes(rxDataPart[2:4]))[0] 63 if cid != 4: 64 trace.trace(6, "Dropping data for non-ATT CID: %d" % cid); 65 continue 66 rxData += rxDataPart; 67 68 return (len(rxData) > 0), rxData; 69 70""" 71 Exchange MTU sizes... 72""" 73def exchangeMTU(transport, initiator, mtuSize, trace): 74 attData = ATTData(); 75 76 mtuReply = 0; 77 txData = attData.encode( ATTOpcode.ATT_EXCH_MTU_REQUEST, mtuSize ); 78 trace.trace(7, str(attData)); 79 success = attRequest( transport, initiator, txData, trace ); 80 if success: 81 success, rxData = attResponse( transport, initiator, trace ); 82 if success: 83 reply = attData.decode( rxData ); 84 trace.trace(7, str(attData)); 85 success = reply['opcode'] == ATTOpcode.ATT_EXCH_MTU_RESPONSE; 86 if success: 87 mtuReply = reply['mtu']; 88 89 return success, min(mtuSize, mtuReply); 90 91def __nextByType(transport, initiator, uuid, firstHandle, lastHandle, trace): 92 reply = { 'opcode': ATTOpcode.ATT_ERROR_RESPONSE, 'error': ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND }; 93 attData = ATTData(); 94 95 txData = attData.encode( ATTOpcode.ATT_READ_BY_TYPE_REQUEST, firstHandle, lastHandle, uuid ); 96 trace.trace(7, str(attData)); 97 success = attRequest( transport, initiator, txData, trace ); 98 if success: 99 success, rxData = attResponse( transport, initiator, trace ); 100 if success: 101 reply = attData.decode( rxData ); 102 trace.trace(7, str(attData)); 103 success = reply['opcode'] == ATTOpcode.ATT_READ_BY_TYPE_RESPONSE; 104 105 return success, reply 106 107def __nextFindInformation(transport, initiator, firstHandle, lastHandle, trace): 108 reply = { 'opcode': ATTOpcode.ATT_ERROR_RESPONSE, 'error': ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND }; 109 attData = ATTData(); 110 111 txData = attData.encode( ATTOpcode.ATT_FIND_INFORMATION_REQUEST, firstHandle, lastHandle ); 112 trace.trace(7, str(attData)); 113 success = attRequest( transport, initiator, txData, trace ); 114 if success: 115 success, rxData = attResponse( transport, initiator, trace ); 116 if success: 117 reply = attData.decode( rxData ); 118 trace.trace(7, str(attData)); 119 success = reply['opcode'] == ATTOpcode.ATT_FIND_INFORMATION_RESPONSE; 120 121 return success, reply 122 123""" 124 Discover Primary Services by using ATT_Find_By_Type_Value_Requests 125""" 126def discoverPrimaryService(transport, initiator, serviceUUID, trace): 127 services = { 'handles': [], 'uuids': [] }; 128 attData = ATTData(); 129 130 success, handle = True, 1; 131 while success: 132 txData = attData.encode( ATTOpcode.ATT_FIND_BY_TYPE_VALUE_REQUEST, handle, 0xffff, 0x2800, toArray( serviceUUID, \ 133 2 if serviceUUID <= 0xFFFF else 16 ) ); 134 success = attRequest( transport, initiator, txData, trace ); 135 if not success: 136 break; 137 success, rxData = attResponse( transport, initiator, trace ); 138 if not success: 139 break; 140 141 reply = attData.decode( rxData ); 142 success = reply['opcode'] == ATTOpcode.ATT_FIND_BY_TYPE_VALUE_RESPONSE; 143 if not success: 144 success = (reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE) and \ 145 (reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND) and (len(services['handles']) > 0); 146 break; 147 148 for first, last in zip(reply['handle'][0::2], reply['handle'][1::2]): 149 services['handles'] += [ [ first, last ] ]; 150 services['uuids'] += [ serviceUUID ]; 151 152 handle = reply['handle'][-1] + 1; 153 if handle > 0xFFFF: 154 break; 155 156 return success, services; 157 158""" 159 Discover Services by using ATT_Read_By_Group_Type_Requests 160""" 161def __discoverServices(transport, initiator, first, last, uuid, trace): 162 services = { 'handles': [], 'uuids': [] }; 163 attData = ATTData(); 164 165 success, handle = True, first; 166 while success: 167 txData = attData.encode( ATTOpcode.ATT_READ_BY_GROUP_TYPE_REQUEST, handle, last, uuid ); 168 trace.trace(7, str(attData)); 169 success = attRequest( transport, initiator, txData, trace ); 170 if not success: 171 break; 172 success, rxData = attResponse( transport, initiator, trace ); 173 if not success: 174 break; 175 176 reply = attData.decode( rxData ); 177 trace.trace(7, str(attData)); 178 success = reply['opcode'] == ATTOpcode.ATT_READ_BY_GROUP_TYPE_RESPONSE; 179 if not success: 180 success = (reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE) and \ 181 (reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND) and (len(services['handles']) > 0); 182 break; 183 184 for _first, _last, _uuid in zip(reply['first_handle'], reply['last_handle'], reply['value']): 185 services['handles'] += [ [ _first, _last ] ]; 186 services['uuids'] += [ toNumber(_uuid) ]; 187 188 handle = reply['last_handle'][-1] + 1; 189 if handle > last: 190 break; 191 192 return success, services; 193 194""" 195 Discover Primary Services by using ATT_Read_By_Group_Type_Requests 196""" 197def discoverPrimaryServices(transport, initiator, trace): 198 return __discoverServices(transport, initiator, 0x0001, 0xffff, 0x2800, trace); 199 200""" 201 Discover Secondary Services by using ATT_Read_By_Group_Type_Requests 202""" 203def discoverSecondaryServices(transport, initiator, trace): 204 return __discoverServices(transport, initiator, 0x0001, 0xffff, 0x2801, trace); 205 206""" 207 Discover Secondary Services by using ATT_Read_By_Type_Requests 208""" 209def secondaryServicesByType(transport, initiator, trace): 210 services = { 'handle': [], 'uuid': [] }; 211 uuid, attData = 0x2801, ATTData(); 212 213 success, handle = True, 1; 214 while success: 215 success, reply = __nextByType(transport, initiator, uuid, handle, 0xffff, trace); 216 if not success: 217 success = (reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE) and \ 218 (reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND) and (len(services['handle']) > 0); 219 break; 220 221 for _handle, _value in zip(reply['handle'], reply['value']): 222 services['handle'] += [ _handle ]; 223 if len(_value) > 0: 224 services['uuid'] += [ toNumber(_value) ]; 225 else: 226 """ 227 NOTE: Test Specification suggest to issue a ATT_READ_REQUEST to get the 128-bit UUID, 228 but the ATT_READ_RESPONSE will only contain the handle range. 229 """ 230 success, _service = __discoverServices(transport, initiator, _handle, _handle, uuid, trace); 231 if success: 232 services['uuid'] += _service['uuids']; 233 234 handle = reply['handle'][-1] + 1; 235 if handle > 0xFFFF: 236 break; 237 238 return success, services; 239 240""" 241 Discover Included Services by using ATT_Read_By_Type_Requests 242""" 243def includedServicesByType(transport, initiator, trace): 244 services = { 'handles': [], 'uuids': [] }; 245 uuid, attData = 0x2802, ATTData(); 246 247 success, handle = True, 1; 248 while success: 249 success, reply = __nextByType(transport, initiator, uuid, handle, 0xffff, trace); 250 if not success: 251 success = (reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE) and \ 252 (reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND) and (len(services['handles']) > 0); 253 break; 254 255 for _handle, _value in zip(reply['handle'], reply['value']): 256 services['handles'] += [ [ toNumber(_value[:2]), toNumber(_value[2:4]) ] ]; 257 if len(_value) > 4: 258 services['uuids'] += [ toNumber(_value[4:]) ]; 259 else: 260 """ 261 262 NOTE: Test Specification suggest to issue a ATT_READ_REQUEST to get the 128-bit UUID, 263 but the ATT_READ_RESPONSE will only contain the handle range. 264 """ 265 success, _service = __discoverServices(transport, initiator, toNumber(_value[:2]), toNumber(_value[2:4]), 0x2800, trace); 266 if success: 267 services['uuids'] += _service['uuids']; 268 269 handle = reply['handle'][-1] + 1; 270 if handle > 0xFFFF: 271 break; 272 273 return success, services; 274 275""" 276 Discover Characteristic by using ATT_Read_By_Type_Requests 277""" 278def characteristicByType(transport, initiator, handles, characteristicUUID, ignoreErrors, trace): 279 characteristics = { 'handle': [], 'value': [] }; 280 reply = {}; 281 attData = ATTData(); 282 283 success, handle = True, handles[0]; 284 while success: 285 success, reply = __nextByType(transport, initiator, characteristicUUID, handle, handles[1], trace); 286 if success: 287 for _handle, _value in zip(reply['handle'], reply['value']): 288 characteristics['handle'] += [ _handle ]; 289 characteristics['value'] += [ _value ]; 290 291 elif reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE: 292 if reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND: 293 success = len(characteristics['handle']) > 0; 294 break; 295 elif attData.isPermissionError(reply['error']): 296 success = ignoreErrors; 297 298 handle = reply['handle'][-1] + 1; 299 if handle > handles[1]: 300 break; 301 302 return success, characteristics if success else reply; 303 304""" 305 Discover Characteristics by using ATT_Read_By_Type_Requests 306""" 307def characteristicsByType(transport, initiator, handles, trace): 308 characteristics = { 'handle': [], 'property': [], 'value_handle': [], 'uuid': [] }; 309 attData = ATTData(); 310 311 success, handle, uuid = True, handles[0], 0x2803; 312 while success: 313 success, reply = __nextByType(transport, initiator, uuid, handle, handles[1], trace); 314 if success: 315 for _handle, _value in zip(reply['handle'], reply['value']): 316 characteristics['handle'] += [ _handle ]; 317 characteristics['property'] += [ _value[0] ]; 318 characteristics['value_handle'] += [ toNumber(_value[1:3]) ]; 319 characteristics['uuid'] += [ toNumber(_value[3:]) ]; 320 321 elif reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE: 322 if reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND: 323 success = len(characteristics['handle']) > 0; 324 break; 325 elif reply['error'] == ATTError.ATT_ERROR_READ_NOT_PERMITTED: 326 success = True; 327 328 handle = reply['handle'][-1] + 1; 329 if handle > handles[1]: 330 break; 331 332 return success, characteristics; 333 334""" 335 Discover Descriptors by using ATT_Find_Information_Requests 336""" 337def discoverDescriptors(transport, initiator, handles, trace): 338 characteristics = { 'handle': [], 'uuid': [] }; 339 attData = ATTData(); 340 341 success, handle, bCharacteristic, bValue, bDescriptor = True, handles[0], False, False, False; 342 while success: 343 success, reply = __nextFindInformation(transport, initiator, handle, handles[1], trace); 344 if not success: 345 success = (reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE) and \ 346 (reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND) and (len(characteristics['handle']) > 0); 347 break; 348 """ 349 The hirachy is: 350 CHARACTERIISTIC 351 VALUE 352 DESCRIPTOR... 353 """ 354 for _handle, _uuid in zip(reply['handle'], reply['uuid']): 355 bCharacteristic = _uuid == 0x2803; 356 bDescriptor = bDescriptor and not bCharacteristic; 357 if bDescriptor: 358 characteristics['handle'] += [ _handle ]; 359 characteristics['uuid'] += [ _uuid ]; 360 bDescriptor = bDescriptor or bValue; 361 bValue = bCharacteristic; 362 363 handle = reply['handle'][-1] + 1; 364 if handle > handles[1]: 365 break; 366 367 return success, characteristics; 368 369""" 370 Discover Descriptors by using ATT_Find_Information_Requests 371""" 372def specificDescriptors(transport, initiator, handles, uuid, trace): 373 characteristics = { 'handle': [], 'uuid': [] }; 374 attData = ATTData(); 375 376 success, handle, bCharacteristic, bValue, bDescriptor = True, handles[0], False, False, False; 377 while success: 378 success, reply = __nextFindInformation(transport, initiator, handle, handles[1], trace); 379 if not success: 380 success = (reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE) and \ 381 (reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND) and (len(characteristics['handle']) > 0); 382 break; 383 384 for _handle, _uuid in zip(reply['handle'], reply['uuid']): 385 bDescriptor = _uuid == uuid; 386 if bDescriptor: 387 characteristics['handle'] += [ _handle ]; 388 characteristics['uuid'] += [ _uuid ]; 389 390 handle = reply['handle'][-1] + 1; 391 if handle > handles[1]: 392 break; 393 394 return success, characteristics; 395 396""" 397 Partial Read Blob passing handle and offset 398""" 399def __readBlob(transport, initiator, handle, offset, trace): 400 attData = ATTData(); 401 reply = { 'error': -1 }; 402 403 txData = attData.encode( ATTOpcode.ATT_READ_BLOB_REQUEST, handle, offset ); 404 trace.trace(7, str(attData)); 405 success = attRequest( transport, initiator, txData, trace ); 406 if success: 407 success, rxData = attResponse( transport, initiator, trace ); 408 if success: 409 reply = attData.decode( rxData ); 410 trace.trace(7, str(attData)); 411 success = reply['opcode'] == ATTOpcode.ATT_READ_BLOB_RESPONSE; 412 413 return success, reply; 414 415""" 416 Read Blob passing handle and MTU size 417""" 418def readBlob(transport, initiator, handle, mtuSize, trace): 419 attData = ATTData(); 420 421 value, offset, success = [], 0, True; 422 while success: 423 success, reply = __readBlob(transport, initiator, handle, offset, trace); 424 if success and len(reply['value']) > 0: 425 value += reply['value']; 426 offset += len(reply['value']); 427 if len(reply['value']) < mtuSize-1: 428 break; 429 else: 430 break; 431 432 return success, value if success else reply['error']; 433 434""" 435 Read Characteristic passing handle 436""" 437def readCharacteristic(transport, initiator, handle, trace): 438 attData = ATTData(); 439 440 txData = attData.encode( ATTOpcode.ATT_READ_REQUEST, handle ); 441 trace.trace(7, str(attData)); 442 success = attRequest( transport, initiator, txData, trace ); 443 if success: 444 success, rxData = attResponse( transport, initiator, trace ); 445 if success: 446 reply = attData.decode( rxData ); 447 trace.trace(7, str(attData)); 448 success = reply['opcode'] == ATTOpcode.ATT_READ_RESPONSE; 449 450 return success, reply['value'] if success else reply['error']; 451 452""" 453 Read Multiple Characteristics passing handles 454""" 455def readMultipleCharacteristics(transport, initiator, handles, trace): 456 attData = ATTData(); 457 458 txData = attData.encode( ATTOpcode.ATT_READ_MULTIPLE_REQUEST, handles ); 459 trace.trace(7, str(attData)); 460 success = attRequest( transport, initiator, txData, trace ); 461 if success: 462 success, rxData = attResponse( transport, initiator, trace ); 463 if success: 464 reply = attData.decode( rxData ); 465 trace.trace(7, str(attData)); 466 success = reply['opcode'] == ATTOpcode.ATT_READ_MULTIPLE_RESPONSE; 467 468 return success, reply['value'] if success else reply['error']; 469 470""" 471 Read Characteristics as a String passing handles 472""" 473def readStringCharacteristic(transport, initiator, handle, trace): 474 success, data = readCharacteristic(transport, initiator, handle, trace); 475 476 return success, bytes(data).decode('utf-8') if success else ''; 477 478""" 479 Writing Characteristic passing handle 480""" 481def writeCharacteristic(transport, initiator, handle, data, trace): 482 attData = ATTData(); 483 reply = { 'opcode': ATTOpcode.ATT_WRITE_RESPONSE }; 484 485 txData = attData.encode( ATTOpcode.ATT_WRITE_REQUEST, handle, data ); 486 trace.trace(7, str(attData)); 487 success = attRequest( transport, initiator, txData, trace ); 488 """ 489 Receive the response ATT_WRITE_RESPONSE or ATT_ERROR_RESPONSE... 490 """ 491 if success: 492 success, rxData = attResponse( transport, initiator, trace ); 493 if success: 494 reply = attData.decode( rxData ); 495 trace.trace(7, str(attData)); 496 success = reply['opcode'] == ATTOpcode.ATT_WRITE_RESPONSE; 497 498 return success, reply; 499 500""" 501 Writing Characteristic with No Response 502""" 503def writeNoResponse(transport, initiator, handle, data, trace): 504 attData = ATTData(); 505 reply = { 'opcode': ATTOpcode.ATT_ERROR_RESPONSE, 'error': 0 }; 506 507 txData = attData.encode( ATTOpcode.ATT_WRITE_COMMAND, handle, data ); 508 success = attRequest( transport, initiator, txData, trace ); 509 """ 510 Check for a response, could be an ATT_ERROR_RESPONSE... 511 """ 512 if success: 513 success, rxData = attResponse( transport, initiator, trace ); 514 if success: 515 reply = attData.decode( rxData ); 516 success = False; 517 else: 518 success = True; 519 520 return success, reply; 521 522""" 523 Partial Writing Long Characteristic passing handle, offset and data (ATT_Prepare_Write_Request) 524""" 525def __writeLong(transport, initiator, handle, data, offset, trace): 526 attData = ATTData(); 527 reply = { 'opcode': ATTOpcode.ATT_ERROR_RESPONSE, 'error': -1 }; 528 529 txData = attData.encode( ATTOpcode.ATT_PREPARE_WRITE_REQUEST, handle, offset, data ); 530 success = attRequest( transport, initiator, txData, trace ); 531 """ 532 Check for a response, could be an ATT_ERROR_RESPONSE... 533 """ 534 if success: 535 success, rxData = attResponse( transport, initiator, trace ); 536 if success: 537 reply = attData.decode( rxData ); 538 success = reply['opcode'] == ATTOpcode.ATT_PREPARE_WRITE_RESPONSE; 539 540 return success, reply; 541 542""" 543 Partial Writing Long Characteristic (ATT_Execute_Write_Request) 544""" 545def __writeExecute(transport, initiator, trace): 546 attData = ATTData(); 547 reply = { 'opcode': ATTOpcode.ATT_ERROR_RESPONSE, 'error': -1 }; 548 549 txData = attData.encode( ATTOpcode.ATT_EXECUTE_WRITE_REQUEST, 1 ); 550 success = attRequest( transport, initiator, txData, trace ); 551 if success: 552 success, rxData = attResponse( transport, initiator, trace ); 553 if success: 554 reply = attData.decode( rxData ); 555 success = reply['opcode'] == ATTOpcode.ATT_EXECUTE_WRITE_RESPONSE; 556 557 return success, reply; 558 559""" 560 Writing Long Characteristic passing handle, data and MTU size 561""" 562def writeLong(transport, initiator, handle, data, mtuSize, trace): 563 offset, success, attData = 0, True, ATTData(); 564 reply = { 'opcode': ATTOpcode.ATT_ERROR_RESPONSE, 'error': 0 }; 565 566 while success: 567 success, reply = __writeLong(transport, initiator, handle, \ 568 data[offset:offset+mtuSize-5 if offset+mtuSize-5 < len(data) else len(data)], offset, trace); 569 if not success: 570 break; 571 offset += len(reply['value']); 572 if offset >= len(data): 573 break; 574 575 if success: 576 success, reply = __writeExecute(transport, initiator, trace); 577 578 return success, reply; 579 580""" 581 Receive Notification... 582""" 583def notification(transport, initiator, trace): 584 attData = ATTData(); 585 reply = { 'opcode': ATTOpcode.ATT_HANDLE_VALUE_NOTIFICATION, 'value': [] }; 586 587 success, rxData = attResponse( transport, initiator, trace ); 588 if success: 589 reply = attData.decode( rxData ); 590 trace.trace(7, str(attData)); 591 success = reply['opcode'] == ATTOpcode.ATT_HANDLE_VALUE_NOTIFICATION; 592 593 return success, reply; 594 595""" 596 Receive Indication and issue Indication Confirmation... 597""" 598def indication(transport, initiator, trace): 599 attData = ATTData(); 600 reply = { 'opcode': ATTOpcode.ATT_HANDLE_VALUE_INDICATION, 'value': [] }; 601 602 success, rxData = attResponse( transport, initiator, trace, 200 ); 603 if success: 604 reply = attData.decode( rxData ); 605 trace.trace(7, str(attData)); 606 success = reply['opcode'] == ATTOpcode.ATT_HANDLE_VALUE_INDICATION; 607 if success: 608 txData = attData.encode( ATTOpcode.ATT_HANDLE_VALUE_CONFIRMATION ); 609 trace.trace(7, str(attData)); 610 success = attRequest( transport, initiator, txData, trace ); 611 612 return success, reply; 613 614""" 615 Obtain the value handle for a Characteristic given its UUID 616""" 617def valueHandle(characteristics, uuid): 618 handle = -1; 619 for value_handle, char_uuid in zip(characteristics['value_handle'], characteristics['uuid']): 620 if char_uuid == uuid: 621 handle = value_handle; 622 break; 623 return handle; 624 625def filterCharacteristics(characteristics, uuid): 626 _characteristics = { 'uuid': [], 'handle': [] }; 627 for _uuid, _handle in zip(characteristics['uuid'], characteristics['handle']): 628 if _uuid == uuid: 629 _characteristics['uuid'] += [ _uuid ]; 630 _characteristics['handle'] += [ _handle ]; 631 return _characteristics; 632 633""" 634 Obtain the peer Bluetooth address by starting a scanner... 635""" 636def peerAddress(transport, upperTester, trace): 637 success, address = False, Address( None, None ); 638 639 try: 640 ownAddress = Address( ExtendedAddressType.PUBLIC ); 641 scanner = Scanner(transport, upperTester, trace, ScanType.PASSIVE, AdvertisingReport.ADV_IND, ownAddress, ScanningFilterPolicy.FILTER_NONE, 1); 642 """ 643 Start Scanner to obtain address of peer 644 """ 645 success = scanner.enable(); 646 scanner.monitor(); 647 success = success and scanner.disable(); 648 success = success and scanner.qualifyReports( 1 ); 649 """ 650 Obtain address of Advertiser 651 """ 652 if success: 653 address = scanner.reportAddress; 654 655 except Exception as e: 656 trace.trace(3, "Failed to obtain peer Address: %s" % str(e)); 657 success = False; 658 659 return success, address; 660 661""" 662 Obtain address of peer, connect to peer and exchange MTU sizes 663""" 664def preambleConnected(transport, idx, mtuSizeRequested, trace): 665 mtuSize = -1; 666 """ 667 Obtain address of Advertiser 668 """ 669 success, address = peerAddress(transport, idx, trace); 670 if not success: 671 raise UnboundLocalError('Failed to obtain peer Address'); 672 673 trace.trace(6, "Advertiser address: %s" % str(address)); 674 """ 675 Initiate connection with Advertiser 676 """ 677 initiator = Initiator(transport, idx, None, trace, Address( ExtendedAddressType.PUBLIC, 0x123456789ABC ), address ); 678 connected = initiator.connect(); 679 success = success and connected; 680 if connected: 681 """ 682 Exchange MTU Size 683 """ 684 success, mtuSize = exchangeMTU(transport, initiator, mtuSizeRequested, trace); 685 trace.trace(6,"MTU Size: %d" % mtuSize); 686 687 return success, mtuSize, initiator; 688 689""" 690 Trial Pairing and Pairing pause 691""" 692def pairing_bv_01_c(transport, upperTester, trace): 693 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 694 if success: 695 pairing = Pairing(transport, trace, initiator, toNumber(upperIRK)); 696 paired = pairing.pair(); 697 if paired: 698 trace.trace(6,"Link Encrypted!"); 699 success = pairing.pause(); 700 if success: 701 trace.trace(6, "Link re-encrypted!"); 702 else: 703 trace.trace(6, "Failed to re-encrypt link!"); 704 705 success = success and paired; 706 707 connected = not initiator.disconnect(0x13) 708 success = success and not connected; 709 710 return success; 711 712""" 713 GAP/GAT/BV-01-C [Mandatory Characteristics] 714""" 715def gap_gat_bv_01_c(transport, upperTester, trace): 716 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 717 if success: 718 """ 719 Lookup the Generic Access Service (0x1800) 720 """ 721 success, service = discoverPrimaryService(transport, initiator, 0x1800, trace); 722 if success: 723 """ 724 Fetch the Characteristics 725 """ 726 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 727 success, characteristics = characteristicsByType(transport, initiator, service["handles"][0], trace); 728 if success: 729 for c_uuid, c_handle, c_property, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 730 characteristics["property"], characteristics["value_handle"]): 731 trace.trace(6, "Characteristic %s handle %02X value-handle %02X properties %s" % \ 732 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property))); 733 734 _characteristics = gattData.characteristics(sset, service["handles"][0][0]); 735 _characteristics.pop("permission"); 736 """ 737 Verify Characteristics outline... 738 """ 739 success = characteristics == _characteristics 740 trace.trace(6, "GAP Characteristics structure verified %s" % success); 741 if success: 742 """ 743 Verify Characteristic values... 744 """ 745 for c_uuid, c_handle, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], characteristics["value_handle"]): 746 if c_uuid == 0x2A00: 747 _value = gattData.characteristicString(sset, c_handle); 748 ok, reply = readStringCharacteristic(transport, initiator, c_vhandle, trace); 749 trace.trace(6, "Read Characteristic with handle #%d - %s" % (c_vhandle, reply)); 750 else: 751 _value = gattData.characteristicValue(sset, c_handle); 752 ok, reply = readCharacteristic(transport, initiator, c_vhandle, trace); 753 trace.trace(6, "Read Characteristic with handle #%d - %s" % (c_vhandle, formatArray(reply))); 754 success = success and ok and reply == _value; 755 else: 756 trace.trace(6, "Failed to verify GAP Characteristics structure!"); 757 else: 758 trace.trace(6, "Failed to read GAP Service Characteristics!"); 759 else: 760 trace.trace(6, "Failed to locate GAP Service!"); 761 762 success = initiator.disconnect(0x13) and success; 763 764 return success; 765 766""" 767 GAP/GAT/BV-02-C [Peripheral Privacy Flag Characteristic] 768""" 769def gap_gat_bv_02_c(transport, upperTester, trace): 770 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 771 if success: 772 """ 773 Lookup the Generic Access Service (0x1800) 774 """ 775 success, service = discoverPrimaryService(transport, initiator, 0x1800, trace); 776 """ 777 Fetch the Peripheral Privacy Flag Characteristic 778 """ 779 success, characteristic = characteristicByType(transport, initiator, service["handles"][0], 0x2A02, False, trace); 780 if success: 781 flag = characteristic["value"][0] 782 trace.trace(6,"Peripheral Privacy Flag: %d" % flag); 783 else: 784 trace.trace(6,"Peripheral Privacy Flag: Not present!"); 785 786 success = initiator.disconnect(0x13) and success; 787 788 return success; 789 790""" 791 GAP/GAT/BV-03-C [Reconnection Address Characteristic] 792""" 793def gap_gat_bv_03_c(transport, upperTester, trace): 794 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 795 if success: 796 """ 797 Lookup the Generic Access Service (0x1800) 798 """ 799 success, service = discoverPrimaryService(transport, initiator, 0x1800, trace); 800 """ 801 Fetch the Reconnection Address Characteristic 802 """ 803 success, characteristic = characteristicByType(transport, initiator, service["handles"][0], 0x2A03, False, trace); 804 if success: 805 data = characteristic["value"][0]; 806 trace.trace(6,"Reconnection Address: %s" % formatAddress( data )); 807 else: 808 trace.trace(6,"Reconnection Address: Not present!"); 809 810 success = initiator.disconnect(0x13) and success; 811 812 return success; 813 814""" 815 GAP/GAT/BV-04-C [Peripheral Preferred Connection Parameters Characteristic] 816""" 817def gap_gat_bv_04_c(transport, upperTester, trace): 818 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 819 if success: 820 """ 821 Lookup the Generic Access Service (0x1800) 822 """ 823 success, service = discoverPrimaryService(transport, initiator, 0x1800, trace); 824 """ 825 Fetch the Peripheral Preferred Connection Parameters Characteristic 826 """ 827 success, characteristic = characteristicByType(transport, initiator, service["handles"][0], 0x2A04, False, trace); 828 if success: 829 data = characteristic["value"][0]; 830 trace.trace(6,"Peripheral Preferred Connection Parameters:"); 831 trace.trace(6,"Minimum Connection Interval: %d" % toNumber( data[0:2] )); 832 trace.trace(6,"Maximum Connection Interval: %d" % toNumber( data[2:4] )); 833 trace.trace(6," Peripheral Latency: %d" % toNumber( data[4:6] )); 834 trace.trace(6,"Connection Supervision Timeout Multiplier: %d" % toNumber( data[6:8] )); 835 else: 836 trace.trace(6,"Peripheral Preferred Connection Parameters: Not present!"); 837 838 connected = not initiator.disconnect(0x13) 839 success = success and not connected; 840 if not connected: 841 """ 842 Attempt to reconnect with proposed connection parameters 843 """ 844 initiator.intervalMin = toNumber( data[0:2] ); 845 initiator.intervalMax = toNumber( data[2:4] ); 846 initiator.latency = toNumber( data[4:6] ); 847 initiator.supervisionTimeout = toNumber( data[6:8] ); 848 849 connected = initiator.connect(); 850 success = success and connected; 851 if connected: 852 transport.wait(200); 853 success = initiator.disconnect(0x13) and success; 854 855 return success; 856 857""" 858 GAP/GAT/BV-05-C [Changing Device Name] 859""" 860def gap_gat_bv_05_c(transport, upperTester, trace): 861 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 862 if success: 863 """ 864 Lookup the Generic Access Service (0x1800) 865 """ 866 success, service = discoverPrimaryService(transport, initiator, 0x1800, trace); 867 """ 868 Fetch the Device Name Characteristic 869 """ 870 success, characteristic = characteristicByType(transport, initiator, service["handles"][0], 0x2A00, False, trace); 871 if success: 872 handle = characteristic["handle"][0]; 873 data = characteristic["value"][0]; 874 name = ''.join([chr(_) for _ in data]).decode('utf-8'); 875 trace.trace(6,"Device Name: %s" % name); 876 877 setName = 'Rødgrød & Blåbær med fløde'.encode('UTF-8'); 878 data = [ ord(_) for _ in setName ]; 879 success, reply = writeCharacteristic(transport, initiator, handle, data, trace); 880 881 if success: 882 success, gotName = readStringCharacteristic(transport, initiator, handle, trace); 883 trace.trace(6,"Device Name: %s" % gotName); 884 success = success and (gotName == setName); 885 else: 886 if reply["opcode"] == ATTOpcode.ATT_ERROR_RESPONSE: 887 trace.trace(6,"Failed to write Device Name - error code: %d - %s" % (reply["error"], ATTData().error(reply["error"])) ); 888 else: 889 trace.trace(6,"Failed to write Device Name - unknown reply: %d" % reply["opcode"]); 890 else: 891 trace.trace(6,"Device Name: Not present!"); 892 893 success = initiator.disconnect(0x13) and success; 894 895 return success; 896 897""" 898 GAP/GAT/BX-01-C [Discover All Services] 899""" 900def gap_gat_bx_01_c(transport, upperTester, trace): 901 try: 902 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 903 if success: 904 """ 905 Discover all Services 906 """ 907 attData = ATTData(); 908 success, services = discoverPrimaryServices(transport, initiator, trace); 909 for uuid, handles in zip(services["uuids"], services["handles"]): 910 trace.trace(6, "Service %s covers [%02X, %02X]" % (attData.uuid(uuid), handles[0], handles[1])); 911 912 success, characteristics = characteristicsByType(transport, initiator, handles, trace); 913 for c_uuid, c_handle, c_property, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 914 characteristics["property"], characteristics["value_handle"]): 915 trace.trace(6, " Characteristic %s handle %02X value-handle %02X properties %s" % \ 916 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property))); 917 918 success = initiator.disconnect(0x13) and success; 919 920 except Exception as e: 921 trace.trace(3, "Discover All Services test failed: %s" % str(e)); 922 success = False; 923 924 return success; 925 926""" 927 GAP/IDLE/NAMP/BV-01-C [Name Discovery Procedure GATT Client] 928""" 929def gap_idle_namp_bv_01_c(transport, upperTester, trace): 930 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 931 if success: 932 """ 933 Lookup the Generic Access Service (0x1800) 934 """ 935 success, service = discoverPrimaryService(transport, initiator, 0x1800, trace); 936 """ 937 Fetch the Device Name Characteristic 938 """ 939 success, characteristic = characteristicByType(transport, initiator, service["handles"][0], 0x2A00, False, trace); 940 if success: 941 data = characteristic["value"][0]; 942 name = bytes(data).decode('utf-8'); 943 trace.trace(6,"Device Name: %s" % name); 944 else: 945 trace.trace(6,"Device Name: Not present!"); 946 947 success = initiator.disconnect(0x13) and success; 948 949 return success; 950 951""" 952 GATT/SR/GAC/BV-01-C [Server accepts Server Configuration] 953""" 954def gatt_sr_gac_bv_01_c(transport, upperTester, lowerTester, trace): 955 for mtuSize in [ 23, 512 ]: 956 success, mtuSize, initiator = preambleConnected(transport, upperTester, mtuSize, trace); 957 if success: 958 """ 959 Switch to Service Set #1 960 """ 961 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 962 switch_gatt_service_set(transport, lowerTester, sset, 200); 963 """ 964 Collect all Characteristics that have READ permission 965 """ 966 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ); 967 """ 968 Find the ones that is longer than (MTU-1) if MTU < 512 else the ones that is 512 if MTU = 512 969 """ 970 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 971 _value = gattData.characteristicValue(sset, _handle); 972 if len(_value) > mtuSize-1: 973 trace.trace(6, "Read Characteristic %s handle #%d length %d" % (attData.uuid(_uuid), _value_handle, len(_value))); 974 ok, reply = readCharacteristic(transport, initiator, _value_handle, trace); 975 success = success and ok and reply == _value[:mtuSize-1]; 976 977 success = initiator.disconnect(0x13) and success; 978 979 return success; 980 981""" 982 GATT/SR/GAD/BV-01-C [Server Discovers All Primary Services] 983""" 984def gatt_sr_gad_bv_01_c(transport, upperTester, lowerTester, trace): 985 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 986 if success: 987 attData, gattData = ATTData(), GATTData.instance(); 988 989 for sset in range(4): 990 """ 991 Switching Service Set 992 """ 993 trace.trace(6, "Switching to Service Set #%d" % sset); 994 switch_gatt_service_set(transport, lowerTester, sset, 200); 995 """ 996 Discover all Primary Services 997 """ 998 success, services = discoverPrimaryServices(transport, initiator, trace); 999 if success: 1000 for _uuid, _handles in zip(services["uuids"], services["handles"]): 1001 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(_uuid), _handles[0], _handles[1])); 1002 success = services == gattData.primaryServices(sset) 1003 trace.trace(6, "Verified Service Set: %s" % success); 1004 else: 1005 trace.trace(6, "Unable to discover Primary Services!"); 1006 1007 success = initiator.disconnect(0x13) and success; 1008 1009 return success; 1010 1011""" 1012 GATT/SR/GAD/BV-02-C [Server Discovers Primary Services by Service UUID] 1013""" 1014def gatt_sr_gad_bv_02_c(transport, upperTester, lowerTester, trace): 1015 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1016 if success: 1017 attData, gattData = ATTData(), GATTData.instance(); 1018 1019 for sset in range(4): 1020 """ 1021 Switching Service Set 1022 """ 1023 trace.trace(6, "Switching to Service Set #%d" % sset); 1024 switch_gatt_service_set(transport, lowerTester, sset, 200); 1025 """ 1026 Iterate over the unique Service UUIDs in the Service Set... 1027 """ 1028 trace.trace(6, "Service Set #%d:" % sset); 1029 for uuid in sorted(list(set(gattData.primaryServices(sset)['uuids']))): 1030 found, services = discoverPrimaryService(transport, initiator, uuid, trace); 1031 if found: 1032 for _uuid, _handles in zip(services["uuids"], services["handles"]): 1033 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(_uuid), _handles[0], _handles[1])); 1034 else: 1035 trace.trace(6, "Couldn't find Service %s" % attData.uuid(uuid)); 1036 1037 success = success and found; 1038 success = success and (services == gattData.primaryServices(sset, uuid)); 1039 trace.trace(6, "Verified Services: %s" % success); 1040 1041 success = initiator.disconnect(0x13) and success; 1042 1043 return success; 1044 1045""" 1046 GATT/SR/GAD/BV-03-C [Server Finds Included Services] 1047""" 1048def gatt_sr_gad_bv_03_c(transport, upperTester, lowerTester, trace): 1049 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1050 if success: 1051 attData, gattData = ATTData(), GATTData.instance(); 1052 1053 for sset in range(4): 1054 """ 1055 Switching Service Set 1056 """ 1057 trace.trace(6, "Switching to Service Set #%d" % sset); 1058 switch_gatt_service_set(transport, lowerTester, sset, 200); 1059 """ 1060 Discover Included Services in the selected Service Set... 1061 """ 1062 found, services = includedServicesByType(transport, initiator, trace); 1063 if found: 1064 for uuid, handles in zip(services["uuids"], services["handles"]): 1065 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(uuid), handles[0], handles[1])); 1066 1067 if sset == 0: 1068 success = success and not found; 1069 else: 1070 success = success and found; 1071 success = success and (services == gattData.includedServices(sset)) 1072 trace.trace(6, "Verified Included Services: %s" % success); 1073 1074 success = initiator.disconnect(0x13) and success; 1075 1076 return success; 1077 1078""" 1079 GATT/SR/GAD/BV-04-C [Server Discovers All Characteristics of a Service] 1080""" 1081def gatt_sr_gad_bv_04_c(transport, upperTester, lowerTester, trace): 1082 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1083 if success: 1084 attData, gattData = ATTData(), GATTData.instance(); 1085 1086 for sset in range(4): 1087 """ 1088 Switching Service Set 1089 """ 1090 trace.trace(6, "Switching to Service Set #%d" % sset); 1091 switch_gatt_service_set(transport, lowerTester, sset, 200); 1092 """ 1093 Discover all Primary Services... 1094 """ 1095 found, services = discoverPrimaryServices(transport, initiator, trace); 1096 success = success and found; 1097 for uuid, handles in zip(services["uuids"], services["handles"]): 1098 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(uuid), handles[0], handles[1])); 1099 1100 _characteristics = gattData.characteristics(sset, handles[0]); 1101 _characteristics.pop("permission"); 1102 1103 found, characteristics = characteristicsByType(transport, initiator, handles, trace); 1104 if found: 1105 for c_uuid, c_handle, c_property, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 1106 characteristics["property"], characteristics["value_handle"]): 1107 trace.trace(6, " Characteristic %s handle 0x%02X value-handle 0x%02X properties %s" % \ 1108 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property))); 1109 success = success and (characteristics == _characteristics) 1110 else: 1111 success = success and len(_characteristics["uuid"]) == 0; 1112 trace.trace(6, "Characteristics for Service %s Verified: %s" % (attData.uuid(uuid), success)); 1113 1114 success = initiator.disconnect(0x13) and success; 1115 1116 return success; 1117 1118""" 1119 GATT/SR/GAD/BV-05-C [Server Discovers Characteristics by UUID] 1120""" 1121def gatt_sr_gad_bv_05_c(transport, upperTester, lowerTester, trace): 1122 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1123 if success: 1124 attData, gattData = ATTData(), GATTData.instance(); 1125 1126 for sset in range(4): 1127 """ 1128 Switching Service Set 1129 """ 1130 trace.trace(6, "Switching to Service Set #%d" % sset); 1131 switch_gatt_service_set(transport, lowerTester, sset, 200); 1132 """ 1133 Discover all Primary Services 1134 """ 1135 found, services = discoverPrimaryServices(transport, initiator, trace); 1136 success = success and found; 1137 for uuid, handles in zip(services["uuids"], services["handles"]): 1138 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(uuid), handles[0], handles[1])); 1139 1140 _characteristics = gattData.characteristics(sset, handles[0]); 1141 _characteristics.pop("permission"); 1142 1143 found, characteristics = characteristicsByType(transport, initiator, handles, trace); 1144 if found: 1145 for c_uuid, c_handle, c_property, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 1146 characteristics["property"], characteristics["value_handle"]): 1147 trace.trace(6, " Characteristic %s handle 0x%02X value-handle 0x%02X properties %s" % \ 1148 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property))); 1149 success = success and (characteristics == _characteristics) 1150 else: 1151 success = success and len(_characteristics["uuid"]) == 0; 1152 trace.trace(6, "Characteristics for Service %s Verified: %s" % (attData.uuid(uuid), success)); 1153 1154 success = initiator.disconnect(0x13) and success; 1155 1156 return success; 1157 1158""" 1159 GATT/SR/GAD/BV-06-C [Server Discovers All Characteristic Descriptors] 1160""" 1161def gatt_sr_gad_bv_06_c(transport, upperTester, lowerTester, trace): 1162 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1163 if success: 1164 attData, gattData = ATTData(), GATTData.instance(); 1165 1166 for sset in range(4): 1167 """ 1168 Switching Service Set 1169 """ 1170 trace.trace(6, "Switching to Service Set #%d" % sset); 1171 switch_gatt_service_set(transport, lowerTester, sset, 200); 1172 """ 1173 Discover all Primary Services 1174 """ 1175 found, services = discoverPrimaryServices(transport, initiator, trace); 1176 success = success and found; 1177 for uuid, handles in zip(services["uuids"], services["handles"]): 1178 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(uuid), handles[0], handles[1])); 1179 1180 _descriptors = gattData.descriptors(sset, handles[0]); 1181 1182 found, descriptors = discoverDescriptors(transport, initiator, handles, trace); 1183 if found: 1184 for c_uuid, c_handle in zip(descriptors["uuid"], descriptors["handle"]): 1185 trace.trace(6, " Descriptor %s handle 0x%02X" % (attData.uuid(c_uuid), c_handle)); 1186 success = success and (descriptors == _descriptors) 1187 else: 1188 success = success and len(_descriptors["uuid"]) == 0; 1189 trace.trace(6, "Descriptors for Service %s Verified: %s" % (attData.uuid(uuid), success)); 1190 1191 success = initiator.disconnect(0x13) and success; 1192 1193 return success; 1194 1195""" 1196 GATT/SR/GAR/BV-01-C [Server Reads Characteristic Value] 1197""" 1198def gatt_sr_gar_bv_01_c(transport, upperTester, lowerTester, trace): 1199 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1200 if success: 1201 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 1202 """ 1203 Switch to Service Set #2 1204 """ 1205 trace.trace(6, "Switching to Service Set #%d" % sset); 1206 switch_gatt_service_set(transport, lowerTester, sset, 200); 1207 """ 1208 Get all Characteristics that have READ permission 1209 """ 1210 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ); 1211 for c_uuid, c_handle, c_property, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 1212 characteristics["property"], characteristics["value_handle"]): 1213 trace.trace(6, "Characteristic %s handle 0x%02X value-handle 0x%02X properties %s" % \ 1214 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property))); 1215 success, data = readCharacteristic(transport, initiator, c_vhandle, trace); 1216 trace.trace(6, " Characteristic Value: %s" % formatArray(data)); 1217 match = data == gattData.characteristicValue(sset, c_handle); 1218 success = success and match; 1219 trace.trace(6, " Characteristic Value Verified: %s" % success); 1220 1221 success = initiator.disconnect(0x13) and success; 1222 1223 return success; 1224 1225""" 1226 GATT/SR/GAR/BI-01-C [Read Not Permitted error - Reading Characteristic Value] 1227""" 1228def gatt_sr_gar_bi_01_c(transport, upperTester, lowerTester, trace): 1229 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1230 if success: 1231 sset, prevLast, attData, gattData = 2, 0, ATTData(), GATTData.instance(); 1232 """ 1233 Switch to Service Set #2 1234 """ 1235 trace.trace(6, "Switching to Service Set #%d" % sset); 1236 switch_gatt_service_set(transport, lowerTester, sset, 200); 1237 """ 1238 Collect all Services 1239 """ 1240 services = gattData.allServices(sset); 1241 for uuid, handles in zip(services["uuids"], services["handles"]): 1242 trace.trace(6, "Service %s covers handles [%02d, %02d]" % (attData.uuid(uuid), handles[0], handles[1])); 1243 1244 if handles[0] > (prevLast+1): 1245 ok, data = readCharacteristic(transport, initiator, (handles[0] + prevLast)//2, trace); 1246 success = success and not ok and data == ATTError.ATT_ERROR_INVALID_HANDLE; 1247 trace.trace(6, "Attempted to read Characteristic @ handle %02d - %s" % ((handles[0] + prevLast)//2, attData.error(data))); 1248 prevLast = handles[1]; 1249 1250 success = initiator.disconnect(0x13) and success; 1251 1252 return success; 1253 1254""" 1255 GATT/SR/GAR/BI-02-C [Invalid Handle error - Reading Characteristic Value] 1256""" 1257def gatt_sr_gar_bi_02_c(transport, upperTester, lowerTester, trace): 1258 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1259 if success: 1260 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 1261 """ 1262 Switch to Service Set #2 1263 """ 1264 trace.trace(6, "Switching to Service Set #%d" % sset); 1265 switch_gatt_service_set(transport, lowerTester, sset, 200); 1266 """ 1267 Get all Characteristics that doesn't have READ permission 1268 """ 1269 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_ANY_READ, True); 1270 for c_uuid, c_handle, c_property, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 1271 characteristics["property"], characteristics["value_handle"]): 1272 trace.trace(6, "Characteristic %s handle 0x%02X value-handle 0x%02X properties %s" % \ 1273 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property))); 1274 ok, data = readCharacteristic(transport, initiator, c_vhandle, trace); 1275 success = success and not ok and data == ATTError.ATT_ERROR_READ_NOT_PERMITTED; 1276 trace.trace(6, "Attempted to read Characteristic @ handle %02d - %s" % (c_vhandle, attData.error(data))); 1277 1278 success = initiator.disconnect(0x13) and success; 1279 1280 return success; 1281 1282""" 1283 GATT/SR/GAR/BI-03-C [Insufficient Authorization error - Reading Characteristic Value] 1284""" 1285def gatt_sr_gar_bi_03_c(transport, upperTester, lowerTester, trace): 1286 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1287 if success: 1288 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1289 """ 1290 Switch to Service Set #1 1291 """ 1292 trace.trace(6, "Switching to Service Set #%d" % sset); 1293 switch_gatt_service_set(transport, lowerTester, sset, 200); 1294 """ 1295 Collect all Characteristics that have Authorized READ permission 1296 """ 1297 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHOR); 1298 for c_uuid, c_handle, c_property, c_permission, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 1299 characteristics["property"], characteristics["permission"], \ 1300 characteristics["value_handle"]): 1301 trace.trace(6, "Characteristic %s handle 0x%02X value-handle 0x%02X properties %s permissions %s" % \ 1302 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property), attData.permission(c_permission))); 1303 ok, data = readCharacteristic(transport, initiator, c_vhandle, trace); 1304 success = success and not ok and data == ATTError.ATT_ERROR_INSUFFICIENT_AUTHORIZATION; 1305 trace.trace(6, "Attempted to read Characteristic @ handle 0x%02X - %s" % (c_vhandle, attData.error(data))); 1306 1307 success = initiator.disconnect(0x13) and success; 1308 1309 return success; 1310 1311""" 1312 GATT/SR/GAR/BI-04-C [Insufficient Authentication error - Reading Characteristic Value] 1313""" 1314def gatt_sr_gar_bi_04_c(transport, upperTester, lowerTester, trace): 1315 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 1316 if success: 1317 sset, found, attData, gattData = 1, False, ATTData(), GATTData.instance(); 1318 """ 1319 Switch to Service Set #1 1320 """ 1321 trace.trace(6, "Switching to Service Set #%d" % sset); 1322 switch_gatt_service_set(transport, lowerTester, sset, 200); 1323 """ 1324 Collect all Characteristics that have Authenticated READ permission 1325 """ 1326 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHEN); 1327 for c_uuid, c_handle, c_property, c_permission, c_vhandle in zip(characteristics["uuid"], characteristics["handle"], \ 1328 characteristics["property"], characteristics["permission"], \ 1329 characteristics["value_handle"]): 1330 trace.trace(6, "Characteristic %s handle 0x%02X value-handle 0x%02X properties %s permissions %s" % \ 1331 (attData.uuid(c_uuid), c_handle, c_vhandle, attData.property(c_property), attData.permission(c_permission))); 1332 ok, data = readCharacteristic(transport, initiator, c_vhandle, trace); 1333 success = success and not ok and data == ATTError.ATT_ERROR_INSUFFICIENT_AUTHENTICATION; 1334 trace.trace(6, "Attempted to read Characteristic @ handle 0x%02X - %s" % (c_vhandle, attData.error(data))); 1335 found = True; 1336 1337 if not found: 1338 trace.trace(6, "Didn't find any characteristics that require Authentication for reading..."); 1339 success = success and found; 1340 1341 success = initiator.disconnect(0x13) and success; 1342 1343 return success; 1344 1345""" 1346 GATT/SR/GAR/BV-03-C [Server Reads using Characteristic UUID] 1347""" 1348def gatt_sr_gar_bv_03_c(transport, upperTester, lowerTester, trace): 1349 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1350 if success: 1351 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1352 """ 1353 Switch to Service Set #1 1354 """ 1355 trace.trace(6, "Switching to Service Set #%d" % sset); 1356 switch_gatt_service_set(transport, lowerTester, sset, 200); 1357 """ 1358 Collect a set of unique Characteristics UUIDs 1359 """ 1360 uuids = set(gattData.characteristics(sset)['uuid']); 1361 for uuid in list(uuids): 1362 s_uuid = attData.uuid(uuid); 1363 """ 1364 Select one 16-bit UUID and one 128-bit UUID 1365 """ 1366 if s_uuid == '0000B006-0000-1000-8000-00805F9B34FB' or s_uuid == '0000B009-0000-0000-0123-456789ABCDEF': 1367 trace.trace(6, "Read Characteristics matching %s" % attData.uuid(uuid)); 1368 found, characteristics = characteristicByType(transport, initiator, [ 0x0001, 0xFFFF ], uuid, True, trace); 1369 success = success and found; 1370 for c_handle, c_value in zip(characteristics["handle"], characteristics["value"]): 1371 trace.trace(6, " Characteristic %s handle 0x%02X value %s" % (attData.uuid(uuid), c_handle, formatArray(c_value))); 1372 e_value = gattData.characteristicValue(sset, c_handle-1); 1373 match = (c_value == e_value) if len(e_value) < mtuSize-3 else (c_value == e_value[:mtuSize-4]); 1374 success = success and match; 1375 trace.trace(6, " Characteristic Value Verified: %s" % success); 1376 1377 success = initiator.disconnect(0x13) and success; 1378 1379 return success; 1380 1381""" 1382 GATT/SR/GAR/BI-06-C [Read Not Permitted error - Reading Characteristic by UUID] 1383""" 1384def gatt_sr_gar_bi_06_c(transport, upperTester, lowerTester, trace): 1385 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1386 if success: 1387 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1388 """ 1389 Switch to Service Set #1 1390 """ 1391 trace.trace(6, "Switching to Service Set #%d" % sset); 1392 switch_gatt_service_set(transport, lowerTester, sset, 200); 1393 """ 1394 Filter out all Characteristics which doesn't have READ permission 1395 """ 1396 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_ANY_READ, True); 1397 for _uuid, _handle, in zip(characteristics['uuid'], characteristics['handle']): 1398 _service = gattData.serviceCovering(sset, _handle); 1399 trace.trace(6, "Read Characteristics matching %s [%d, %d]" % (attData.uuid(_uuid), _service['handles'][0], _service['handles'][1])); 1400 found, reply = characteristicByType(transport, initiator, _service['handles'], _uuid, False, trace); 1401 if found and reply['handle'] != _handle+1: 1402 continue; 1403 success = success and not found and reply['error'] == ATTError.ATT_ERROR_READ_NOT_PERMITTED; 1404 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 1405 1406 success = initiator.disconnect(0x13) and success; 1407 1408 return success; 1409 1410""" 1411 GATT/SR/GAR/BI-07-C [Attribute Not Found error - Reading Characteristic by UUID] 1412""" 1413def gatt_sr_gar_bi_07_c(transport, upperTester, lowerTester, trace): 1414 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 1415 if success: 1416 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1417 """ 1418 Switch to Service Set #1 1419 """ 1420 trace.trace(6, "Switching to Service Set #%d" % sset); 1421 switch_gatt_service_set(transport, lowerTester, sset, 200); 1422 1423 for _uuid in [ 0xB018, 0xB019 ]: 1424 trace.trace(6, "Read Characteristics matching %s [%d, %d]" % (attData.uuid(_uuid), 1, 0xFFFF)); 1425 found, reply = characteristicByType(transport, initiator, [ 0x0001, 0xFFFF ], _uuid, False, trace); 1426 success = success and not found and reply['error'] == ATTError.ATT_ERROR_ATTRIBUTE_NOT_FOUND; 1427 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 1428 1429 success = initiator.disconnect(0x13) and success; 1430 1431 return success; 1432 1433""" 1434 GATT/SR/GAR/BI-09-C [Insufficient Authorization error - Reading Using Characteristic UUID] 1435""" 1436def gatt_sr_gar_bi_09_c(transport, upperTester, lowerTester, trace): 1437 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 1438 if success: 1439 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1440 """ 1441 Switch to Service Set #1 1442 """ 1443 trace.trace(6, "Switching to Service Set #%d" % sset); 1444 switch_gatt_service_set(transport, lowerTester, sset, 200); 1445 """ 1446 Filter out all Characteristics which have READ AUTHORIZED permission 1447 """ 1448 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHOR); 1449 for _uuid, _handle, in zip(characteristics['uuid'], characteristics['handle']): 1450 trace.trace(6, "Read Characteristics matching %s [%d, %d]" % (attData.uuid(_uuid), _handle, 0xFFFF)); 1451 found, reply = characteristicByType(transport, initiator, [_handle, 0xFFFF], _uuid, False, trace); 1452 success = success and not found and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_AUTHORIZATION; 1453 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 1454 1455 success = initiator.disconnect(0x13) and success; 1456 1457 return success; 1458 1459""" 1460 GATT/SR/GAR/BI-10-C [Insufficient Authentication error - Reading Using Characteristic UUID] 1461""" 1462def gatt_sr_gar_bi_10_c(transport, upperTester, lowerTester, trace): 1463 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 1464 if success: 1465 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1466 """ 1467 Switch to Service Set #1 1468 """ 1469 trace.trace(6, "Switching to Service Set #%d" % sset); 1470 switch_gatt_service_set(transport, lowerTester, sset, 200); 1471 """ 1472 Filter out all Characteristics which have READ AUTHENTICATION permission 1473 """ 1474 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHEN); 1475 for _uuid, _handle, in zip(characteristics['uuid'], characteristics['handle']): 1476 trace.trace(6, "Read Characteristics matching %s [%d, %d]" % (attData.uuid(_uuid), _handle, 0xFFFF)); 1477 found, reply = characteristicByType(transport, initiator, [_handle, 0xFFFF], _uuid, False, trace); 1478 success = success and not found and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_AUTHENTICATION; 1479 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 1480 1481 success = initiator.disconnect(0x13) and success; 1482 1483 return success; 1484 1485""" 1486 GATT/SR/GAR/BI-11-C [Insufficient Encryption Key Size error - Reading Using Characteristic UUID] 1487""" 1488def gatt_sr_gar_bi_11_c(transport, upperTester, lowerTester, trace): 1489 success, mtuSize, initiator = preambleConnected(transport, upperTester, 512, trace); 1490 if success: 1491 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1492 """ 1493 Switch to Service Set #1 1494 """ 1495 trace.trace(6, "Switching to Service Set #%d" % sset); 1496 switch_gatt_service_set(transport, lowerTester, sset, 200); 1497 """ 1498 Filter out all Characteristics which have READ ENCRYPTED permission 1499 """ 1500 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_ENCRYPT); 1501 for _uuid, _handle, in zip(characteristics['uuid'], characteristics['handle']): 1502 trace.trace(6, "Read Characteristics matching %s [%d, %d]" % (attData.uuid(_uuid), _handle, 0xFFFF)); 1503 found, reply = characteristicByType(transport, initiator, [_handle, 0xFFFF], _uuid, False, trace); 1504 success = success and not found and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_ENCRYPTION; 1505 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 1506 1507 success = initiator.disconnect(0x13) and success; 1508 1509 return success; 1510 1511""" 1512 GATT/SR/GAR/BV-04-C [Server Reads Long Characteristic Value] 1513""" 1514def gatt_sr_gar_bv_04_c(transport, upperTester, lowerTester, trace): 1515 success, mtuSize, initiator = preambleConnected(transport, upperTester, 23, trace); 1516 if success: 1517 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1518 """ 1519 Switch to Service Set #1 1520 """ 1521 trace.trace(6, "Switching to Service Set #%d" % sset); 1522 switch_gatt_service_set(transport, lowerTester, sset, 200); 1523 """ 1524 Filter out all Characteristics which have READ permission 1525 """ 1526 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ); 1527 1528 prevSize = 513; 1529 for m,n in zip([2,2,1,0], [mtuSize//2,0,0,mtuSize//2]): 1530 _characteristics = { 'uuid': [], 'handle': [], 'value_handle': [] }; 1531 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 1532 _size = len(gattData.characteristicValue(sset, _handle)); 1533 if m*mtuSize-1+n <= _size and _size < prevSize: 1534 _characteristics['uuid'] += [ _uuid ]; 1535 _characteristics['handle'] += [ _handle ]; 1536 _characteristics['value_handle'] += [ _value_handle ]; 1537 prevSize = _size; 1538 1539 for _uuid, _handle, _value_handle in zip(_characteristics['uuid'], _characteristics['handle'], _characteristics['value_handle']): 1540 trace.trace(6, "Read Characteristic %s [#%d]" % (attData.uuid(_uuid), _handle)); 1541 found, reply = readCharacteristic(transport, initiator, _value_handle, trace); 1542 success = success and found and reply == gattData.characteristicValue(sset, _handle)[:mtuSize-1]; 1543 if found: 1544 trace.trace(6, "Data: %s" % formatArray(reply)); 1545 found, reply = readBlob(transport, initiator, _value_handle, mtuSize, trace); 1546 success = success and found and reply == gattData.characteristicValue(sset, _handle); 1547 if found: 1548 trace.trace(6, "Data: %s" % formatArray(reply)); 1549 1550 success = initiator.disconnect(0x13) and success; 1551 1552 return success; 1553 1554""" 1555 GATT/SR/GAR/BI-12-C [Read Not Permitted error - Reading Long Characteristic Value] 1556""" 1557def gatt_sr_gar_bi_12_c(transport, upperTester, lowerTester, trace): 1558 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1559 if success: 1560 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1561 """ 1562 Switch to Service Set #1 1563 """ 1564 trace.trace(6, "Switching to Service Set #%d" % sset); 1565 switch_gatt_service_set(transport, lowerTester, sset, 200); 1566 """ 1567 Filter out all Characteristics which doesn't have READ permission 1568 """ 1569 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_ANY_READ, True); 1570 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 1571 trace.trace(6, "Read Characteristic %s [#%d]" % (attData.uuid(_uuid), _handle)); 1572 found, reply = readBlob(transport, initiator, _value_handle, mtuSize, trace); 1573 success = success and not found and reply == ATTError.ATT_ERROR_READ_NOT_PERMITTED; 1574 if not found: 1575 trace.trace(6, "Reply: %s" % attData.error(reply)); 1576 1577 success = initiator.disconnect(0x13) and success; 1578 1579 return success; 1580 1581""" 1582 GATT/SR/GAR/BI-13-C [Invalid Offset error - Reading Long Characteristic Value] 1583""" 1584def gatt_sr_gar_bi_13_c(transport, upperTester, lowerTester, trace): 1585 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1586 if success: 1587 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1588 """ 1589 Switch to Service Set #1 1590 """ 1591 trace.trace(6, "Switching to Service Set #%d" % sset); 1592 switch_gatt_service_set(transport, lowerTester, sset, 200); 1593 """ 1594 Filter out all Characteristics which have READ permission 1595 """ 1596 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ); 1597 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 1598 trace.trace(6, "Read Characteristic %s [#%d]" % (attData.uuid(_uuid), _handle)); 1599 found, reply = __readBlob(transport, initiator, _value_handle, len(gattData.characteristicValue(sset, _handle))+1, trace); 1600 success = success and not found and reply['error'] == ATTError.ATT_ERROR_INVALID_OFFSET; 1601 if not found: 1602 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 1603 1604 success = initiator.disconnect(0x13) and success; 1605 1606 return success; 1607 1608""" 1609 GATT/SR/GAR/BI-14-C [Invalid Handle error - Reading Long Characteristic Value] 1610""" 1611def gatt_sr_gar_bi_14_c(transport, upperTester, lowerTester, trace): 1612 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1613 if success: 1614 sset, prevLast, attData, gattData = 1, 0, ATTData(), GATTData.instance(); 1615 """ 1616 Switch to Service Set #1 1617 """ 1618 trace.trace(6, "Switching to Service Set #%d" % sset); 1619 switch_gatt_service_set(transport, lowerTester, sset, 200); 1620 """ 1621 Collect all Services 1622 """ 1623 services = gattData.allServices(sset); 1624 for uuid, handles in zip(services["uuids"], services["handles"]): 1625 trace.trace(6, "Service %s covers [%02d, %02d]" % (attData.uuid(uuid), handles[0], handles[1])); 1626 1627 if handles[0] > (prevLast+1): 1628 trace.trace(6, "Read Blob @[#%d]" % ((handles[0] + prevLast)//2)); 1629 found, reply = __readBlob(transport, initiator, (handles[0] + prevLast)//2, 0, trace); 1630 success = success and not found and reply['error'] == ATTError.ATT_ERROR_INVALID_HANDLE; 1631 if not found: 1632 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 1633 prevLast = handles[1]; 1634 1635 success = initiator.disconnect(0x13) and success; 1636 1637 return success; 1638 1639""" 1640 GATT/SR/GAR/BI-15-C [Insufficient Authorization error - Reading Long Characteristic Value] 1641""" 1642def gatt_sr_gar_bi_15_c(transport, upperTester, lowerTester, trace): 1643 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1644 if success: 1645 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1646 """ 1647 Switch to Service Set #1 1648 """ 1649 trace.trace(6, "Switching to Service Set #%d" % sset); 1650 switch_gatt_service_set(transport, lowerTester, sset, 200); 1651 """ 1652 Collect all Characteristics that require READ AUTHORIZATION 1653 """ 1654 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHOR); 1655 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 1656 trace.trace(6, "Read Blob @[#%d]" % _value_handle); 1657 found, reply = readBlob(transport, initiator, _value_handle, mtuSize, trace); 1658 success = success and not found and (reply == ATTError.ATT_ERROR_INSUFFICIENT_AUTHORIZATION); 1659 trace.trace(6, "Reply: %s" % attData.error(reply)); 1660 1661 success = initiator.disconnect(0x13) and success; 1662 1663 return success; 1664 1665""" 1666 GATT/SR/GAR/BI-16-C [Insufficient Authentication error - Reading Long Characteristic Value] 1667""" 1668def gatt_sr_gar_bi_16_c(transport, upperTester, lowerTester, trace): 1669 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1670 if success: 1671 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1672 """ 1673 Switch to Service Set #1 1674 """ 1675 trace.trace(6, "Switching to Service Set #%d" % sset); 1676 switch_gatt_service_set(transport, lowerTester, sset, 200); 1677 """ 1678 Collect all Characteristics that require READ AUTHENTICATION 1679 """ 1680 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHEN); 1681 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 1682 trace.trace(6, "Read Blob @[#%d]" % _value_handle); 1683 found, reply = readBlob(transport, initiator, _value_handle, mtuSize, trace); 1684 success = success and not found and (reply == ATTError.ATT_ERROR_INSUFFICIENT_AUTHENTICATION); 1685 trace.trace(6, "Reply: %s" % attData.error(reply)); 1686 1687 success = initiator.disconnect(0x13) and success; 1688 1689 return success; 1690 1691""" 1692 GATT/SR/GAR/BI-17-C [Insufficient Encryption Key Size error - Reading Long Characteristic Value] 1693""" 1694def gatt_sr_gar_bi_17_c(transport, upperTester, lowerTester, trace): 1695 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1696 if success: 1697 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1698 """ 1699 Switch to Service Set #1 1700 """ 1701 trace.trace(6, "Switching to Service Set #%d" % sset); 1702 switch_gatt_service_set(transport, lowerTester, sset, 200); 1703 """ 1704 Collect all Characteristics that require READ ENCRYPTED 1705 """ 1706 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_ENCRYPT); 1707 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 1708 trace.trace(6, "Read Blob @[#%d]" % _value_handle); 1709 found, reply = readBlob(transport, initiator, _value_handle, mtuSize, trace); 1710 success = success and not found and (reply == ATTError.ATT_ERROR_INSUFFICIENT_ENCRYPTION); 1711 trace.trace(6, "Reply: %s" % attData.error(reply)); 1712 1713 success = initiator.disconnect(0x13) and success; 1714 1715 return success; 1716 1717""" 1718 GATT/SR/GAR/BV-05-C [Server Reads Multiple Characteristic Values] 1719 1720 NOTE: If the Request is fragmented - no reponse is received. 1721""" 1722def gatt_sr_gar_bv_05_c(transport, upperTester, lowerTester, trace): 1723 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 1724 if success: 1725 sset, gattData = 2, GATTData.instance(); 1726 """ 1727 Switch to Service Set #2 1728 """ 1729 trace.trace(6, "Switching to Service Set #%d" % sset); 1730 switch_gatt_service_set(transport, lowerTester, sset, 200); 1731 """ 1732 Collect all Characteristics that can be READ 1733 """ 1734 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ); 1735 _size = 0; _handles = []; _values = []; 1736 for _handle, _value_handle in zip(characteristics['handle'], characteristics['value_handle']): 1737 _value = gattData.characteristicValue(sset, _handle); 1738 if (_size + len(_value)) < (mtuSize-1): 1739 _size += len(_value); 1740 _handles += [ _value_handle ]; 1741 _values += _value; 1742 1743 trace.trace(6, "Read Multiple Characteristics @[%s]" % formatArray(_handles)); 1744 found, values = readMultipleCharacteristics(transport, initiator, _handles, trace); 1745 success = success and found and values == _values; 1746 1747 success = initiator.disconnect(0x13) and success; 1748 1749 return success; 1750 1751""" 1752 GATT/SR/GAR/BI-18-C [Read Not Permitted error - Reading Multiple Characteristic Values] 1753""" 1754def gatt_sr_gar_bi_18_c(transport, upperTester, lowerTester, trace): 1755 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1756 if success: 1757 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 1758 """ 1759 Switch to Service Set #2 1760 """ 1761 trace.trace(6, "Switching to Service Set #%d" % sset); 1762 switch_gatt_service_set(transport, lowerTester, sset, 200); 1763 """ 1764 Collect all Characteristics that can be READ 1765 """ 1766 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_ANY_READ, True); 1767 _size = 0; _handles = []; _values = []; 1768 for _handle, _value_handle in zip(characteristics['handle'], characteristics['value_handle']): 1769 _value = gattData.characteristicValue(sset, _handle); 1770 if (_size + len(_value)) < (mtuSize-1): 1771 _size += len(_value); 1772 _handles += [ _value_handle ]; 1773 _values += _value; 1774 1775 trace.trace(6, "Read Multiple Characteristics @[%s]" % formatArray(_handles)); 1776 found, values = readMultipleCharacteristics(transport, initiator, _handles, trace); 1777 success = success and not found and values == ATTError.ATT_ERROR_READ_NOT_PERMITTED; 1778 if not found: 1779 trace.trace(6, "Reply: %s" % attData.error(values)); 1780 1781 success = initiator.disconnect(0x13) and success; 1782 1783 return success; 1784 1785""" 1786 GATT/SR/GAR/BI-19-C [Invalid Handle error - Reading Multiple Characteristic Values] 1787""" 1788def gatt_sr_gar_bi_19_c(transport, upperTester, lowerTester, trace): 1789 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1790 if success: 1791 sset, prevLast, attData, gattData = 2, 0, ATTData(), GATTData.instance(); 1792 """ 1793 Switch to Service Set #2 1794 """ 1795 trace.trace(6, "Switching to Service Set #%d" % sset); 1796 switch_gatt_service_set(transport, lowerTester, sset, 200); 1797 """ 1798 Collect all Services 1799 """ 1800 services = gattData.allServices(sset); 1801 _handles = []; 1802 for handles in services["handles"]: 1803 if handles[0] > (prevLast+1): 1804 _handles += [ (handles[0] + prevLast)//2 ]; 1805 prevLast = handles[1]; 1806 1807 trace.trace(6, "Read Multiple Characteristics @[%s]" % formatArray(_handles)); 1808 found, values = readMultipleCharacteristics(transport, initiator, _handles, trace); 1809 success = success and not found and values == ATTError.ATT_ERROR_INVALID_HANDLE; 1810 if not found: 1811 trace.trace(6, "Reply: %s" % attData.error(values)); 1812 1813 success = initiator.disconnect(0x13) and success; 1814 1815 return success; 1816 1817""" 1818 GATT/SR/GAR/BI-20-C [Insufficient Authorization error - Reading Multiple Characteristic Values] 1819""" 1820def gatt_sr_gar_bi_20_c(transport, upperTester, lowerTester, trace): 1821 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1822 if success: 1823 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1824 """ 1825 Switch to Service Set #1 1826 """ 1827 trace.trace(6, "Switching to Service Set #%d" % sset); 1828 switch_gatt_service_set(transport, lowerTester, sset, 200); 1829 """ 1830 Collect all Characteristics that require READ AUTHORIZATION 1831 """ 1832 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHOR); 1833 _handles = []; 1834 for _handle, _value_handle in zip(characteristics['handle'], characteristics['value_handle']): 1835 _handles += [ _value_handle ]; 1836 1837 trace.trace(6, "Read Multiple Characteristics @[%s]" % formatArray(_handles)); 1838 found, values = readMultipleCharacteristics(transport, initiator, _handles, trace); 1839 success = success and not found and values == ATTError.ATT_ERROR_INSUFFICIENT_AUTHORIZATION; 1840 if not found: 1841 trace.trace(6, "Reply: %s" % attData.error(values)); 1842 1843 success = initiator.disconnect(0x13) and success; 1844 1845 return success; 1846 1847""" 1848 GATT/SR/GAR/BI-21-C [Insufficient Authentication error - Reading Multiple Characteristic Values] 1849""" 1850def gatt_sr_gar_bi_21_c(transport, upperTester, lowerTester, trace): 1851 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1852 if success: 1853 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1854 """ 1855 Switch to Service Set #1 1856 """ 1857 trace.trace(6, "Switching to Service Set #%d" % sset); 1858 switch_gatt_service_set(transport, lowerTester, sset, 200); 1859 """ 1860 Collect all Characteristics that require READ AUTHENTICATION 1861 """ 1862 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_AUTHEN); 1863 _handles = []; 1864 for _handle, _value_handle in zip(characteristics['handle'], characteristics['value_handle']): 1865 _handles += [ _value_handle ]; 1866 1867 trace.trace(6, "Read Multiple Characteristics @[%s]" % formatArray(_handles)); 1868 found, values = readMultipleCharacteristics(transport, initiator, _handles, trace); 1869 success = success and not found and values == ATTError.ATT_ERROR_INSUFFICIENT_AUTHENTICATION; 1870 if not found: 1871 trace.trace(6, "Reply: %s" % attData.error(values)); 1872 1873 success = initiator.disconnect(0x13) and success; 1874 1875 return success; 1876 1877""" 1878 GATT/SR/GAR/BI-22-C [Insufficient Encryption Key Size error - Reading Multiple Characteristic Values] 1879""" 1880def gatt_sr_gar_bi_22_c(transport, upperTester, lowerTester, trace): 1881 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1882 if success: 1883 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1884 """ 1885 Switch to Service Set #1 1886 """ 1887 trace.trace(6, "Switching to Service Set #%d" % sset); 1888 switch_gatt_service_set(transport, lowerTester, sset, 200); 1889 """ 1890 Collect all Characteristics that require READ ENCRYPTED 1891 """ 1892 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_READ_ENCRYPT); 1893 _handles = []; 1894 for _handle, _value_handle in zip(characteristics['handle'], characteristics['value_handle']): 1895 _handles += [ _value_handle ]; 1896 1897 trace.trace(6, "Read Multiple Characteristics @[%s]" % formatArray(_handles)); 1898 found, values = readMultipleCharacteristics(transport, initiator, _handles, trace); 1899 success = success and not found and values == ATTError.ATT_ERROR_INSUFFICIENT_ENCRYPTION; 1900 if not found: 1901 trace.trace(6, "Reply: %s" % attData.error(values)); 1902 1903 success = initiator.disconnect(0x13) and success; 1904 1905 return success; 1906 1907""" 1908 GATT/SR/GAR/BV-06-C [Server Reads Characteristic Descriptors] 1909""" 1910def gatt_sr_gar_bv_06_c(transport, upperTester, lowerTester, trace): 1911 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 1912 if success: 1913 sset, gattData = 1, GATTData.instance(); 1914 """ 1915 Switch to Service Set #1 1916 """ 1917 trace.trace(6, "Switching to Service Set #%d" % sset); 1918 switch_gatt_service_set(transport, lowerTester, sset, 200); 1919 """ 1920 Collect all Descriptors that have READ access 1921 """ 1922 descriptors = gattData.descriptors(sset, None, ATTPermission.ATT_PERM_READ); 1923 for _handle in descriptors['handle']: 1924 trace.trace(6, "Read Descriptor @[#%d]" % _handle); 1925 success, data = readCharacteristic(transport, initiator, _handle, trace); 1926 trace.trace(6, "Descriptor Value: %s" % formatArray(data)); 1927 match = data == gattData.descriptorValue(sset, _handle); 1928 if not match: 1929 trace.trace(6, " GATT Database Value: %s" % formatArray(gattData.descriptorValue(sset, _handle))); 1930 success = success and match; 1931 1932 success = initiator.disconnect(0x13) and success; 1933 1934 return success; 1935 1936""" 1937 GATT/SR/GAR/BV-07-C [Server Reads Long Characteristic Descriptor] 1938""" 1939def gatt_sr_gar_bv_07_c(transport, upperTester, lowerTester, trace): 1940 success, mtuSize, initiator = preambleConnected(transport, upperTester, 23, trace); 1941 if success: 1942 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 1943 """ 1944 Switch to Service Set #1 1945 """ 1946 trace.trace(6, "Switching to Service Set #%d" % sset); 1947 switch_gatt_service_set(transport, lowerTester, sset, 200); 1948 """ 1949 Collect all Descriptors that have READ access 1950 """ 1951 descriptors = gattData.descriptors(sset, None, ATTPermission.ATT_PERM_READ); 1952 prevSize = 513; 1953 for m,n in zip([2,2,1,0], [mtuSize/2,0,0,mtuSize/2]): 1954 _descriptors = { 'uuid': [], 'handle': [] }; 1955 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 1956 _size = len(gattData.descriptorValue(sset, _handle)); 1957 if m*mtuSize-1+n <= _size and _size < prevSize: 1958 _descriptors['uuid'] += [ _uuid ]; 1959 _descriptors['handle'] += [ _handle ]; 1960 prevSize = _size; 1961 1962 for _uuid, _handle in zip(_descriptors['uuid'], _descriptors['handle']): 1963 trace.trace(6, "Read Descriptor %s [#%d]" % (attData.uuid(_uuid), _handle)); 1964 found, reply = readCharacteristic(transport, initiator, _handle, trace); 1965 success = success and found and reply == gattData.descriptorValue(sset, _handle)[:mtuSize-1]; 1966 if found: 1967 trace.trace(6, "Data: %s" % formatArray(reply)); 1968 found, reply = readBlob(transport, initiator, _handle, mtuSize, trace); 1969 success = success and found and reply == gattData.descriptorValue(sset, _handle); 1970 if found: 1971 trace.trace(6, "Data: %s" % formatArray(reply)); 1972 1973 success = initiator.disconnect(0x13) and success; 1974 1975 return success; 1976 1977""" 1978 GATT/SR/GAW/BV-01-C [Server Writes Without Response] 1979""" 1980def gatt_sr_gaw_bv_01_c(transport, upperTester, lowerTester, trace): 1981 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 1982 if success: 1983 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 1984 """ 1985 Switch to Service Set #2 1986 """ 1987 trace.trace(6, "Switching to Service Set #%d" % sset); 1988 switch_gatt_service_set(transport, lowerTester, sset, 200); 1989 """ 1990 Collect all Characteristics that have WRITE access 1991 """ 1992 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE); 1993 for _uuid, _handle, _value_handle, _permission in zip(characteristics['uuid'], characteristics['handle'], \ 1994 characteristics['value_handle'], characteristics['permission']): 1995 _value = gattData.characteristicValue(sset, _handle); 1996 if 1 < len(_value) and len(_value) < mtuSize-4: 1997 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 1998 ok, reply = writeNoResponse(transport, initiator, _value_handle, _value[::-1], trace); 1999 success = success and ok; 2000 if not ok: 2001 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2002 else: 2003 if (_permission & ATTPermission.ATT_PERM_READ) == ATTPermission.ATT_PERM_READ: 2004 ok, value = readCharacteristic(transport, initiator, _value_handle, trace); 2005 success = success and ok and value == _value[::-1]; 2006 trace.trace(6, "Write Verified: %s" % success); 2007 if _value != _value[::-1]: 2008 ok, reply = writeNoResponse(transport, initiator, _value_handle, _value, trace); 2009 success = success and ok; 2010 2011 success = initiator.disconnect(0x13) and success; 2012 2013 return success; 2014 2015""" 2016 GATT/SR/GAW/BV-03-C [Server Writes Characteristic Value] 2017""" 2018def gatt_sr_gaw_bv_03_c(transport, upperTester, lowerTester, trace): 2019 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2020 if success: 2021 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 2022 """ 2023 Switch to Service Set #2 2024 """ 2025 trace.trace(6, "Switching to Service Set #%d" % sset); 2026 switch_gatt_service_set(transport, lowerTester, sset, 200); 2027 """ 2028 Collect all Characteristics that have WRITE access 2029 """ 2030 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE); 2031 for _uuid, _handle, _value_handle, _permission in zip(characteristics['uuid'], characteristics['handle'], \ 2032 characteristics['value_handle'], characteristics['permission']): 2033 _value = gattData.characteristicValue(sset, _handle); 2034 if 2 < len(_value) and len(_value) < mtuSize-4: 2035 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2036 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value[::-1], trace); 2037 success = success and ok; 2038 if not ok: 2039 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2040 else: 2041 if (_permission & ATTPermission.ATT_PERM_READ) == ATTPermission.ATT_PERM_READ: 2042 ok, value = readCharacteristic(transport, initiator, _value_handle, trace); 2043 success = success and ok and value == _value[::-1]; 2044 trace.trace(6, "Write Verified: %s" % success); 2045 if _value != _value[::-1]: 2046 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value, trace); 2047 success = success and ok; 2048 2049 success = initiator.disconnect(0x13) and success; 2050 2051 return success; 2052 2053""" 2054 GATT/SR/GAW/BI-02-C [Invalid Handle error - Writing Characteristic Value] 2055""" 2056def gatt_sr_gaw_bi_02_c(transport, upperTester, lowerTester, trace): 2057 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2058 if success: 2059 sset, prevLast, attData, gattData = 2, 0, ATTData(), GATTData.instance(); 2060 """ 2061 Switch to Service Set #2 2062 """ 2063 trace.trace(6, "Switching to Service Set #%d" % sset); 2064 switch_gatt_service_set(transport, lowerTester, sset, 200); 2065 """ 2066 Collect all Services 2067 """ 2068 services = gattData.allServices(sset); 2069 for uuid, handles in zip(services["uuids"], services["handles"]): 2070 trace.trace(6, "Service %s covers [%02d, %02d]" % (attData.uuid(uuid), handles[0], handles[1])); 2071 2072 if handles[0] > (prevLast+1): 2073 trace.trace(6, "Write Characteristic @[#%d]" % ((handles[0] + prevLast)//2)); 2074 ok, reply = writeCharacteristic(transport, initiator, (handles[0] + prevLast)//2, [ 0x00 ], trace); 2075 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INVALID_HANDLE; 2076 if not ok: 2077 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2078 prevLast = handles[1]; 2079 2080 success = initiator.disconnect(0x13) and success; 2081 2082 return success; 2083 2084""" 2085 GATT/SR/GAW/BI-03-C [Write Not Permitted error - Writing Characteristic Value] 2086""" 2087def gatt_sr_gaw_bi_03_c(transport, upperTester, lowerTester, trace): 2088 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2089 if success: 2090 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2091 """ 2092 Switch to Service Set #1 2093 """ 2094 trace.trace(6, "Switching to Service Set #%d" % sset); 2095 switch_gatt_service_set(transport, lowerTester, sset, 200); 2096 """ 2097 Collect all Characteristics that doesn't allow WRITE access 2098 """ 2099 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_ANY_WRITE, True); 2100 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2101 _value = gattData.characteristicValue(sset, _handle); 2102 if len(_value) < mtuSize-4: 2103 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2104 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value[::-1], trace); 2105 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_WRITE_NOT_PERMITTED; 2106 if not ok: 2107 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2108 2109 success = initiator.disconnect(0x13) and success; 2110 2111 return success; 2112 2113""" 2114 GATT/SR/GAW/BI-04-C [Insufficient Authorization error - Writing Characteristic Value] 2115""" 2116def gatt_sr_gaw_bi_04_c(transport, upperTester, lowerTester, trace): 2117 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2118 if success: 2119 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2120 """ 2121 Switch to Service Set #1 2122 """ 2123 trace.trace(6, "Switching to Service Set #%d" % sset); 2124 switch_gatt_service_set(transport, lowerTester, sset, 200); 2125 """ 2126 Collect all Characteristics that require WRITE Authorization 2127 """ 2128 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE_AUTHOR); 2129 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2130 _value = gattData.characteristicValue(sset, _handle); 2131 if len(_value) < mtuSize-4: 2132 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2133 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value[::-1], trace); 2134 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_AUTHORIZATION; 2135 if not ok: 2136 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2137 else: 2138 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value, trace); 2139 2140 success = initiator.disconnect(0x13) and success; 2141 2142 return success; 2143 2144""" 2145 GATT/SR/GAW/BI-05-C [Insufficient Authentication error - Writing Characteristic Value] 2146""" 2147def gatt_sr_gaw_bi_05_c(transport, upperTester, lowerTester, trace): 2148 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2149 if success: 2150 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2151 """ 2152 Switch to Service Set #1 2153 """ 2154 trace.trace(6, "Switching to Service Set #%d" % sset); 2155 switch_gatt_service_set(transport, lowerTester, sset, 200); 2156 """ 2157 Collect all Characteristics that require WRITE Authentication 2158 """ 2159 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE_AUTHEN); 2160 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2161 _value = gattData.characteristicValue(sset, _handle); 2162 if len(_value) < mtuSize-4: 2163 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2164 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value[::-1], trace); 2165 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_AUTHENTICATION; 2166 if not ok: 2167 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2168 else: 2169 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value, trace); 2170 2171 success = initiator.disconnect(0x13) and success; 2172 2173 return success; 2174 2175""" 2176 GATT/SR/GAW/BI-06-C [Insufficient Encryption Key Size error - Writing Characteristic Value] 2177""" 2178def gatt_sr_gaw_bi_06_c(transport, upperTester, lowerTester, trace): 2179 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2180 if success: 2181 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2182 """ 2183 Switch to Service Set #1 2184 """ 2185 trace.trace(6, "Switching to Service Set #%d" % sset); 2186 switch_gatt_service_set(transport, lowerTester, sset, 200); 2187 """ 2188 Collect all Characteristics that require WRITE Authentication 2189 """ 2190 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE_ENCRYPT); 2191 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2192 _value = gattData.characteristicValue(sset, _handle); 2193 if len(_value) < mtuSize-4: 2194 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2195 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value[::-1], trace); 2196 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_ENCRYPTION; 2197 if not ok: 2198 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2199 else: 2200 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value, trace); 2201 2202 success = initiator.disconnect(0x13) and success; 2203 2204 return success; 2205 2206""" 2207 GATT/SR/GAW/BV-05-C [Server Writes Long Characteristic Value] 2208 2209 NOTE: Attempting to execute this test with an MTU size of 23 bytes will fail with an error ATT_ERROR_PREPARE_QUEUE_FULL. 2210""" 2211def gatt_sr_gaw_bv_05_c(transport, upperTester, lowerTester, trace): 2212 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2213 if success: 2214 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 2215 """ 2216 Switch to Service Set #2 2217 """ 2218 trace.trace(6, "Switching to Service Set #%d" % sset); 2219 switch_gatt_service_set(transport, lowerTester, sset, 200); 2220 """ 2221 Collect all Characteristics that have WRITE access 2222 """ 2223 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE); 2224 for _uuid, _handle, _value_handle, _permission in zip(characteristics['uuid'], characteristics['handle'], \ 2225 characteristics['value_handle'], characteristics['permission']): 2226 _value = gattData.characteristicValue(sset, _handle); 2227 if len(_value) > mtuSize-5: 2228 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2229 ok, reply = writeLong(transport, initiator, _value_handle, _value[::-1], mtuSize, trace); 2230 success = success and ok; 2231 if not ok: 2232 trace.trace(6, "Write Long failed: %s" % attData.error(reply['error'])); 2233 else: 2234 if (_permission & ATTPermission.ATT_PERM_READ) == ATTPermission.ATT_PERM_READ: 2235 ok, value = readBlob(transport, initiator, _value_handle, mtuSize, trace); 2236 success = success and ok and value == _value[::-1]; 2237 trace.trace(6, "Write Verified: %s" % success); 2238 if _value != _value[::-1]: 2239 ok, reply = writeLong(transport, initiator, _value_handle, _value, mtuSize, trace); 2240 success = success and ok; 2241 2242 success = initiator.disconnect(0x13) and success; 2243 2244 return success; 2245 2246""" 2247 GATT/SR/GAW/BI-07-C [Invalid Handle error - Writing Long Characteristic Value] 2248""" 2249def gatt_sr_gaw_bi_07_c(transport, upperTester, lowerTester, trace): 2250 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2251 if success: 2252 sset, prevLast, attData, gattData = 2, 0, ATTData(), GATTData.instance(); 2253 """ 2254 Switch to Service Set #2 2255 """ 2256 trace.trace(6, "Switching to Service Set #%d" % sset); 2257 switch_gatt_service_set(transport, lowerTester, sset, 200); 2258 """ 2259 Collect all Services 2260 """ 2261 services = gattData.allServices(sset); 2262 for uuid, handles in zip(services["uuids"], services["handles"]): 2263 trace.trace(6, "Service %s covers [%02d, %02d]" % (attData.uuid(uuid), handles[0], handles[1])); 2264 2265 if handles[0] > (prevLast+1): 2266 trace.trace(6, "Write Long Characteristic @[#%d]" % ((handles[0] + prevLast)//2)); 2267 ok, reply = writeLong(transport, initiator, (handles[0] + prevLast)//2, [ 0x00 ], mtuSize, trace); 2268 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INVALID_HANDLE; 2269 if not ok: 2270 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2271 prevLast = handles[1]; 2272 2273 success = initiator.disconnect(0x13) and success; 2274 2275 return success; 2276 2277""" 2278 GATT/SR/GAW/BI-08-C [Write Not Permitted error - Writing Long Characteristic Value] 2279""" 2280def gatt_sr_gaw_bi_08_c(transport, upperTester, lowerTester, trace): 2281 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2282 if success: 2283 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2284 """ 2285 Switch to Service Set #1 2286 """ 2287 trace.trace(6, "Switching to Service Set #%d" % sset); 2288 switch_gatt_service_set(transport, lowerTester, sset, 200); 2289 """ 2290 Collect all Characteristics that doesn't allow WRITE access 2291 """ 2292 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_ANY_WRITE, True); 2293 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2294 _value = gattData.characteristicValue(sset, _handle); 2295 if len(_value) > mtuSize-5: 2296 trace.trace(6, "Write Long Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2297 ok, reply = writeLong(transport, initiator, _value_handle, _value[::-1], mtuSize, trace); 2298 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_WRITE_NOT_PERMITTED; 2299 if not ok: 2300 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2301 else: 2302 ok, reply = writeLong(transport, initiator, _value_handle, _value, mtuSize, trace); 2303 2304 success = initiator.disconnect(0x13) and success; 2305 2306 return success; 2307 2308""" 2309 GATT/SR/GAW/BI-09-C [Invalid Offset error - Writing Long Characteristic Value] 2310""" 2311def gatt_sr_gaw_bi_09_c(transport, upperTester, lowerTester, trace): 2312 success, mtuSize, initiator = preambleConnected(transport, upperTester, 43, trace); 2313 if success: 2314 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 2315 """ 2316 Switch to Service Set #2 2317 """ 2318 trace.trace(6, "Switching to Service Set #%d" % sset); 2319 switch_gatt_service_set(transport, lowerTester, sset, 200); 2320 """ 2321 Filter out all Characteristics which have WRITE permission 2322 """ 2323 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE); 2324 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2325 _value = gattData.characteristicValue(sset, _handle); 2326 if len(_value) > mtuSize-5: 2327 trace.trace(6, "Write Long Characteristic %s [#%d]" % (attData.uuid(_uuid), _handle)); 2328 ok, reply = __writeLong(transport, initiator, _value_handle, [ 0x00 ], len(_value)+1, trace); 2329 success = success and ok; 2330 if not ok: 2331 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 2332 else: 2333 ok, reply = __writeExecute(transport, initiator, trace); 2334 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INVALID_OFFSET; 2335 if not ok: 2336 trace.trace(6, "Reply: %s" % attData.error(reply['error'])); 2337 2338 success = initiator.disconnect(0x13) and success; 2339 2340 return success; 2341 2342""" 2343 GATT/SR/GAW/BI-11-C [Insufficient Authorization error - Writing Long Characteristic Value] 2344""" 2345def gatt_sr_gaw_bi_11_c(transport, upperTester, lowerTester, trace): 2346 success, mtuSize, initiator = preambleConnected(transport, upperTester, 43, trace); 2347 if success: 2348 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2349 """ 2350 Switch to Service Set #1 2351 """ 2352 trace.trace(6, "Switching to Service Set #%d" % sset); 2353 switch_gatt_service_set(transport, lowerTester, sset, 200); 2354 """ 2355 Collect all Characteristics that require WRITE Authorization 2356 """ 2357 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE_AUTHOR); 2358 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2359 _value = gattData.characteristicValue(sset, _handle); 2360 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2361 ok, reply = writeLong(transport, initiator, _value_handle, _value[::-1], mtuSize, trace); 2362 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_AUTHORIZATION; 2363 if not ok: 2364 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2365 else: 2366 ok, reply = writeLong(transport, initiator, _value_handle, _value, mtuSize, trace); 2367 2368 success = initiator.disconnect(0x13) and success; 2369 2370 return success; 2371 2372""" 2373 GATT/SR/GAW/BI-12-C [Insufficient Authentication error - Writing Long Characteristic Value] 2374""" 2375def gatt_sr_gaw_bi_12_c(transport, upperTester, lowerTester, trace): 2376 success, mtuSize, initiator = preambleConnected(transport, upperTester, 43, trace); 2377 if success: 2378 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2379 """ 2380 Switch to Service Set #1 2381 """ 2382 trace.trace(6, "Switching to Service Set #%d" % sset); 2383 switch_gatt_service_set(transport, lowerTester, sset, 200); 2384 """ 2385 Collect all Characteristics that require WRITE Authentication 2386 """ 2387 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE_AUTHEN); 2388 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2389 _value = gattData.characteristicValue(sset, _handle); 2390 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2391 ok, reply = writeLong(transport, initiator, _value_handle, _value[::-1], mtuSize, trace); 2392 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_AUTHENTICATION; 2393 if not ok: 2394 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2395 else: 2396 ok, reply = writeLong(transport, initiator, _value_handle, _value, mtuSize, trace); 2397 2398 success = initiator.disconnect(0x13) and success; 2399 2400 return success; 2401 2402""" 2403 GATT/SR/GAW/BI-13-C [Insufficient Encryption Key Size error - Writing Long Characteristic Value] 2404""" 2405def gatt_sr_gaw_bi_13_c(transport, upperTester, lowerTester, trace): 2406 success, mtuSize, initiator = preambleConnected(transport, upperTester, 43, trace); 2407 if success: 2408 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2409 """ 2410 Switch to Service Set #1 2411 """ 2412 trace.trace(6, "Switching to Service Set #%d" % sset); 2413 switch_gatt_service_set(transport, lowerTester, sset, 200); 2414 """ 2415 Collect all Characteristics that require WRITE Authentication 2416 """ 2417 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE_ENCRYPT); 2418 for _uuid, _handle, _value_handle in zip(characteristics['uuid'], characteristics['handle'], characteristics['value_handle']): 2419 _value = gattData.characteristicValue(sset, _handle); 2420 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2421 ok, reply = writeLong(transport, initiator, _value_handle, _value[::-1], mtuSize, trace); 2422 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INSUFFICIENT_ENCRYPTION; 2423 if not ok: 2424 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2425 else: 2426 ok, reply = writeLong(transport, initiator, _value_handle, _value, mtuSize, trace); 2427 2428 success = initiator.disconnect(0x13) and success; 2429 2430 return success; 2431 2432""" 2433 GATT/SR/GAW/BV-08-C [Server Writes Characteristic Descriptors] 2434""" 2435def gatt_sr_gaw_bv_08_c(transport, upperTester, lowerTester, trace): 2436 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2437 if success: 2438 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2439 """ 2440 Switch to Service Set #1 2441 """ 2442 trace.trace(6, "Switching to Service Set #%d" % sset); 2443 switch_gatt_service_set(transport, lowerTester, sset, 200); 2444 """ 2445 Collect all Descriptors that have WRITE access 2446 """ 2447 descriptors = gattData.descriptors(sset, None, ATTPermission.ATT_PERM_WRITE); 2448 for _handle in descriptors['handle']: 2449 _value = gattData.descriptorValue(sset, _handle); 2450 if len(_value) < mtuSize-3: 2451 trace.trace(6, "Write Descriptor @[#%d]" % _handle); 2452 ok, reply = writeCharacteristic(transport, initiator, _handle, _value[::-1], trace); 2453 success = success and ok; 2454 if not ok: 2455 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2456 else: 2457 ok, reply = writeCharacteristic(transport, initiator, _handle, _value, trace); 2458 success = success and ok; 2459 2460 success = initiator.disconnect(0x13) and success; 2461 2462 return success; 2463 2464""" 2465 GATT/SR/GAW/BV-09-C [Server Writes Long Characteristic Descriptors] 2466""" 2467def gatt_sr_gaw_bv_09_c(transport, upperTester, lowerTester, trace): 2468 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2469 if success: 2470 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2471 """ 2472 Switch to Service Set #1 2473 """ 2474 trace.trace(6, "Switching to Service Set #%d" % sset); 2475 switch_gatt_service_set(transport, lowerTester, sset, 200); 2476 """ 2477 Collect all Descriptors that have WRITE access 2478 """ 2479 descriptors = gattData.descriptors(sset, None, ATTPermission.ATT_PERM_WRITE); 2480 for _handle in descriptors['handle']: 2481 _value = gattData.descriptorValue(sset, _handle); 2482 if len(_value) > mtuSize-5: 2483 trace.trace(6, "Write Descriptor @[#%d]" % _handle); 2484 ok, reply = writeLong(transport, initiator, _handle, _value[::-1], mtuSize, trace); 2485 success = success and ok; 2486 if not ok: 2487 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2488 else: 2489 ok, reply = writeLong(transport, initiator, _handle, _value, mtuSize, trace); 2490 success = success and ok; 2491 2492 success = initiator.disconnect(0x13) and success; 2493 2494 return success; 2495 2496""" 2497 GATT/SR/GAW/BV-11-C [No Pending Prepared Write Requests error - Characteristic Value Reliable Writes] 2498""" 2499def gatt_sr_gaw_bv_11_c(transport, upperTester, lowerTester, trace): 2500 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2501 if success: 2502 sset = 1; 2503 """ 2504 Switch to Service Set #1 2505 """ 2506 trace.trace(6, "Switching to Service Set #%d" % sset); 2507 switch_gatt_service_set(transport, lowerTester, sset, 200); 2508 """ 2509 Issue a WRITE EXECUTE command without any pending PREPARED WRITES 2510 """ 2511 ok, reply = __writeExecute(transport, initiator, trace); 2512 success = success and ok; 2513 2514 success = initiator.disconnect(0x13) and success; 2515 2516 return success; 2517 2518""" 2519 GATT/SR/GAW/BI-32-C [Invalid Attribute Value Length error - Writing Characteristic Value] 2520""" 2521def gatt_sr_gaw_bi_32_c(transport, upperTester, lowerTester, trace): 2522 success, mtuSize, initiator = preambleConnected(transport, upperTester, 92, trace); 2523 if success: 2524 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2525 """ 2526 Switch to Service Set #1 2527 """ 2528 trace.trace(6, "Switching to Service Set #%d" % sset); 2529 switch_gatt_service_set(transport, lowerTester, sset, 200); 2530 """ 2531 Collect all Characteristics that have WRITE access 2532 """ 2533 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE); 2534 for _uuid, _handle, _value_handle, _permission in zip(characteristics['uuid'], characteristics['handle'], \ 2535 characteristics['value_handle'], characteristics['permission']): 2536 _value = gattData.characteristicValue(sset, _handle); 2537 if 4 < len(_value) and len(_value) < mtuSize-6: 2538 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2539 ok, reply = writeCharacteristic(transport, initiator, _value_handle, _value + [ 0x00, 0x00 ], trace); 2540 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH; 2541 if not ok: 2542 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2543 2544 success = initiator.disconnect(0x13) and success; 2545 2546 return success; 2547 2548""" 2549 GATT/SR/GAW/BI-33-C [Invalid Attribute Value Length error - Writing Long Characteristic Value] 2550""" 2551def gatt_sr_gaw_bi_33_c(transport, upperTester, lowerTester, trace): 2552 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2553 if success: 2554 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 2555 """ 2556 Switch to Service Set #2 2557 """ 2558 trace.trace(6, "Switching to Service Set #%d" % sset); 2559 switch_gatt_service_set(transport, lowerTester, sset, 200); 2560 """ 2561 Collect all Characteristics that have WRITE access 2562 """ 2563 characteristics = gattData.characteristics(sset, None, ATTPermission.ATT_PERM_WRITE); 2564 for _uuid, _handle, _value_handle, _permission in zip(characteristics['uuid'], characteristics['handle'], \ 2565 characteristics['value_handle'], characteristics['permission']): 2566 _value = gattData.characteristicValue(sset, _handle); 2567 if len(_value) > mtuSize-5: 2568 trace.trace(6, "Write Characteristic %s [#%d]" % (attData.uuid(_uuid), _value_handle)); 2569 ok, reply = writeLong(transport, initiator, _value_handle, _value + [ 0x00, 0x00 ], mtuSize, trace); 2570 success = success and not ok and reply['error'] == ATTError.ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH; 2571 if not ok: 2572 trace.trace(6, "Write failed: %s" % attData.error(reply['error'])); 2573 2574 success = initiator.disconnect(0x13) and success; 2575 2576 return success; 2577 2578""" 2579 GATT/SR/GAN/BV-01-C [Server generates Characteristic Value Notification] 2580""" 2581def gatt_sr_gan_bv_01_c(transport, upperTester, lowerTester, trace): 2582 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2583 if success: 2584 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2585 """ 2586 Switch to Service Set #1 2587 """ 2588 trace.trace(6, "Switching to Service Set #%d" % sset); 2589 switch_gatt_service_set(transport, lowerTester, sset, 200); 2590 """ 2591 Collect all Descriptors that have WRITE access 2592 """ 2593 descriptors = gattData.descriptors(sset, None, ATTPermission.ATT_PERM_WRITE); 2594 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 2595 if _uuid == 0x2902 and _handle >= 16: 2596 trace.trace(7, "Descriptor %s @[#%d]" %(attData.uuid(_uuid), _handle)); 2597 ok, reply = writeCharacteristic(transport, initiator, _handle, [ 0x01, 0x00 ], trace); 2598 success = success and ok; 2599 if success: 2600 gatt_service_notify(transport, lowerTester, 100); 2601 ok, reply = notification(transport, initiator, trace); 2602 success = success and ok; 2603 if ok: 2604 trace.trace(7, "Notification @[#%d] %s" %(reply['handle'], formatArray(reply['value']))); 2605 ok, reply = writeCharacteristic(transport, initiator, _handle, [ 0x00, 0x00 ], trace); 2606 success = success and ok; 2607 2608 success = initiator.disconnect(0x13) and success; 2609 2610 return success; 2611 2612""" 2613 GATT/SR/GAI/BV-01-C [Server generates Characteristic Value Indication] 2614""" 2615def gatt_sr_gai_bv_01_c(transport, upperTester, lowerTester, trace): 2616 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2617 if success: 2618 sset, attData, gattData = 2, ATTData(), GATTData.instance(); 2619 """ 2620 Switch to Service Set #2 2621 """ 2622 trace.trace(6, "Switching to Service Set #%d" % sset); 2623 switch_gatt_service_set(transport, lowerTester, sset, 200); 2624 """ 2625 Collect all Descriptors that have WRITE access 2626 """ 2627 descriptors = gattData.descriptors(sset, None, ATTPermission.ATT_PERM_WRITE); 2628 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 2629 if _uuid == 0x2902 and _handle >= 16: 2630 trace.trace(7, "Descriptor %s @[#%d]" %(attData.uuid(_uuid), _handle)); 2631 ok, reply = writeCharacteristic(transport, initiator, _handle, [ 0x02, 0x00 ], trace); 2632 success = success and ok; 2633 if success: 2634 gatt_service_indicate(transport, lowerTester, 100); 2635 ok, reply = indication(transport, initiator, trace); 2636 success = success and ok; 2637 if ok: 2638 trace.trace(7, "Indication @[#%d] %s" %(reply['handle'], formatArray(reply['value']))); 2639 ok, reply = writeCharacteristic(transport, initiator, _handle, [ 0x00, 0x00 ], trace); 2640 success = success and ok; 2641 2642 success = initiator.disconnect(0x13) and success; 2643 2644 return success; 2645 2646""" 2647 GATT/SR/GAS/BV-01-C [Server accepts Service Changed Characteristic Indication] 2648""" 2649def gatt_sr_gas_bv_01_c(transport, upperTester, lowerTester, trace): 2650 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2651 if success: 2652 sset, attData, gattData = 1, ATTData(), GATTData.instance(); 2653 """ 2654 Switch to Service Set #1 2655 """ 2656 trace.trace(6, "Switching to Service Set #%d" % sset); 2657 switch_gatt_service_set(transport, lowerTester, sset, 200); 2658 """ 2659 Collect all Descriptors that have WRITE access 2660 """ 2661 descriptors = gattData.descriptors(sset, None, ATTPermission.ATT_PERM_WRITE); 2662 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 2663 if _uuid == 0x2902 and _handle < 16: 2664 trace.trace(7, "Descriptor %s @[#%d]" %(attData.uuid(_uuid), _handle)); 2665 ok, reply = writeCharacteristic(transport, initiator, _handle, [ 0x02, 0x00 ], trace); 2666 success = success and ok; 2667 if success: 2668 sset = 2; 2669 """ 2670 Switch to Service Set #2 2671 """ 2672 trace.trace(6, "Switching to Service Set #%d" % sset); 2673 switch_gatt_service_set(transport, lowerTester, sset, 200); 2674 ok, reply = indication(transport, initiator, trace); 2675 success = success and ok; 2676 if ok: 2677 trace.trace(7, "Indication @[#%d] %s" %(reply['handle'], formatArray(reply['value']))); 2678 ok, reply = writeCharacteristic(transport, initiator, _handle, [ 0x00, 0x00 ], trace); 2679 success = success and ok; 2680 2681 success = initiator.disconnect(0x13) and success; 2682 2683 return success; 2684 2685""" 2686 GATT/SR/UNS/BI-01-C [Server sends Unsupported ATT Requests] 2687""" 2688def gatt_sr_uns_bi_01_c(transport, upperTester, lowerTester, trace): 2689 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2690 if success: 2691 attData = ATTData(); 2692 """ 2693 Generate an Invalid ATT Request 2694 """ 2695 txData = attData.encode( ATTOpcode.ATT_INVALID_REQUEST, [ random.randint(0,255) for _ in range(mtuSize-4) ] ); 2696 trace.trace(7, str(attData)); 2697 success = attRequest( transport, initiator, txData, trace ); 2698 if success: 2699 success, rxData = attResponse( transport, initiator, trace ); 2700 if success: 2701 reply = attData.decode( rxData ); 2702 trace.trace(7, str(attData)); 2703 success = reply['opcode'] == ATTOpcode.ATT_ERROR_RESPONSE; 2704 if success: 2705 success = reply['error'] == ATTError.ATT_ERROR_REQUEST_NOT_SUPPORTED; 2706 2707 success = initiator.disconnect(0x13) and success; 2708 2709 return success; 2710 2711""" 2712 GATT/SR/UNS/BI-02-C [Server sends Unsupported ATT Commands] 2713""" 2714def gatt_sr_uns_bi_02_c(transport, upperTester, lowerTester, trace): 2715 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2716 if success: 2717 attData = ATTData(); 2718 """ 2719 Generate an Invalid ATT Command 2720 """ 2721 txData = attData.encode( ATTOpcode.ATT_INVALID_COMMAND, [ random.randint(0,255) for _ in range(mtuSize-4) ] ); 2722 trace.trace(7, str(attData)); 2723 success = attRequest( transport, initiator, txData, trace ); 2724 if success: 2725 success, rxData = attResponse( transport, initiator, trace ); 2726 if success: 2727 reply = attData.decode( rxData ); 2728 trace.trace(7, str(attData)); 2729 success = not success; 2730 2731 success = initiator.disconnect(0x13) and success; 2732 2733 return success; 2734 2735""" 2736 GATT/SR/GPA/BV-01-C [Server Reads Primary Service Declaration] 2737""" 2738def gatt_sr_gpa_bv_01_c(transport, upperTester, lowerTester, trace): 2739 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2740 if success: 2741 attData, gattData = ATTData(), GATTData.instance(); 2742 2743 for sset in range(4): 2744 """ 2745 Switching Service Set 2746 """ 2747 trace.trace(6, "Switching to Service Set #%d" % sset); 2748 switch_gatt_service_set(transport, lowerTester, sset, 200); 2749 """ 2750 Discover all Primary Services 2751 """ 2752 ok, services = discoverPrimaryServices(transport, initiator, trace); 2753 if ok: 2754 for _uuid, _handles in zip(services["uuids"], services["handles"]): 2755 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(_uuid), _handles[0], _handles[1])); 2756 ok = services == gattData.primaryServices(sset) 2757 trace.trace(6, "Verified Service Set: %s" % ok); 2758 else: 2759 trace.trace(6, "Unable to discover Primary Services!"); 2760 success = success and ok; 2761 2762 success = initiator.disconnect(0x13) and success; 2763 2764 return success; 2765 2766""" 2767 GATT/SR/GPA/BV-02-C [Server Reads Secondary Service Declaration] 2768""" 2769def gatt_sr_gpa_bv_02_c(transport, upperTester, lowerTester, trace): 2770 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2771 if success: 2772 attData, gattData = ATTData(), GATTData.instance(); 2773 2774 for sset in range(4): 2775 """ 2776 Switching Service Set 2777 """ 2778 trace.trace(6, "Switching to Service Set #%d" % sset); 2779 switch_gatt_service_set(transport, lowerTester, sset, 200); 2780 """ 2781 Discover all Secondary Services 2782 """ 2783 ok, services = secondaryServicesByType(transport, initiator, trace); 2784 if ok: 2785 for _uuid, _handle in zip(services["uuid"], services["handle"]): 2786 trace.trace(6, "Service %s at handle 0x%02X" % (attData.uuid(_uuid), _handle)); 2787 ok = services == gattData.secondaryServices(sset) 2788 trace.trace(6, "Verified Service Set: %s" % ok); 2789 elif sset == 0: 2790 ok = services == gattData.secondaryServices(sset) 2791 trace.trace(6, "Verified Service Set: %s" % ok); 2792 else: 2793 trace.trace(6, "Unable to discover Secondary Services!"); 2794 success = success and ok; 2795 2796 success = initiator.disconnect(0x13) and success; 2797 2798 return success; 2799 2800""" 2801 GATT/SR/GPA/BV-03-C [Server Reads Include Declaration] 2802""" 2803def gatt_sr_gpa_bv_03_c(transport, upperTester, lowerTester, trace): 2804 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2805 if success: 2806 attData, gattData = ATTData(), GATTData.instance(); 2807 2808 for sset in range(4): 2809 """ 2810 Switching Service Set 2811 """ 2812 trace.trace(6, "Switching to Service Set #%d" % sset); 2813 switch_gatt_service_set(transport, lowerTester, sset, 200); 2814 """ 2815 Discover all Included Services 2816 """ 2817 ok, services = includedServicesByType(transport, initiator, trace); 2818 if ok: 2819 for _uuid, _handles in zip(services["uuids"], services["handles"]): 2820 trace.trace(6, "Service %s covers handles [0x%02X, 0x%02X]" % (attData.uuid(_uuid), _handles[0], _handles[1])); 2821 ok = services == gattData.includedServices(sset) 2822 trace.trace(6, "Verified Service Set: %s" % ok); 2823 elif sset == 0: 2824 ok = services == gattData.includedServices(sset) 2825 trace.trace(6, "Verified Service Set: %s" % ok); 2826 else: 2827 trace.trace(6, "Unable to discover Included Services!"); 2828 success = success and ok; 2829 2830 success = initiator.disconnect(0x13) and success; 2831 2832 return success; 2833 2834""" 2835 GATT/SR/GPA/BV-04-C [Server Reads Characteristic Declaration] 2836""" 2837def gatt_sr_gpa_bv_04_c(transport, upperTester, lowerTester, trace): 2838 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2839 if success: 2840 attData, gattData = ATTData(), GATTData.instance(); 2841 2842 for sset in range(4): 2843 """ 2844 Switching Service Set 2845 2846 """ 2847 trace.trace(6, "Switching to Service Set #%d" % sset); 2848 switch_gatt_service_set(transport, lowerTester, sset, 200); 2849 """ 2850 Discover all Characteristic Declarations 2851 """ 2852 ok, characteristics = characteristicsByType(transport, initiator, [0x0001, 0xffff], trace); 2853 if ok: 2854 for _uuid, _handle, _value_handle, _property in zip(characteristics['uuid'], characteristics['handle'], \ 2855 characteristics['value_handle'], characteristics['property']): 2856 trace.trace(6, "Characteristic %s handle 0x%02X value handle 0x%02X properties %s" % \ 2857 (attData.uuid(_uuid), _handle, _value_handle, attData.property(_property))); 2858 2859 _characteristics = gattData.characteristics(sset); 2860 _characteristics.pop("permission"); 2861 2862 ok = characteristics == _characteristics 2863 trace.trace(6, "Verified Characteristics: %s" % ok); 2864 else: 2865 trace.trace(6, "Unable to discover Characteristic Declarations!"); 2866 success = success and ok; 2867 2868 success = initiator.disconnect(0x13) and success; 2869 2870 return success; 2871 2872""" 2873 GATT/SR/GPA/BV-05-C [Server Reads Characteristic Extended Properties Declaration] 2874""" 2875def gatt_sr_gpa_bv_05_c(transport, upperTester, lowerTester, trace): 2876 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2877 if success: 2878 attData, gattData = ATTData(), GATTData.instance(); 2879 2880 for sset in range(4): 2881 """ 2882 Switching Service Set 2883 2884 """ 2885 trace.trace(6, "Switching to Service Set #%d" % sset); 2886 switch_gatt_service_set(transport, lowerTester, sset, 200); 2887 2888 _descriptors = filterCharacteristics(gattData.descriptors(sset), 0x2900); 2889 2890 """ 2891 Discover all Characteristic Declarations for Extended Properties 2892 """ 2893 ok, descriptors = specificDescriptors(transport, initiator, [0x0001, 0xffff], 0x2900, trace); 2894 if ok: 2895 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 2896 _success, value = readCharacteristic(transport, initiator, _handle, trace); 2897 _value = gattData.descriptorValue(sset, _handle); 2898 if _success: 2899 _success = value == _value; 2900 trace.trace(6, "Descriptor %s handle 0x%02X value %s - %s" % (attData.uuid(_uuid), _handle, formatArray(value), _success)); 2901 else: 2902 trace.trace(6, "Descriptor %s handle 0x%02X value %s" % (attData.uuid(_uuid), _handle, attData.error(value))); 2903 success = success and _success; 2904 2905 ok = descriptors == _descriptors 2906 trace.trace(6, "Verified Descriptors: %s" % ok); 2907 elif sset == 0: 2908 ok = descriptors == _descriptors 2909 trace.trace(6, "Verified Descriptors: %s" % ok); 2910 else: 2911 trace.trace(6, "Unable to discover Extended Properties Descriptors!"); 2912 success = success and ok; 2913 2914 success = initiator.disconnect(0x13) and success; 2915 2916 return success; 2917 2918""" 2919 GATT/SR/GPA/BV-06-C [Server Reads Characteristic User Description Descriptor] 2920""" 2921def gatt_sr_gpa_bv_06_c(transport, upperTester, lowerTester, trace): 2922 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2923 if success: 2924 attData, gattData = ATTData(), GATTData.instance(); 2925 2926 for sset in range(4): 2927 """ 2928 Switching Service Set 2929 2930 """ 2931 trace.trace(6, "Switching to Service Set #%d" % sset); 2932 switch_gatt_service_set(transport, lowerTester, sset, 200); 2933 2934 _descriptors = filterCharacteristics(gattData.descriptors(sset), 0x2901); 2935 2936 """ 2937 Discover all Characteristic Declarations for Extended Properties 2938 """ 2939 ok, descriptors = specificDescriptors(transport, initiator, [0x0001, 0xffff], 0x2901, trace); 2940 if ok: 2941 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 2942 _success, value = readStringCharacteristic(transport, initiator, _handle, trace); 2943 _value = gattData.descriptorString(sset, _handle); 2944 if _success: 2945 _success = value == _value; 2946 trace.trace(6, "Descriptor %s handle 0x%02X value %s - %s" % (attData.uuid(_uuid), _handle, value, _success)); 2947 else: 2948 trace.trace(6, "Descriptor %s handle 0x%02X value %s" % (attData.uuid(_uuid), _handle, attData.error(value))); 2949 success = success and _success; 2950 2951 ok = descriptors == _descriptors 2952 trace.trace(6, "Verified Descriptors: %s" % ok); 2953 elif sset == 0: 2954 ok = descriptors == _descriptors 2955 trace.trace(6, "Verified Descriptors: %s" % ok); 2956 else: 2957 trace.trace(6, "Unable to discover User Description Descriptors!"); 2958 success = success and ok; 2959 2960 success = initiator.disconnect(0x13) and success; 2961 2962 return success; 2963 2964""" 2965 GATT/SR/GPA/BV-07-C [Server Reads Client Characteristic Configuration Descriptor] 2966""" 2967def gatt_sr_gpa_bv_07_c(transport, upperTester, lowerTester, trace): 2968 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 2969 if success: 2970 attData, gattData = ATTData(), GATTData.instance(); 2971 2972 for sset in range(4): 2973 """ 2974 Switching Service Set 2975 2976 """ 2977 trace.trace(6, "Switching to Service Set #%d" % sset); 2978 switch_gatt_service_set(transport, lowerTester, sset, 200); 2979 2980 _descriptors = filterCharacteristics(gattData.descriptors(sset), 0x2902); 2981 2982 """ 2983 Discover all Client Characteristic Configuration Descriptors 2984 """ 2985 ok, descriptors = specificDescriptors(transport, initiator, [0x0001, 0xffff], 0x2902, trace); 2986 if ok: 2987 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 2988 _success, value = readCharacteristic(transport, initiator, _handle, trace); 2989 _value = gattData.descriptorValue(sset, _handle); 2990 if _success: 2991 _success = value == _value; 2992 trace.trace(6, "Descriptor %s handle 0x%02X value %s - %s" % (attData.uuid(_uuid), _handle, formatArray(value), _success)); 2993 else: 2994 trace.trace(6, "Descriptor %s handle 0x%02X value %s" % (attData.uuid(_uuid), _handle, attData.error(value))); 2995 success = success and _success; 2996 2997 ok = descriptors == _descriptors 2998 trace.trace(6, "Verified Descriptors: %s" % ok); 2999 elif sset == 0: 3000 ok = descriptors == _descriptors 3001 trace.trace(6, "Verified Descriptors: %s" % ok); 3002 else: 3003 trace.trace(6, "Unable to discover Client Characteristic Configuration Descriptors!"); 3004 success = success and ok; 3005 3006 success = initiator.disconnect(0x13) and success; 3007 3008 return success; 3009 3010""" 3011 GATT/SR/GPA/BV-08-C [Server Reads Server Characteristic Configuration Descriptor] 3012""" 3013def gatt_sr_gpa_bv_08_c(transport, upperTester, lowerTester, trace): 3014 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 3015 if success: 3016 attData, gattData = ATTData(), GATTData.instance(); 3017 3018 for sset in range(4): 3019 """ 3020 Switching Service Set 3021 3022 """ 3023 trace.trace(6, "Switching to Service Set #%d" % sset); 3024 switch_gatt_service_set(transport, lowerTester, sset, 200); 3025 3026 _descriptors = filterCharacteristics(gattData.descriptors(sset), 0x2903); 3027 3028 """ 3029 Discover all Server Characteristic Configuration Descriptors 3030 """ 3031 ok, descriptors = specificDescriptors(transport, initiator, [0x0001, 0xffff], 0x2903, trace); 3032 if ok: 3033 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 3034 _success, value = readCharacteristic(transport, initiator, _handle, trace); 3035 _value = gattData.descriptorValue(sset, _handle); 3036 if _success: 3037 _success = value == _value; 3038 trace.trace(6, "Descriptor %s handle 0x%02X value %s - %s" % (attData.uuid(_uuid), _handle, formatArray(value), _success)); 3039 else: 3040 trace.trace(6, "Descriptor %s handle 0x%02X value %s" % (attData.uuid(_uuid), _handle, attData.error(value))); 3041 success = success and _success; 3042 3043 ok = descriptors == _descriptors 3044 trace.trace(6, "Verified Descriptors: %s" % ok); 3045 elif sset == 0: 3046 ok = descriptors == _descriptors 3047 trace.trace(6, "Verified Descriptors: %s" % ok); 3048 else: 3049 trace.trace(6, "Unable to discover Server Characteristic Configuration Descriptors!"); 3050 success = success and ok; 3051 3052 success = initiator.disconnect(0x13) and success; 3053 3054 return success; 3055 3056""" 3057 GATT/SR/GPA/BV-12-C [Server handles Characteristic Presentation Format Descriptors] 3058""" 3059def gatt_sr_gpa_bv_12_c(transport, upperTester, lowerTester, trace): 3060 success, mtuSize, initiator = preambleConnected(transport, upperTester, 46, trace); 3061 if success: 3062 attData, gattData = ATTData(), GATTData.instance(); 3063 3064 for sset in range(4): 3065 """ 3066 Switching Service Set 3067 3068 """ 3069 trace.trace(6, "Switching to Service Set #%d" % sset); 3070 switch_gatt_service_set(transport, lowerTester, sset, 200); 3071 3072 _descriptors = filterCharacteristics(gattData.descriptors(sset), 0x2904); 3073 3074 """ 3075 Discover all Characteristic Presentation Format Descriptors 3076 """ 3077 ok, descriptors = specificDescriptors(transport, initiator, [0x0001, 0xffff], 0x2904, trace); 3078 if ok: 3079 for _uuid, _handle in zip(descriptors['uuid'], descriptors['handle']): 3080 _success, value = readCharacteristic(transport, initiator, _handle, trace); 3081 _value = gattData.descriptorValue(sset, _handle); 3082 if _success: 3083 _success = value == _value; 3084 trace.trace(6, "Descriptor %s handle 0x%02X value %s - %s" % (attData.uuid(_uuid), _handle, formatArray(value), _success)); 3085 else: 3086 trace.trace(6, "Descriptor %s handle 0x%02X value %s" % (attData.uuid(_uuid), _handle, attData.error(value))); 3087 success = success and _success; 3088 3089 characteristic = gattData.characteristicWithDescriptor(sset, _handle); 3090 _success, value = readCharacteristic(transport, initiator, characteristic['value_handle'], trace); 3091 trace.trace(6, "Characteristic %s handle 0x%02X value %s" % \ 3092 (attData.uuid(characteristic['uuid']), characteristic['handle'], formatArray(value))); 3093 3094 ok = descriptors == _descriptors 3095 trace.trace(6, "Verified Descriptors: %s" % ok); 3096 elif sset == 0: 3097 ok = descriptors == _descriptors 3098 trace.trace(6, "Verified Descriptors: %s" % ok); 3099 else: 3100 trace.trace(6, "Unable to discover Characteristic Presentation Format Descriptors!"); 3101 success = success and ok; 3102 3103 success = initiator.disconnect(0x13) and success; 3104 3105 return success; 3106 3107__tests__ = { 3108 "GAP/GAT/BV-01-C": [ gap_gat_bv_01_c, 'Mandatory Characteristics' ], 3109# "GAP/GAT/BV-02-C": [ gap_gat_bv_02_c, 'Peripheral Privacy Flag Characteristic' ], 3110# "GAP/GAT/BV-03-C": [ gap_gat_bv_03_c, 'Reconnection Address Characteristic' ], 3111 "GAP/GAT/BV-04-C": [ gap_gat_bv_04_c, 'Peripheral Preferred Connection Parameters Characteristic' ], 3112# "GAP/GAT/BV-05-C": [ gap_gat_bv_05_c, 'Changing Device Name' ], 3113 "GAP/IDLE/NAMP/BV-01-C": [ gap_idle_namp_bv_01_c, 'Name Discovery Procedure GATT Client' ], 3114# "GAP/GAT/BX-01-C": [ gap_gat_bx_01_c, 'Discover All Services' ], 3115 3116 "GATT/SR/GAC/BV-01-C": [ gatt_sr_gac_bv_01_c, 'Server accepts Server Configuration' ], 3117 "GATT/SR/GAD/BV-01-C": [ gatt_sr_gad_bv_01_c, 'Server Discovers All Primary Services' ], 3118 "GATT/SR/GAD/BV-02-C": [ gatt_sr_gad_bv_02_c, 'Server Discovers Primary Services by Service UUID' ], 3119 "GATT/SR/GAD/BV-03-C": [ gatt_sr_gad_bv_03_c, 'Server Finds Included Services' ], 3120 "GATT/SR/GAD/BV-04-C": [ gatt_sr_gad_bv_04_c, 'Server Discovers All Characteristics of a Service' ], 3121 "GATT/SR/GAD/BV-05-C": [ gatt_sr_gad_bv_05_c, 'Server Discovers Characteristics by UUID' ], 3122 "GATT/SR/GAD/BV-06-C": [ gatt_sr_gad_bv_06_c, 'Server Discovers All Characteristic Descriptors' ], 3123 "GATT/SR/GAR/BV-01-C": [ gatt_sr_gar_bv_01_c, 'Server Reads Characteristic Value' ], 3124 "GATT/SR/GAR/BI-01-C": [ gatt_sr_gar_bi_01_c, 'Read Not Permitted error - Reading Characteristic Value' ], 3125 "GATT/SR/GAR/BI-02-C": [ gatt_sr_gar_bi_02_c, 'Invalid Handle error - Reading Characteristic Value' ], 3126 "GATT/SR/GAR/BI-03-C": [ gatt_sr_gar_bi_03_c, 'Insufficient Authorization error - Reading Characteristic Value' ], 3127 "GATT/SR/GAR/BI-04-C": [ gatt_sr_gar_bi_04_c, 'Insufficient Authentication error - Reading Characteristic Value' ], 3128 "GATT/SR/GAR/BV-03-C": [ gatt_sr_gar_bv_03_c, 'Server Reads using Characteristic UUID' ], 3129 "GATT/SR/GAR/BI-06-C": [ gatt_sr_gar_bi_06_c, 'Read Not Permitted error - Reading Characteristic by UUID' ], 3130 "GATT/SR/GAR/BI-07-C": [ gatt_sr_gar_bi_07_c, 'Attribute Not Found error - Reading Characteristic by UUID' ], 3131 "GATT/SR/GAR/BI-09-C": [ gatt_sr_gar_bi_09_c, 'Insufficient Authorization error - Reading Using Characteristic UUID' ], 3132 "GATT/SR/GAR/BI-10-C": [ gatt_sr_gar_bi_10_c, 'Insufficient Authentication error - Reading Using Characteristic UUID' ], 3133 "GATT/SR/GAR/BI-11-C": [ gatt_sr_gar_bi_11_c, 'Insufficient Encryption Key Size error - Reading Using Characteristic UUID' ], 3134 "GATT/SR/GAR/BV-04-C": [ gatt_sr_gar_bv_04_c, 'Server Reads Long Characteristic Value' ], 3135 "GATT/SR/GAR/BI-12-C": [ gatt_sr_gar_bi_12_c, 'Read Not Permitted error - Reading Long Characteristic Value' ], 3136 "GATT/SR/GAR/BI-13-C": [ gatt_sr_gar_bi_13_c, 'Invalid Offset error - Reading Long Characteristic Value' ], 3137 "GATT/SR/GAR/BI-14-C": [ gatt_sr_gar_bi_14_c, 'Invalid Handle error - Reading Long Characteristic Value' ], 3138 "GATT/SR/GAR/BI-15-C": [ gatt_sr_gar_bi_15_c, 'Insufficient Authorization error - Reading Long Characteristic Value' ], 3139 "GATT/SR/GAR/BI-16-C": [ gatt_sr_gar_bi_16_c, 'Insufficient Authentication error - Reading Long Characteristic Value' ], 3140 "GATT/SR/GAR/BI-17-C": [ gatt_sr_gar_bi_17_c, 'Insufficient Encryption Key Size error - Reading Long Characteristic Value' ], 3141 "GATT/SR/GAR/BV-05-C": [ gatt_sr_gar_bv_05_c, 'Server Reads Multiple Characteristic Values' ], 3142 "GATT/SR/GAR/BI-18-C": [ gatt_sr_gar_bi_18_c, 'Read Not Permitted error - Reading Multiple Characteristic Values' ], 3143 "GATT/SR/GAR/BI-19-C": [ gatt_sr_gar_bi_19_c, 'Invalid Handle error - Reading Multiple Characteristic Values' ], 3144 "GATT/SR/GAR/BI-20-C": [ gatt_sr_gar_bi_20_c, 'Insufficient Authorization error - Reading Multiple Characteristic Values' ], 3145 "GATT/SR/GAR/BI-21-C": [ gatt_sr_gar_bi_21_c, 'Insufficient Authentication error - Reading Multiple Characteristic Values' ], 3146 "GATT/SR/GAR/BI-22-C": [ gatt_sr_gar_bi_22_c, 'Insufficient Encryption Key Size error - Reading Multiple Characteristic Values' ], 3147 "GATT/SR/GAR/BV-06-C": [ gatt_sr_gar_bv_06_c, 'Server Reads Characteristic Descriptors' ], 3148 "GATT/SR/GAR/BV-07-C": [ gatt_sr_gar_bv_07_c, 'Server Reads Long Characteristic Descriptor' ], 3149 "GATT/SR/GAW/BV-01-C": [ gatt_sr_gaw_bv_01_c, 'Server Writes Without Response' ], 3150 "GATT/SR/GAW/BV-03-C": [ gatt_sr_gaw_bv_03_c, 'Server Writes Characteristic Value' ], 3151 "GATT/SR/GAW/BI-02-C": [ gatt_sr_gaw_bi_02_c, 'Invalid Handle error - Writing Characteristic Value' ], 3152 "GATT/SR/GAW/BI-03-C": [ gatt_sr_gaw_bi_03_c, 'Write Not Permitted error - Writing Characteristic Value' ], 3153 "GATT/SR/GAW/BI-04-C": [ gatt_sr_gaw_bi_04_c, 'Insufficient Authorization error - Writing Characteristic Value' ], 3154 "GATT/SR/GAW/BI-05-C": [ gatt_sr_gaw_bi_05_c, 'Insufficient Authentication error - Writing Characteristic Value' ], 3155 "GATT/SR/GAW/BI-06-C": [ gatt_sr_gaw_bi_06_c, 'Insufficient Encryption Key Size error - Writing Characteristic Value' ], 3156 "GATT/SR/GAW/BV-05-C": [ gatt_sr_gaw_bv_05_c, 'Server Writes Long Characteristic Value' ], 3157 "GATT/SR/GAW/BI-07-C": [ gatt_sr_gaw_bi_07_c, 'Invalid Handle error - Writing Long Characteristic Value' ], 3158 "GATT/SR/GAW/BI-08-C": [ gatt_sr_gaw_bi_08_c, 'Write Not Permitted error - Writing Long Characteristic Value' ], 3159 "GATT/SR/GAW/BI-09-C": [ gatt_sr_gaw_bi_09_c, 'Invalid Offset error - Writing Long Characteristic Value' ], 3160 "GATT/SR/GAW/BI-11-C": [ gatt_sr_gaw_bi_11_c, 'Insufficient Authorization error - Writing Long Characteristic Value' ], 3161 "GATT/SR/GAW/BI-12-C": [ gatt_sr_gaw_bi_12_c, 'Insufficient Authentication error - Writing Long Characteristic Value' ], 3162 "GATT/SR/GAW/BI-13-C": [ gatt_sr_gaw_bi_13_c, 'Insufficient Encryption Key Size error - Writing Long Characteristic Value' ], 3163 "GATT/SR/GAW/BV-08-C": [ gatt_sr_gaw_bv_08_c, 'Server Writes Characteristic Descriptors' ], 3164 "GATT/SR/GAW/BV-09-C": [ gatt_sr_gaw_bv_09_c, 'Server Writes Long Characteristic Descriptors' ], 3165 "GATT/SR/GAW/BV-11-C": [ gatt_sr_gaw_bv_11_c, 'No Pending Prepared Write Requests error - Characteristic Value Reliable Writes' ], 3166 "GATT/SR/GAW/BI-32-C": [ gatt_sr_gaw_bi_32_c, 'Invalid Attribute Value Length error - Writing Characteristic Value' ], 3167 "GATT/SR/GAW/BI-33-C": [ gatt_sr_gaw_bi_33_c, 'Invalid Attribute Value Length error - Writing Long Characteristic Value' ], 3168 "GATT/SR/GAN/BV-01-C": [ gatt_sr_gan_bv_01_c, 'Server generates Characteristic Value Notification' ], 3169 "GATT/SR/GAI/BV-01-C": [ gatt_sr_gai_bv_01_c, 'Server generates Characteristic Value Indication' ], 3170 "GATT/SR/GAS/BV-01-C": [ gatt_sr_gas_bv_01_c, 'Server accepts Service Changed Characteristic Indication' ], 3171 "GATT/SR/UNS/BI-01-C": [ gatt_sr_uns_bi_01_c, 'Server sends Unsupported ATT Requests' ], 3172 "GATT/SR/UNS/BI-02-C": [ gatt_sr_uns_bi_02_c, 'Server sends Unsupported ATT Commands' ], 3173 "GATT/SR/GPA/BV-01-C": [ gatt_sr_gpa_bv_01_c, 'Server Reads Primary Service Declaration' ], 3174 "GATT/SR/GPA/BV-02-C": [ gatt_sr_gpa_bv_02_c, 'Server Reads Secondary Service Declaration' ], 3175 "GATT/SR/GPA/BV-03-C": [ gatt_sr_gpa_bv_03_c, 'Server Reads Include Declaration' ], 3176 "GATT/SR/GPA/BV-04-C": [ gatt_sr_gpa_bv_04_c, 'Server Reads Characteristic Declaration' ], 3177 "GATT/SR/GPA/BV-05-C": [ gatt_sr_gpa_bv_05_c, 'Server Reads Characteristic Extended Properties Declaration' ], 3178 "GATT/SR/GPA/BV-06-C": [ gatt_sr_gpa_bv_06_c, 'Server Reads Characteristic User Description Descriptor' ], 3179 "GATT/SR/GPA/BV-07-C": [ gatt_sr_gpa_bv_07_c, 'Server Reads Client Characteristic Configuration Descriptor' ], 3180 "GATT/SR/GPA/BV-08-C": [ gatt_sr_gpa_bv_08_c, 'Server Reads Server Characteristic Configuration Descriptor' ], 3181 "GATT/SR/GPA/BV-12-C": [ gatt_sr_gpa_bv_12_c, 'Server handles Characteristic Presentation Format Descriptors' ] 3182}; 3183 3184_maxNameLength = max([ len(key) for key in __tests__ ]); 3185 3186_spec = { key: TestSpec(name = key, number_devices = 1, description = "#[" + __tests__[key][1] + "]", test_private = __tests__[key][0]) for key in __tests__ }; 3187 3188""" 3189 Return the test spec which contains info about all the tests 3190 this test module provides 3191""" 3192def get_tests_specs(): 3193 return _spec; 3194 3195def preamble(transport, trace): 3196 global lowerIRK, upperIRK, lowerRandomAddress, upperRandomAddress; 3197 3198 ok = success = preamble_standby(transport, 0, trace); 3199 trace.trace(4, "preamble Standby " + ("PASS" if success else "FAIL")); 3200 success, upperIRK, upperRandomAddress = preamble_device_address_set(transport, 0, trace); 3201 trace.trace(4, "preamble Device Address Set " + ("PASS" if success else "FAIL")); 3202 ok = ok and success; 3203 return ok; 3204 3205""" 3206 Run a test given its test_spec 3207""" 3208def run_a_test(args, transport, trace, test_spec, device_dumps): 3209 try: 3210 success = preamble(transport, trace); 3211 except Exception as e: 3212 trace.trace(3, "Preamble generated exception: %s" % str(e)); 3213 success = False; 3214 3215 trace.trace(2, "%-*s %s test started..." % (_maxNameLength, test_spec.name, test_spec.description[1:])); 3216 test_f = test_spec.test_private; 3217 try: 3218 if test_f.__code__.co_argcount > 4: 3219 success = success and test_f(transport, 0, 1, trace, device_dumps); 3220 elif test_f.__code__.co_argcount > 3: 3221 success = success and test_f(transport, 0, 1, trace); 3222 else: 3223 success = success and test_f(transport, 0, trace); 3224 except Exception as e: 3225 import traceback 3226 traceback.print_exc() 3227 trace.trace(3, "Test generated exception: %s" % str(e)); 3228 success = False; 3229 3230 return not success 3231