예제 #1
0
    def _setup_mock_subprocess(self):
        """
        Setup long-term expectations on the mocked out subprocess.

        These expectations are only met when |self._channel.close| is called in
        |tearDown|.

        """
        self._subprocess_mox = mox.Mox()
        mock_process = self._subprocess_mox.CreateMock(multiprocessing.Process)
        mock_process(target=mox.IgnoreArg(),
                     args=mox.IgnoreArg()).AndReturn(mock_process)
        mock_process.start()

        # Each API call into MBIMChannel results in an aliveness ping to the
        # subprocess.
        # Finally, when |self._channel| is destructed, it will attempt to
        # terminate the |mock_process|, with increasingly drastic actions.
        mock_process.is_alive().MultipleTimes().AndReturn(True)
        mock_process.join(mox.IgnoreArg())
        mock_process.is_alive().AndReturn(True)
        mock_process.terminate()

        self._subprocess_mox.ReplayAll()
        self._channel = mbim_channel.MBIMChannel(
                self._device,
                self._interface_number,
                self._interrupt_endpoint_address,
                self._in_buffer_size,
                mock_process)
    def run_internal(self):
        """ Run the MBIM_CID_DEVICE_CAPS Sequence. """
        # Step 1
        # Send MBIM_COMMAND_MSG.
        device_context = self.device_context
        descriptor_cache = device_context.descriptor_cache
        command_message = mbim_command_message.MBIMDeviceCapsQuery()
        packets = mbim_message_request.generate_request_packets(
            command_message, device_context.max_control_transfer_size)
        channel = mbim_channel.MBIMChannel(
            device_context._device,
            descriptor_cache.mbim_communication_interface.bInterfaceNumber,
            descriptor_cache.interrupt_endpoint.bEndpointAddress,
            device_context.max_control_transfer_size)
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        # Step 2
        response_message = mbim_message_response.parse_response_packets(
            response_packets)

        # Step 3
        is_message_valid = isinstance(response_message,
                                      mbim_command_message.MBIMDeviceCapsInfo)
        if ((not is_message_valid) or
            (response_message.message_type != mbim_constants.MBIM_COMMAND_DONE)
                or (response_message.status_codes !=
                    mbim_constants.MBIM_STATUS_SUCCESS)):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.3')

        return command_message, response_message
예제 #3
0
    def run_internal(self):
        """ Run the MBIM Close Sequence. """
        # Step 1
        # Send MBIM_CLOSE_MSG to the device.
        close_message = mbim_message_request.MBIMClose()
        device_context = self.device_context
        descriptor_cache = device_context.descriptor_cache
        packets = mbim_message_request.generate_request_packets(
            close_message, device_context.max_control_transfer_size)
        channel = mbim_channel.MBIMChannel(
            device_context._device,
            descriptor_cache.mbim_communication_interface.bInterfaceNumber,
            descriptor_cache.interrupt_endpoint.bEndpointAddress,
            device_context.max_control_transfer_size)

        # Step 2
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        response_message = mbim_message_response.parse_response_packets(
            response_packets)

        # Step 3
        if response_message.transaction_id != close_message.transaction_id:
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.2#1')

        if response_message.status_codes != mbim_constants.MBIM_STATUS_SUCCESS:
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.2#2')

        return close_message, response_message
