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
Esempio n. 2
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
Esempio n. 3
0
 def test_generate_mbim_open(self):
     """
     Verifies the raw packet of |MBIM_OPEN| type is generated correctly.
     """
     message = mbim_message_request.MBIMOpen(max_control_transfer=40)
     packets = mbim_message_request.generate_request_packets(message, 64)
     self.assertEqual(packets, [array.array('B', [0x01, 0x00, 0x00, 0x00,
                                                  0x10, 0x00, 0x00, 0x00,
                                                  0x02, 0x00, 0x00, 0x00,
                                                  0x28, 0x00, 0x00, 0x00])])
Esempio n. 4
0
 def test_generate_mbim_command_packets(self):
     """
     Verifies the raw packets of |MBIM_COMMAND| type are generated correctly.
     This verifies the fragmentation logic in the generate_request_packets.
     """
     payload_buffer=array.array('B', [0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
                                      0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
                                      0x28, 0x00, 0x00, 0x00, 0x04, 0x05,
                                      0x06, 0x10, 0x87, 0xDE, 0xED, 0xAC,
                                      0x45, 0x35, 0x50, 0x60, 0x90, 0xED,
                                      0xAB])
     message = mbim_message_request.MBIMCommand(
             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=len(payload_buffer),
             payload_buffer=payload_buffer)
     packets = mbim_message_request.generate_request_packets(message, 64)
     self.assertEqual(packets, [array.array('B', [0x03, 0x00, 0x00, 0x00,
                                                  0x40, 0x00, 0x00, 0x00,
                                                  0x01, 0x00, 0x00, 0x00,
                                                  0x02, 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,
                                                  0x1F, 0x00, 0x00, 0x00,
                                                  0x01, 0x00, 0x00, 0x00,
                                                  0x10, 0x00, 0x00, 0x00,
                                                  0x01, 0x00, 0x00, 0x00,
                                                  0x28, 0x00, 0x00, 0x00]),
                                array.array('B', [0x03, 0x00, 0x00, 0x00,
                                                  0x23, 0x00, 0x00, 0x00,
                                                  0x01, 0x00, 0x00, 0x00,
                                                  0x02, 0x00, 0x00, 0x00,
                                                  0x01, 0x00, 0x00, 0x00,
                                                  0x04, 0x05, 0x06, 0x10,
                                                  0x87, 0xDE, 0xED, 0xAC,
                                                  0x45, 0x35, 0x50, 0x60,
                                                  0x90, 0xED, 0xAB])])
Esempio n. 5
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')
Esempio n. 6
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')
    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
Esempio n. 8
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
Esempio n. 9
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')