def ConnectionRequestCapture(): return Capture( HciMatchers.EventWithCode( hci_packets.EventCode.CONNECTION_REQUEST), lambda packet: hci_packets.ConnectionRequestView( HciMatchers.ExtractEventWithCode( packet.event, hci_packets.EventCode.CONNECTION_REQUEST)))
def ConnectionCompleteCapture(): return Capture( HciMatchers.EventWithCode( hci_packets.EventCode.CONNECTION_COMPLETE), lambda packet: hci_packets.ConnectionCompleteView( HciMatchers.ExtractEventWithCode( packet.event, hci_packets.EventCode.CONNECTION_COMPLETE)))
def wait_for_disconnect_event(self): """ Cert side needs to pass """ logging.info("Cert: Waiting for DISCONNECT_COMPLETE") assertThat(self._hci_event_stream).emits( HciMatchers.DisconnectionComplete())
def _set_name(self): padded_name = self.cert_name while len(padded_name) < 248: padded_name = padded_name + b'\0' self.cert_hci.send_command(hci_packets.WriteLocalNameBuilder(padded_name)) assertThat(self.cert_hci.get_event_stream()).emits(HciMatchers.CommandComplete(OpCode.WRITE_LOCAL_NAME))
def start(self): enabled_set = EnabledSet() enabled_set.advertising_handle = self.handle enabled_set.duration = 0 enabled_set.max_extended_advertising_events = 0 self.py_hci.send_command(LeSetExtendedAdvertisingEnableBuilder(Enable.ENABLED, [enabled_set])) assertThat(self.py_hci.get_event_stream()).emits( HciMatchers.CommandComplete(OpCode.LE_SET_EXTENDED_ADVERTISING_ENABLE))
def test_local_hci_cmd_and_event(self): # Loopback mode responds with ACL and SCO connection complete self.dut_hci.register_for_events(EventCode.LOOPBACK_COMMAND) self.dut_hci.send_command( WriteLoopbackModeBuilder(LoopbackMode.ENABLE_LOCAL)) self.dut_hci.send_command(ReadLocalNameBuilder()) assertThat(self.dut_hci.get_event_stream()).emits( HciMatchers.LoopbackOf(ReadLocalNameBuilder()))
def test_inquiry_from_dut(self): self.dut_hci.register_for_events(EventCode.INQUIRY_RESULT) self.cert_hal.enable_inquiry_and_page_scan() lap = Lap() lap.lap = 0x33 self.dut_hci.send_command(InquiryBuilder(lap, 0x30, 0xff)) assertThat(self.dut_hci.get_event_stream()).emits( HciMatchers.EventWithCode(EventCode.INQUIRY_RESULT))
def verify_security_connection(self): """ Verify that we get a connection and a link key request """ assertThat(self.get_security_connection_event_stream()).emits( lambda event: event.event_type == LinkSecurityInterfaceCallbackEventType.ON_CONNECTED) assertThat(self._hci.get_event_stream()).emits( HciMatchers.LinkKeyRequest())
def send_io_caps(self, address): logging.info("Cert: Waiting for IO_CAPABILITY_REQUEST") assertThat(self._hci_event_stream).emits( HciMatchers.IoCapabilityRequest()) logging.info("Cert: Sending IO_CAPABILITY_REQUEST_REPLY") oob_data_present = hci_packets.OobDataPresent.NOT_PRESENT self._enqueue_hci_command( hci_packets.IoCapabilityRequestReplyBuilder( address.decode('utf8'), self._io_caps, oob_data_present, self._auth_reqs), True)
def test_stream_events(self): self.dut_hal.send_hci_command( hci_packets.LeAddDeviceToConnectListBuilder( hci_packets.ConnectListAddressType.RANDOM, '0C:05:04:03:02:01')) assertThat(self.dut_hal.get_hci_event_stream()).emits( HciMatchers.Exactly( hci_packets.LeAddDeviceToConnectListCompleteBuilder( 1, hci_packets.ErrorCode.SUCCESS)))
def test_loopback_hci_command(self): self.dut_hal.send_hci_command( hci_packets.WriteLoopbackModeBuilder( hci_packets.LoopbackMode.ENABLE_LOCAL)) command = hci_packets.LeAddDeviceToConnectListBuilder( hci_packets.ConnectListAddressType.RANDOM, '0C:05:04:03:02:01') self.dut_hal.send_hci_command(command) assertThat(self.dut_hal.get_hci_event_stream()).emits( HciMatchers.LoopbackOf(command))
def accept_oob_pairing(self, dut_address): logging.info("Cert: Waiting for IO_CAPABILITY_RESPONSE") assertThat(self._hci_event_stream).emits( HciMatchers.IoCapabilityResponse()) self.send_io_caps(dut_address) logging.info("Cert: Waiting for SIMPLE_PAIRING_COMPLETE") ssp_complete_capture = HciCaptures.SimplePairingCompleteCapture() assertThat(self._hci_event_stream).emits(ssp_complete_capture) ssp_complete = ssp_complete_capture.get() logging.info(ssp_complete.GetStatus()) assertThat(ssp_complete.GetStatus()).isEqualTo( hci_packets.ErrorCode.SUCCESS)
def enable_secure_simple_pairing(self): """ This is called when you want to enable SSP for testing """ logging.info("Cert: Sending WRITE_SIMPLE_PAIRING_MODE [True]") self._enqueue_hci_command( hci_packets.WriteSimplePairingModeBuilder( hci_packets.Enable.ENABLED), True) logging.info("Cert: Waiting for controller response") assertThat(self._hci_event_stream).emits( HciMatchers.CommandComplete( hci_packets.OpCode.WRITE_SIMPLE_PAIRING_MODE))
def test_le_connect_list_connection_cert_advertises(self): self.dut_hal.set_random_le_address('0D:05:04:03:02:01') self.dut_hal.add_to_connect_list('0C:05:04:03:02:01') self.dut_hal.initiate_le_connection_by_connect_list( 'BA:D5:A4:A3:A2:A1') advertisement = self.cert_hal.create_advertisement( 1, '0C:05:04:03:02:01', min_interval=512, max_interval=768, peer_address='A6:A5:A4:A3:A2:A1', tx_power=0x7F, sid=0) advertisement.set_data(b'Im_A_Cert') advertisement.start() assertThat(self.cert_hal.get_hci_event_stream()).emits( HciMatchers.LeConnectionComplete()) assertThat(self.dut_hal.get_hci_event_stream()).emits( HciMatchers.LeConnectionComplete())
def test_inquiry_from_dut(self): self.dut_hci.register_for_events(hci_packets.EventCode.INQUIRY_RESULT) self.send_hal_hci_command( hci_packets.WriteScanEnableBuilder( hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN)) lap = hci_packets.Lap() lap.lap = 0x33 self.dut_hci.send_command_with_status( hci_packets.InquiryBuilder(lap, 0x30, 0xff)) assertThat(self.dut_hci.get_event_stream()).emits( HciMatchers.EventWithCode(hci_packets.EventCode.INQUIRY_RESULT))
def enable_secure_connections(self): """ This is called when you want to enable secure connections support """ logging.info( "Cert: Sending WRITE_SECURE_CONNECTIONS_HOST_SUPPORT [True]") self._enqueue_hci_command( hci_packets.WriteSecureConnectionsHostSupportBuilder( hci_packets.Enable.ENABLED), True) logging.info("Cert: Waiting for controller response") assertThat(self._hci_event_stream).emits( HciMatchers.CommandComplete( hci_packets.OpCode.WRITE_SECURE_CONNECTIONS_HOST_SUPPORT))
def accept_pairing(self, dut_address, reply_boolean): """ Here we handle the pairing events at the HCI level """ logging.info("Cert: Waiting for LINK_KEY_REQUEST") assertThat(self._hci_event_stream).emits(HciMatchers.LinkKeyRequest()) logging.info("Cert: Sending LINK_KEY_REQUEST_NEGATIVE_REPLY") self._enqueue_hci_command( hci_packets.LinkKeyRequestNegativeReplyBuilder( dut_address.decode('utf8')), True) self.send_io_caps(dut_address) logging.info("Cert: Waiting for USER_CONFIRMATION_REQUEST") assertThat(self._hci_event_stream).emits( HciMatchers.UserConfirmationRequest()) logging.info("Cert: Sending Simulated User Response '%s'" % reply_boolean) if reply_boolean: logging.info("Cert: Sending USER_CONFIRMATION_REQUEST_REPLY") self._enqueue_hci_command( hci_packets.UserConfirmationRequestReplyBuilder( dut_address.decode('utf8')), True) logging.info("Cert: Waiting for SIMPLE_PAIRING_COMPLETE") assertThat(self._hci_event_stream).emits( HciMatchers.SimplePairingComplete()) logging.info("Cert: Waiting for LINK_KEY_NOTIFICATION") assertThat(self._hci_event_stream).emits( HciMatchers.LinkKeyNotification()) else: logging.info( "Cert: Sending USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY") self._enqueue_hci_command( hci_packets.UserConfirmationRequestNegativeReplyBuilder( dut_address.decode('utf8')), True) logging.info("Cert: Waiting for SIMPLE_PAIRING_COMPLETE") assertThat(self._hci_event_stream).emits( HciMatchers.SimplePairingComplete())
def input_pin(self, address, pin): """ Pretend to answer the pairing dialog as a user """ if len(pin) > self.MAX_PIN_LENGTH or len(pin) < self.MIN_PIN_LENGTH: raise Exception("Pin code must be within range") logging.info("Cert: Waiting for PIN request") assertThat(self._hci_event_stream).emits(HciMatchers.PinCodeRequest()) logging.info("Cert: Send user input PIN %s for %s" % (pin.decode(), address)) peer = address.decode('utf-8') pin_list = list(pin) # Pad for i in range(self.MAX_PIN_LENGTH - len(pin_list)): pin_list.append(0) self._enqueue_hci_command( hci_packets.PinCodeRequestReplyBuilder(peer, len(pin), pin_list), True)
def input_passkey(self, address, passkey): """ Pretend to answer the pairing dialog as a user """ logging.info("Cert: Waiting for PASSKEY request") assertThat(self._hci_event_stream).emits( HciMatchers.EventWithCode( hci_packets.EventCode.USER_PASSKEY_REQUEST)) logging.info("Cert: Send user input passkey %d for %s" % (passkey, address)) peer = address.decode('utf-8') self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.ENTRY_STARTED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.CLEARED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ERASED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.DIGIT_ENTERED), True) self._enqueue_hci_command( hci_packets.SendKeypressNotificationBuilder( peer, hci_packets.KeypressNotificationType.ENTRY_COMPLETED), True) self._enqueue_hci_command( hci_packets.UserPasskeyRequestReplyBuilder(peer, passkey), True)
def ReadBdAddrCompleteCapture(): return Capture( HciMatchers.CommandComplete(hci_packets.OpCode.READ_BD_ADDR), lambda packet: hci_packets.ReadBdAddrCompleteView( HciMatchers.ExtractMatchingCommandComplete( packet.event, hci_packets.OpCode.READ_BD_ADDR)))
def ReadLocalOobExtendedDataCompleteCapture(): return Capture( HciMatchers.CommandComplete(hci_packets.OpCode.READ_LOCAL_OOB_EXTENDED_DATA), lambda packet: HciMatchers.ExtractMatchingCommandComplete(packet.payload, hci_packets.OpCode.READ_LOCAL_OOB_EXTENDED_DATA) )
def LeConnectionCompleteCapture(): return Capture( HciMatchers.LeConnectionComplete(), lambda packet: HciMatchers. ExtractLeConnectionComplete(packet.event))
def SimplePairingCompleteCapture(): return Capture(HciMatchers.EventWithCode(hci_packets.EventCode.SIMPLE_PAIRING_COMPLETE), lambda packet: hci_packets.SimplePairingCompleteView( HciMatchers.ExtractEventWithCode(packet.payload, hci_packets.EventCode.SIMPLE_PAIRING_COMPLETE)))
def DisconnectionCompleteCapture(): return Capture( HciMatchers.EventWithCode(hci_packets.EventCode.DISCONNECTION_COMPLETE), lambda packet: hci_packets.DisconnectionCompleteView( HciMatchers.ExtractEventWithCode(packet.payload, hci_packets.EventCode.DISCONNECTION_COMPLETE)))
def wait_for_complete(self, opcode): assertThat(self.hci_event_stream).emits( HciMatchers.CommandComplete(opcode))
def test_le_connection_dut_advertises(self): self.dut_hci.register_for_le_events( hci_packets.SubeventCode.CONNECTION_COMPLETE) # Cert Connects self.send_hal_hci_command( hci_packets.LeSetRandomAddressBuilder('0C:05:04:03:02:01')) phy_scan_params = DirectHciTest._create_phy_scan_params() self.send_hal_hci_command( hci_packets.LeExtendedCreateConnectionBuilder( hci_packets.InitiatorFilterPolicy.USE_PEER_ADDRESS, hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS, hci_packets.AddressType.RANDOM_DEVICE_ADDRESS, '0D:05:04:03:02:01', 1, [phy_scan_params])) # DUT Advertises advertising_handle = 0 self.dut_hci.send_command_with_complete( hci_packets.LeSetExtendedAdvertisingLegacyParametersBuilder( advertising_handle, hci_packets.LegacyAdvertisingProperties.ADV_IND, 400, 450, 7, hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS, hci_packets.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS, '00:00:00:00:00:00', hci_packets.AdvertisingFilterPolicy.ALL_DEVICES, 0xF8, 1, #SID hci_packets.Enable.DISABLED # Scan request notification )) self.dut_hci.send_command_with_complete( hci_packets.LeSetExtendedAdvertisingRandomAddressBuilder( advertising_handle, '0D:05:04:03:02:01')) gap_name = hci_packets.GapData() gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME gap_name.data = list(bytes(b'Im_The_DUT!')) # TODO: Fix and remove ! self.dut_hci.send_command_with_complete( hci_packets.LeSetExtendedAdvertisingDataBuilder( advertising_handle, hci_packets.Operation.COMPLETE_ADVERTISEMENT, hci_packets.FragmentPreference.CONTROLLER_SHOULD_NOT, [gap_name])) gap_short_name = hci_packets.GapData() gap_short_name.data_type = hci_packets.GapDataType.SHORTENED_LOCAL_NAME gap_short_name.data = list(bytes(b'Im_The_D')) self.dut_hci.send_command_with_complete( hci_packets.LeSetExtendedAdvertisingScanResponseBuilder( advertising_handle, hci_packets.Operation.COMPLETE_ADVERTISEMENT, hci_packets.FragmentPreference.CONTROLLER_SHOULD_NOT, [gap_short_name])) enabled_set = hci_packets.EnabledSet() enabled_set.advertising_handle = advertising_handle enabled_set.duration = 0 enabled_set.max_extended_advertising_events = 0 self.dut_hci.send_command_with_complete( hci_packets.LeSetExtendedAdvertisingEnableBuilder( hci_packets.Enable.ENABLED, [enabled_set])) # Check for success of Enable assertThat(self.dut_hci.get_event_stream()).emits( HciMatchers.CommandComplete( hci_packets.OpCode.LE_SET_EXTENDED_ADVERTISING_ENABLE)) (dut_handle, cert_handle) = self._verify_le_connection_complete() # Send ACL Data self.enqueue_acl_data( dut_handle, hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE, hci_packets.BroadcastFlag.POINT_TO_POINT, bytes(b'Just SomeAclData')) self.send_hal_acl_data( cert_handle, hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE, hci_packets.BroadcastFlag.POINT_TO_POINT, bytes(b'Just SomeMoreAclData')) assertThat( self.cert_hal.get_acl_stream()).emits(lambda packet: logging.debug( packet.payload) or b'SomeAclData' in packet.payload) assertThat(self.dut_hci.get_raw_acl_stream()).emits( lambda packet: logging.debug( packet.data) or b'SomeMoreAclData' in packet.data)
def wait_for_status(self, opcode): assertThat(self.hci_event_stream).emits( HciMatchers.CommandStatus(opcode))