예제 #4
0
    def run_internal(self):
        """ Run CM_05 test. """
        # Precondition
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
            self.test_context).run()

        caps_command_message = mbim_control.MBIMCommandMessage(
            device_service_id=mbim_constants.UUID_BASIC_CONNECT.bytes,
            cid=mbim_constants.MBIM_CID_DEVICE_CAPS,
            command_type=mbim_constants.COMMAND_TYPE_QUERY,
            information_buffer_length=0)
        caps_packets = caps_command_message.generate_packets()
        services_command_message = mbim_control.MBIMCommandMessage(
            device_service_id=mbim_constants.UUID_BASIC_CONNECT.bytes,
            cid=mbim_constants.MBIM_CID_DEVICE_SERVICES,
            command_type=mbim_constants.COMMAND_TYPE_QUERY,
            information_buffer_length=0)
        services_packets = services_command_message.generate_packets()
        self.caps_transaction_id = caps_command_message.transaction_id
        self.services_transaction_id = services_command_message.transaction_id
        self.channel = mbim_channel.MBIMChannel(
            {
                'idVendor': self.test_context.id_vendor,
                'idProduct': self.test_context.id_product
            }, self.test_context.mbim_communication_interface.bInterfaceNumber,
            self.test_context.interrupt_endpoint.bEndpointAddress,
            self.test_context.mbim_functional.wMaxControlMessage)
        # Step 1
        self.channel.unidirectional_transaction(*caps_packets)
        # Step 2
        self.channel.unidirectional_transaction(*services_packets)

        utils.poll_for_condition(
            self._get_response_packets,
            timeout=5,
            exception=mbim_errors.MBIMComplianceChannelError(
                'Failed to retrieve the response packets to specific '
                'control messages.'))

        self.channel.close()
        caps_response_message = mbim_control.parse_response_packets(
            self.caps_response_packet)
        services_response_message = mbim_control.parse_response_packets(
            self.services_response_packet)

        # Step 3
        if not ((caps_response_message.transaction_id
                 == caps_command_message.transaction_id) and
                (caps_response_message.device_service_id
                 == caps_command_message.device_service_id)
                and caps_response_message.cid == caps_command_message.cid and
                (services_command_message.transaction_id
                 == services_response_message.transaction_id) and
                (services_command_message.device_service_id
                 == services_response_message.device_service_id) and
                services_command_message.cid == services_response_message.cid):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:8.1.2#2')
예제 #5
0
    def run_internal(self):
        """ Run CM_13 test. """
        # Precondition
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
                self.test_context).run()
        connect_sequence.ConnectSequence(self.test_context).run()
        mbim_close_sequence.MBIMCloseSequence(self.test_context).run()
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
                self.test_context).run()

        # Step 1
        connect_info_structure = mbim_data.MBIMConnectInfoStructure(
                session_id=0,
                activation_state=0,
                voice_call_state=0,
                ip_type=0,
                context_type=mbim_constants.MBIM_CONTEXT_TYPE_NONE.bytes,
                nw_error=0)
        command_message = mbim_control.MBIMCommandMessage(
                message_length=84,
                total_fragments=1,
                current_fragment=0,
                device_service_id=mbim_constants.UUID_BASIC_CONNECT.bytes,
                cid=mbim_constants.MBIM_CID_CONNECT,
                command_type=mbim_constants.COMMAND_TYPE_QUERY,
                information_buffer_length=36,
                information_buffer=connect_info_structure.pack())
        packets = command_message.generate_packets()
        channel = mbim_channel.MBIMChannel(
                {'idVendor': self.test_context.id_vendor,
                 'idProduct': self.test_context.id_product},
                self.test_context.mbim_communication_interface.bInterfaceNumber,
                self.test_context.interrupt_endpoint.bEndpointAddress,
                self.test_context.mbim_functional.wMaxControlMessage)
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        # Step 2
        response_message = mbim_control.parse_response_packets(response_packets)

        # Step 3
        if (response_message.status_codes !=
            mbim_constants.MBIM_STATUS_CONTEXT_NOT_ACTIVATED):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.3.2#3')
