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
    def _get_response_packets(self):
        """
        Condition method for |poll_for_condition| to check the retrieval of
        target packets.

        @returns True if both caps response packet and services response packet
                are received, False otherwise.

        """
        try:
            packets = self.channel.get_outstanding_packets()
        except mbim_errors.MBIMComplianceChannelError:
            logging.debug(
                "Error in receiving response fragments from the device")
            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
                                      'mbim1.0:9.5#1')
        self.caps_response = None
        self.services_response = None
        for packet in packets:
            try:
                message_response = mbim_message_response.parse_response_packets(
                    packet)
            except mbim_errors.MBIMComplianceControlMessageError:
                logging.debug(
                    "Error in parsing response fragments from the device")
                mbim_errors.log_and_raise(
                    mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.5#1')
            if message_response.transaction_id == self.caps_transaction_id:
                self.caps_response = message_response
            elif (message_response.transaction_id ==
                  self.services_transaction_id):
                self.services_response = message_response
            if self.caps_response and self.services_response:
                return True
        return False
예제 #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 test_parse_mbim_close_done(self):
     """
     Verifies the packets of |MBIM_OPEN_DONE| type are parsed correctly.
     """
     packets = [array.array('B', [0x02, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                                  0x00, 0x00])]
     message = mbim_message_response.parse_response_packets(packets)
     self.assertEqual(True, isinstance(message,
             mbim_message_response.MBIMCloseDone))
     self.assertEqual(message.message_type, mbim_constants.MBIM_CLOSE_DONE)
     self.assertEqual(message.message_length, 16)
     self.assertEqual(message.transaction_id, 1)
     self.assertEqual(message.status_codes,
                      mbim_constants.MBIM_STATUS_SUCCESS)
예제 #5
0
 def test_parse_mbim_function_error_msg(self):
     """
     Verifies the |MBIM_FUNCTION_ERROR_MSG| packets are parsed correctly.
     """
     packets = [array.array('B', [0x04, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00,
                                  0x00, 0x00])]
     message = mbim_message_response.parse_response_packets(packets)
     self.assertEqual(True, isinstance(message,
             mbim_message_response.MBIMFunctionError))
     self.assertEqual(message.message_type,
                      mbim_constants.MBIM_FUNCTION_ERROR_MSG)
     self.assertEqual(message.message_length, 16)
     self.assertEqual(message.transaction_id, 1)
     self.assertEqual(message.error_status_code,
                      mbim_constants.MBIM_ERROR_UNKNOWN)
예제 #6
0
    def _get_response_packets(self):
        """
        Condition method for |poll_for_condition| to check the retrieval of
        target packets.

        @returns True if both caps response packet and services response packet
                are received, False otherwise.

        """
        packets = self.channel.get_outstanding_packets()
        self.caps_response = None
        self.services_response = None
        for packet in packets:
            message_response = mbim_message_response.parse_response_packets(
                packet)
            if message_response.transaction_id == self.caps_transaction_id:
                self.caps_response = message_response
            elif message_response.transaction_id == self.services_transaction_id:
                self.services_response = message_response
            if self.caps_response and self.services_response:
                return True
        return False
예제 #7
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')
예제 #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 test_parse_mbim_command_done(self):
     """
     Verifies the packets of |MBIM_COMMAND_DONE| type are parsed correctly.
     This tests both the fragmentation reassembly and message parsing
     functionality.
     """
     packets = [array.array('B', [0x03, 0x00, 0x00, 0x80, 0x34, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
                                  0x00, 0x06, 0xEE, 0x00, 0x00, 0x00, 0x00,
                                  0x80, 0x40, 0x20, 0x10, 0x00, 0xAA, 0xBB,
                                  0xCC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                                  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01,
                                  0x01, 0x01, 0x01]),
                array.array('B', [0x03, 0x00, 0x00, 0x80, 0x18, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
                                  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
                                  0x01, 0x01, 0x01])]
     message = mbim_message_response.parse_response_packets(packets)
     is_instance = isinstance(message,
                              mbim_message_response.MBIMCommandDone)
     self.assertEqual(is_instance, True)
     self.assertEqual(message.message_type, mbim_constants.MBIM_COMMAND_DONE)
     self.assertEqual(message.message_length, 56)
     self.assertEqual(message.transaction_id, 1)
     self.assertEqual(message.total_fragments, 2)
     self.assertEqual(message.current_fragment, 0)
     self.assertEqual(message.device_service_id,
                      '\x02\x00\x06\xEE\x00\x00\x00\x00\x80\x40\x20\x10'
                      '\x00\xAA\xBB\xCC')
     self.assertEqual(message.cid, 1)
     self.assertEqual(message.status_codes,
                      mbim_constants.MBIM_STATUS_SUCCESS)
     self.assertEqual(message.information_buffer_length, 8)
     self.assertEqual(message.payload_buffer,
                      array.array('B', [0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                                        0x01, 0x01]))
    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 test_parse_mbim_get_device_caps(self):
     """
     Verifies the packets of |MBIM_COMMAND_DONE| type for a GetDeviceCaps
     CID query are parsed correctly.
     This tests both the fragmentation reassembly and message parsing
     functionality.
     """
     packets = [array.array('B', [0x03, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,
                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2,
                                  0x89, 0xCC, 0x33, 0xBC, 0xBB, 0x8B, 0x4F,
                                  0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6,
                                  0xDF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                                  0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x01,
                                  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
                                  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
                                  0x0]),
                array.array('B', [0x03, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,
                                  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F,
                                  0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00,
                                  0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
                                  0x00, 0x40, 0x00, 0x00, 0x00, 0x0A, 0x00,
                                  0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x1E,
                                  0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
                                  0x1E, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00,
                                  0x00]),
                array.array('B', [0x03, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,
                                  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12,
                                  0x00, 0x00, 0x00, 0x48, 0x00, 0x53, 0x00,
                                  0x50, 0x00, 0x41, 0x00, 0x2B, 0x00, 0x00,
                                  0x00, 0x33, 0x00, 0x35, 0x00, 0x31, 0x00,
                                  0x38, 0x00, 0x35, 0x00, 0x31, 0x00, 0x30,
                                  0x00, 0x36, 0x00, 0x30, 0x00, 0x30, 0x00,
                                  0x30, 0x00, 0x30, 0x00, 0x37, 0x00, 0x38,
                                  0x00]),
                array.array('B', [0x03, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,
                                  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34,
                                  0x00, 0x00, 0x00, 0x31, 0x00, 0x31, 0x00,
                                  0x2E, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30,
                                  0x00, 0x2E, 0x00, 0x31, 0x00, 0x36, 0x00,
                                  0x2E, 0x00, 0x30, 0x00, 0x34, 0x00, 0x2E,
                                  0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00,
                                  0x4D, 0x00, 0x4C, 0x00, 0x31, 0x00, 0x4D,
                                  0x0]),
                array.array('B', [0x03, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
                                  0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,
                                  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x45,
                                  0x00, 0x39, 0x00, 0x33, 0x00, 0x36, 0x00,
                                  0x4D, 0x00, 0x00, 0x00])]
     message = mbim_message_response.parse_response_packets(packets)
     is_instance = isinstance(message,
                              mbim_command_message.MBIMDeviceCapsInfo)
     self.assertEqual(is_instance, True)
     self.assertEqual(message.message_type, mbim_constants.MBIM_COMMAND_DONE)
     self.assertEqual(message.message_length, 208)
     self.assertEqual(message.transaction_id, 1)
     self.assertEqual(message.total_fragments, 5)
     self.assertEqual(message.current_fragment, 0)
     self.assertEqual(message.device_service_id,
                      '\xA2\x89\xCC3\xBC\xBB\x8BO\xB6\xB0\x13>\xC2\xAA\xE6'
                      '\xDF')
     self.assertEqual(message.cid, 1)
     self.assertEqual(message.status_codes,
                      mbim_constants.MBIM_STATUS_SUCCESS)
     self.assertEqual(message.information_buffer_length, 160)
     self.assertEqual(message.device_type, 1)
     self.assertEqual(message.cellular_class, 1)
     self.assertEqual(message.voice_class, 1)
     self.assertEqual(message.sim_class, 2)
     self.assertEqual(message.data_class, 2147483679)
     self.assertEqual(message.sms_caps, 3)
     self.assertEqual(message.control_caps, 3)
     self.assertEqual(message.max_sessions, 8)
     self.assertEqual(message.custom_data_class_offset, 64)
     self.assertEqual(message.custom_data_class_size, 10)
     self.assertEqual(message.device_id_offset, 76)
     self.assertEqual(message.device_id_size, 30)
     self.assertEqual(message.firmware_info_offset, 108)
     self.assertEqual(message.firmware_info_size, 30)
     self.assertEqual(message.hardware_info_offset, 140)
     self.assertEqual(message.hardware_info_size, 18)