예제 #6
0
    def run_internal(self):
        """ Run CM_08 test. """
        # Precondition
        descriptors = get_descriptors_sequence.GetDescriptorsSequence(
            self.device_context).run()
        self.device_context.update_descriptor_cache(descriptors)
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
            self.device_context).run()

        # Step 1
        device_context = self.device_context
        descriptor_cache = device_context.descriptor_cache
        command_message = mbim_message_request.MBIMCommand(
            device_service_id=mbim_constants.UUID_BASIC_CONNECT.bytes,
            cid=mbim_constants.MBIM_CID_RADIO_STATE,
            command_type=mbim_constants.COMMAND_TYPE_SET,
            information_buffer_length=4,
            payload_buffer=array.array('B', struct.pack('I', 2)))
        packets = mbim_message_request.generate_request_packets(
            command_message, device_context.max_control_transfer_size)
        channel = mbim_channel.MBIMChannel(
            device_context._device,
            descriptor_cache.mbim_communication_interface.bInterfaceNumber,
            descriptor_cache.interrupt_endpoint.bEndpointAddress,
            device_context.max_control_transfer_size)
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        # Step 2
        response_message = mbim_message_response.parse_response_packets(
            response_packets)

        # Step 3
        if ((response_message.message_type != mbim_constants.MBIM_COMMAND_DONE)
                or (response_message.status_codes
                    == mbim_constants.MBIM_STATUS_SUCCESS)
                or response_message.information_buffer_length != 0):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.5#3')
예제 #7
0
    def run_internal(self):
        """ Run CM_08 test. """
        # Precondition
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
            self.test_context).run()

        # Step 1
        command_message = mbim_control.MBIMCommandMessage(
            message_length=52,
            total_fragments=1,
            current_fragment=0,
            device_service_id=mbim_constants.UUID_BASIC_CONNECT.bytes,
            cid=mbim_constants.MBIM_CID_RADIO_STATE,
            command_type=mbim_constants.COMMAND_TYPE_SET,
            information_buffer_length=4,
            information_buffer=array.array('B', struct.pack('I', 2)))
        packets = command_message.generate_packets()
        channel = mbim_channel.MBIMChannel(
            {
                'idVendor': self.test_context.id_vendor,
                'idProduct': self.test_context.id_product
            }, self.test_context.mbim_communication_interface.bInterfaceNumber,
            self.test_context.interrupt_endpoint.bEndpointAddress,
            self.test_context.mbim_functional.wMaxControlMessage)
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        # Step 2
        response_message = mbim_control.parse_response_packets(
            response_packets)

        # Step 3
        if ((response_message.message_type != mbim_constants.MBIM_COMMAND_DONE)
                or (response_message.status_codes
                    == mbim_constants.MBIM_STATUS_SUCCESS)
                or response_message.information_buffer_length != 0):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.5#3')
예제 #8
0
    def run_internal(self):
        """ Run CM_07 test. """
        # Precondition
        descriptors = get_descriptors_sequence.GetDescriptorsSequence(
            self.device_context).run()
        self.device_context.update_descriptor_cache(descriptors)
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
            self.device_context).run()

        # Step 1
        # 255 is an unsupported CID.
        device_context = self.device_context
        descriptor_cache = device_context.descriptor_cache
        command_message = mbim_message_request.MBIMCommand(
            device_service_id=mbim_constants.UUID_BASIC_CONNECT.bytes,
            cid=255,
            command_type=mbim_constants.COMMAND_TYPE_QUERY,
            information_buffer_length=0)
        packets = mbim_message_request.generate_request_packets(
            command_message, device_context.max_control_transfer_size)
        channel = mbim_channel.MBIMChannel(
            device_context._device,
            descriptor_cache.mbim_communication_interface.bInterfaceNumber,
            descriptor_cache.interrupt_endpoint.bEndpointAddress,
            device_context.max_control_transfer_size)
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        # Step 2
        response_message = mbim_message_response.parse_response_packets(
            response_packets)

        # Step 3
        if (response_message.message_type != mbim_constants.MBIM_COMMAND_DONE
                or (response_message.status_codes !=
                    mbim_constants.MBIM_STATUS_NO_DEVICE_SUPPORT)):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.5#2')
예제 #9
0
    def run_internal(self):
        """ Run CM_07 test. """
        # Precondition
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
            self.test_context).run()

        # Step 1
        # 255 is an unsupported CID.
        command_message = mbim_control.MBIMCommandMessage(
            message_length=48,
            total_fragments=1,
            current_fragment=0,
            device_service_id=mbim_constants.UUID_BASIC_CONNECT.bytes,
            cid=255,
            command_type=mbim_constants.COMMAND_TYPE_QUERY,
            information_buffer_length=0)
        packets = command_message.generate_packets()
        channel = mbim_channel.MBIMChannel(
            {
                'idVendor': self.test_context.id_vendor,
                'idProduct': self.test_context.id_product
            }, self.test_context.mbim_communication_interface.bInterfaceNumber,
            self.test_context.interrupt_endpoint.bEndpointAddress,
            self.test_context.mbim_functional.wMaxControlMessage)
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        # Step 2
        response_message = mbim_control.parse_response_packets(
            response_packets)

        # Step 3
        if (response_message.message_type != mbim_constants.MBIM_COMMAND_DONE
                or (response_message.status_codes !=
                    mbim_constants.MBIM_STATUS_NO_DEVICE_SUPPORT)):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.5#2')
    def run_internal(self,
                     introduce_error_in_access_offset=False,
                     introduce_error_in_packets_order=None,
                     raise_exception_on_failure=True):
        """
        Run the Connect Sequence.

        Once the command message is sent, there should be at least one
        notification received apart from the command done message.

        @param introduce_error_in_access_offset: Whether to introduce an
                error in the access_string offset or not.
        @param introduce_error_in_packets_order: Whether to introduce an
                error in the order of packets sent or not. It's a user provided
                list of packet sequence numbers to reorder, repeat or remove
                packets generated for connect before sending it to the device.
        @param raise_exception_on_failure: Whether to raise an exception or not.
        @returns tuple of (command_message, response_message, notifications):
                command_message: The command message sent to device.
                |command_message| is a MBIMCommandMessage object.
                response_message: The response to the |command_message|.
                |response_message| is a MBIMCommandDoneMessage object.
                notifications: The list of notifications message sent from the
                modem to the host. |notifications| is a list of
                |MBIMIndicateStatusMessage| objects.
        """
        # Step 1
        # Send MBIM_COMMAND_MSG.
        context_type = mbim_constants.MBIM_CONTEXT_TYPE_INTERNET.bytes
        data_buffer = array.array('B', 'loopback'.encode('utf-16le'))
        information_buffer_length = (
            mbim_command_message.MBIMSetConnect.get_struct_len())
        information_buffer_length += len(data_buffer)
        device_context = self.device_context
        descriptor_cache = device_context.descriptor_cache
        if introduce_error_in_access_offset:
            access_string_offset = 0
        else:
            access_string_offset = 60
        command_message = (mbim_command_message.MBIMSetConnect(
            session_id=0,
            activation_command=1,
            access_string_offset=access_string_offset,
            access_string_size=16,
            user_name_offset=0,
            user_name_size=0,
            password_offset=0,
            password_size=0,
            compression=0,
            auth_protocol=0,
            ip_type=1,
            context_type=context_type,
            information_buffer_length=information_buffer_length,
            payload_buffer=data_buffer))
        packets = mbim_message_request.generate_request_packets(
            command_message, device_context.max_control_transfer_size)
        channel = mbim_channel.MBIMChannel(
            device_context._device,
            descriptor_cache.mbim_communication_interface.bInterfaceNumber,
            descriptor_cache.interrupt_endpoint.bEndpointAddress,
            device_context.max_control_transfer_size)
        if introduce_error_in_packets_order is not None:
            packets = [packets[i] for i in introduce_error_in_packets_order]
        response_packets = channel.bidirectional_transaction(*packets)
        notifications_packets = channel.get_outstanding_packets()
        channel.close()

        # Step 2
        response_message = mbim_message_response.parse_response_packets(
            response_packets)
        notifications = []
        for notification_packets in notifications_packets:
            notifications.append(
                mbim_message_response.parse_response_packets(
                    notification_packets))

        # Step 3
        if (response_message.message_type != mbim_constants.MBIM_COMMAND_DONE
                or response_message.status_codes !=
                mbim_constants.MBIM_STATUS_SUCCESS):
            if raise_exception_on_failure:
                mbim_errors.log_and_raise(
                    mbim_errors.MBIMComplianceSequenceError,
                    'Connect sequence failed.')

        return command_message, response_message, notifications
예제 #11
0
    def run_internal(self,
                     max_control_transfer_size=None,
                     ntb_format=mbim_constants.NTB_FORMAT_32):
        """
        Run the MBIM Open Generic Sequence.

        @param max_control_transfer_size: Sets the max_control_transfer
                parameter in the open message sent to the device and the size
                of control buffers sent to the device.
        @param ntb_format: Sets the NTB type to 16 bit vs 32 bit. This will only
                be set on devices which support both 32 bit NTB and 16 bit NTB.
        @returns tuple of (command_message, response_message):
                command_message: The command message sent to device.
                |command_message| is a MBIMCommandMessage object.
                response_message: The response to the |command_message|.
                |response_message| is a MBIMCommandDoneMessage object.
        """
        # Step 1 and 2
        device_context = self.device_context
        device_type = device_context.device_type
        mbim_communication_interface = (
            device_context.descriptor_cache.mbim_communication_interface)
        ncm_communication_interface = (
            device_context.descriptor_cache.ncm_communication_interface)
        no_data_data_interface = (
            device_context.descriptor_cache.no_data_data_interface)
        ncm_data_interface = (
            device_context.descriptor_cache.ncm_data_interface)
        mbim_data_interface = (
            device_context.descriptor_cache.mbim_data_interface)
        mbim_functional_descriptor = (
            device_context.descriptor_cache.mbim_functional)
        interrupt_endpoint = (
            device_context.descriptor_cache.interrupt_endpoint)
        descriptor_cache = device_context.descriptor_cache

        communication_interface_number = (
            mbim_communication_interface.bInterfaceNumber)
        data_interface_number = mbim_data_interface.bInterfaceNumber

        # Step 3
        # Set alternate setting to be 0 for MBIM only data interface and
        # NCM/MBIM data interface.
        self.detach_kernel_driver_if_active(data_interface_number)
        self.set_alternate_setting(data_interface_number, 0)

        # Step 4
        # Set alternate setting to be 1 for MBIM communication interface of
        # NCM/MBIM function.
        if device_type == mbim_device_context.DEVICE_TYPE_NCM_MBIM:
            self.set_alternate_setting(communication_interface_number, 1)

        # Step 5
        # Send a RESET_FUNCTION(0x05) request to reset communication interface.
        self.reset_function(communication_interface_number)

        # Step 6
        # Send GetNtbParameters() request to communication interface.
        ntb_parameters = self.get_ntb_parameters(
            mbim_communication_interface.bInterfaceNumber)

        # Step 7
        # Send SetNtbFormat() request to communication interface.
        # Bit 1 of |bmNtbForatsSupported| indicates whether the device
        # supports 32-bit NTBs.
        if (ntb_parameters.bmNtbFormatsSupported >> 1) & 1:
            self.set_ntb_format(communication_interface_number, ntb_format)

        # Step 8
        # Send SetNtbInputSize() request to communication interface.
        self.set_ntb_input_size(communication_interface_number,
                                ntb_parameters.dwNtbInMaxSize)

        # Step 9
        # Send SetMaxDatagramSize() request to communication interface.
        # Bit 3 determines whether the device can process SetMaxDatagramSize()
        # and GetMaxDatagramSize() requests.
        if (mbim_functional_descriptor.bmNetworkCapabilities >> 3) & 1:
            self.set_max_datagram_size(communication_interface_number)

        # Step 10
        if device_type == mbim_device_context.DEVICE_TYPE_MBIM:
            alternate_setting = 1
        else:
            alternate_setting = 2
        self.set_alternate_setting(data_interface_number, alternate_setting)

        # Step 11 and 12
        # Send MBIM_OPEN_MSG request and receive the response.
        interrupt_endpoint_address = interrupt_endpoint.bEndpointAddress

        # If |max_control_transfer_size| is not explicitly set by the test,
        # we'll revert to using the |wMaxControlMessage| advertized by the
        # device in the MBIM functional descriptor.
        if not max_control_transfer_size:
            max_control_transfer_size = (
                mbim_functional_descriptor.wMaxControlMessage)
        open_message = mbim_message_request.MBIMOpen(
            max_control_transfer=max_control_transfer_size)
        packets = mbim_message_request.generate_request_packets(
            open_message, max_control_transfer_size)
        channel = mbim_channel.MBIMChannel(device_context._device,
                                           communication_interface_number,
                                           interrupt_endpoint_address,
                                           max_control_transfer_size)
        response_packets = channel.bidirectional_transaction(*packets)
        channel.close()

        # Step 13
        # Verify if MBIM_OPEN_MSG request succeeds.
        response_message = mbim_message_response.parse_response_packets(
            response_packets)

        if response_message.transaction_id != open_message.transaction_id:
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.4.1#1')

        if response_message.status_codes != mbim_constants.MBIM_STATUS_SUCCESS:
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceSequenceError,
                                      'mbim1.0:9.4.1#2')

        # Store data/control transfer parameters in the device context so that
        # it can be used in any further control/data transfers.
        device_context.max_control_transfer_size = max_control_transfer_size
        device_context.current_ntb_format = self.get_ntb_format(
            communication_interface_number)
        device_context.max_in_data_transfer_size = (
            ntb_parameters.dwNtbInMaxSize)
        device_context.max_out_data_transfer_size = (
            ntb_parameters.dwNtbOutMaxSize)
        device_context.out_data_transfer_divisor = (
            ntb_parameters.wNdpOutDivisor)
        device_context.out_data_transfer_payload_remainder = (
            ntb_parameters.wNdpOutPayloadRemainder)
        device_context.out_data_transfer_ndp_alignment = (
            ntb_parameters.wNdpOutAlignment)

        return open_message, response_message
예제 #12
0
    def run_internal(self):
        """ Run CM_05 test. """
        # Precondition
        descriptors = get_descriptors_sequence.GetDescriptorsSequence(
            self.device_context).run()
        self.device_context.update_descriptor_cache(descriptors)
        mbim_open_generic_sequence.MBIMOpenGenericSequence(
            self.device_context).run()

        device_context = self.device_context
        descriptor_cache = device_context.descriptor_cache
        self.channel = mbim_channel.MBIMChannel(
            device_context._device,
            descriptor_cache.mbim_communication_interface.bInterfaceNumber,
            descriptor_cache.interrupt_endpoint.bEndpointAddress,
            device_context.max_control_transfer_size)

        # Step 1
        caps_command_message = mbim_command_message.MBIMDeviceCapsQuery()
        caps_packets = mbim_message_request.generate_request_packets(
            caps_command_message, device_context.max_control_transfer_size)
        self.caps_transaction_id = caps_command_message.transaction_id
        self.channel.unidirectional_transaction(*caps_packets)

        # Step 2
        services_command_message = (
            mbim_command_message.MBIMDeviceServicesQuery())
        services_packets = mbim_message_request.generate_request_packets(
            services_command_message, device_context.max_control_transfer_size)
        self.services_transaction_id = services_command_message.transaction_id
        self.channel.unidirectional_transaction(*services_packets)

        # Step 3
        utils.poll_for_condition(
            self._get_response_packets,
            timeout=5,
            exception=mbim_errors.MBIMComplianceChannelError(
                'Failed to retrieve the response packets to specific '
                'control messages.'))
        self.channel.close()

        caps_response_message = self.caps_response
        services_response_message = self.services_response
        is_caps_message_valid = isinstance(
            caps_response_message, mbim_command_message.MBIMDeviceCapsInfo)
        is_services_message_valid = isinstance(
            services_response_message,
            mbim_command_message.MBIMDeviceServicesInfo)
        if not ((is_caps_message_valid and is_services_message_valid) and
                (caps_response_message.transaction_id
                 == caps_command_message.transaction_id) and
                (caps_response_message.device_service_id
                 == caps_command_message.device_service_id)
                and caps_response_message.cid == caps_command_message.cid and
                (services_command_message.transaction_id
                 == services_response_message.transaction_id) and
                (services_command_message.device_service_id
                 == services_response_message.device_service_id) and
                services_command_message.cid == services_response_message.cid):
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:8.1.2#2')