def run_precondition(self, ntb_format): """ Runs all the precondition sequences for data transfer tests. @param ntb_format: Whether to send/receive an NTB16 or NTB32 frame. Possible values: NTB_FORMAT_16, NTB_FORMAT_32 (mbim_constants) @returns tuple of (desc_sequence, open_sequence, connect_sequence) where, desc_sequence - Handle to run the get descriptor sequence. open_sequence - Handle to run the open sequence. connect_sequence - Handle to run the connect sequence. """ desc_sequence = get_descriptors_sequence.GetDescriptorsSequence( self.device_context) descriptors = desc_sequence.run() self.device_context.update_descriptor_cache(descriptors) open_sequence = mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context) open_sequence.run(ntb_format=ntb_format) connect_seq = connect_sequence.ConnectSequence(self.device_context) connect_seq.run() # Devices may not support SetNtbFormat(), so fail the NTB32 tests on # such devices. if ((ntb_format == mbim_constants.NTB_FORMAT_32) and (self.device_context.current_ntb_format != ntb_format)): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceFrameworkError, 'Device does not support NTB 32 format.') return (desc_sequence, open_sequence, connect_seq)
def run_internal(self): """ Run the CM_01 test. """ # Precondition. descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() self.device_context.update_descriptor_cache(descriptors) # Step 1 open_message, response_message = ( mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context).run())
def run_internal(self): """ Run CM_10 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 close_message, response_message = mbim_close_sequence.MBIMCloseSequence( self.device_context).run()
def run_internal(self): """ Run CM_06 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 _, response_message = ( mbim_cid_device_caps_sequence.MBIMCIDDeviceCapsSequence( self.device_context).run()) if response_message.status_codes != mbim_constants.MBIM_STATUS_SUCCESS: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.4.5#1')
def run_internal(self): """ Run the CM_02 test. """ # Precondition. descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() self.device_context.update_descriptor_cache(descriptors) # Step 1 _, response_message = ( mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context).run()) # Validate message length of response to MBIM_OPEN_MESSAGE. if response_message.message_length < 0x0C: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.1#2')
def run_internal(self): """ Run CM_04 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 command_message, response_message = ( mbim_cid_device_caps_sequence.MBIMCIDDeviceCapsSequence( self.device_context).run()) # Validate |transaction_id| in the response to MBIM_COMMAND_MSG. if response_message.transaction_id != command_message.transaction_id: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.4.3')
def run_internal(self): """ Run CM_15 test. """ # Precondition descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() self.device_context.update_descriptor_cache(descriptors) open_sequence = mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context) open_sequence.run(max_control_transfer_size=64) # Step 1 caps_sequence = mbim_cid_device_caps_sequence.MBIMCIDDeviceCapsSequence( self.device_context) _, response_message = caps_sequence.run() if not isinstance(response_message, mbim_command_message.MBIMDeviceCapsInfo): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.2')
def run_internal(self): """ Run CM_03 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 _, response_message = ( mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context).run()) # Validate function's behaviour for an unsynchronized MBIM_OPEN_MSG. if response_message.message_type == mbim_constants.MBIM_CLOSE_DONE: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.3.1#1')
def run_internal(self): """ Run CM_09 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 _, _, notifications = (connect_sequence.ConnectSequence( self.device_context).run()) # Step 2 for notification in notifications: if notification.transaction_id != 0: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.1#1')
def run_internal(self): """ Run CM_14 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() mbim_close_sequence.MBIMCloseSequence(self.device_context).run() # Step 1 _, response_message, _ = (connect_sequence.ConnectSequence( self.device_context).run(raise_exception_on_failure=False)) # Step 2 if ((response_message.message_type != mbim_constants.MBIM_FUNCTION_ERROR_MSG) or (response_message.message_length != 16)): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.3.4#2')
def run_internal(self): """ Run ERR_04 test. """ # Precondition descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() self.device_context.update_descriptor_cache(descriptors) open_sequence = mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context) open_sequence.run(max_control_transfer_size=64) # Step 1 request_message, response_message, _ = ( connect_sequence.ConnectSequence(self.device_context).run( introduce_error_in_packets_order=[1, 0, 2], raise_exception_on_failure=False)) # Step 2 if ((response_message.transaction_id != request_message.transaction_id) or (response_message.message_type == mbim_constants.MBIM_COMMAND_DONE)): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.3.4.2#3')
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')
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): """ Run ERR_02 test. """ # Precondition descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() self.device_context.update_descriptor_cache(descriptors) open_sequence = mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context) open_sequence.run(max_control_transfer_size=64) # Step 1 request_message, response_message, _ = ( connect_sequence.ConnectSequence(self.device_context).run( introduce_error_in_packets_order=[1, 0, 2], raise_exception_on_failure=False)) # Step 2 if ((response_message.message_type != mbim_constants.MBIM_FUNCTION_ERROR_MSG) or (response_message.error_status_code != mbim_constants.MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE)): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.3.4#3')
def run_internal(self): """ Run ERR_05 test. """ # Precondition descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() self.device_context.update_descriptor_cache(descriptors) open_sequence = mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context) open_sequence.run(max_control_transfer_size=64) # Step 1 request_message, first_response_message, notifications = ( connect_sequence.ConnectSequence(self.device_context).run( introduce_error_in_packets_order=[1, 1], raise_exception_on_failure=False)) if len(notifications) > 1: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceTestError, 'Not expecting more than 1 pending response.') second_response_message = notifications[0] # Step 2 if (((first_response_message.transaction_id != request_message.transaction_id) or (first_response_message.message_type != mbim_constants.MBIM_FUNCTION_ERROR_MSG) or (first_response_message.error_status_code != mbim_constants.MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE)) or ((second_response_message.transaction_id != request_message.transaction_id) or (second_response_message.message_type != mbim_constants.MBIM_FUNCTION_ERROR_MSG) or (second_response_message.error_status_code != mbim_constants.MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE))): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:9.3.4.2#4')
def run_internal(self): """ Run the CM_01 test. """ # Precondition. desc_sequence = get_descriptors_sequence.GetDescriptorsSequence( self.device_context) descriptors = desc_sequence.run() self.device_context.update_descriptor_cache(descriptors) open_sequence = mbim_open_generic_sequence.MBIMOpenGenericSequence( self.device_context) open_sequence.run() caps_sequence = mbim_cid_device_caps_sequence.MBIMCIDDeviceCapsSequence( self.device_context) _, caps_response = caps_sequence.run() # Step1 if (caps_response.cellular_class & mbim_constants.CELLULAR_CLASS_MASK_CDMA): if not ((caps_response.control_caps & mbim_constants.CTRL_CAPS_MASK_CDMA_MOBILE_IP) or (caps_response.control_caps & mbim_constants.CTRL_CAPS_MASK_CDMA_SIMPLE_IP)): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:10.5.1.3#1')
def run_internal(self): """ Run the DES_01 test. """ # Precondition. descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() # Test step 1 # Get ncm communication interface and mbim communication interface. interfaces = usb_descriptors.filter_descriptors( usb_descriptors.InterfaceDescriptor, descriptors) ncm_communication_interfaces = ( usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.NCM_MBIM_COMMUNICATION_INTERFACE_NCM)) mbim_communication_interfaces = ( usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.NCM_MBIM_COMMUNICATION_INTERFACE_MBIM)) # If we don't find both NCM and MBIM interfaces, then we should bail # out of this test if (not ncm_communication_interfaces or not mbim_communication_interfaces): return if len(ncm_communication_interfaces) != 1: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.1#2') ncm_communication_interface = ncm_communication_interfaces[0] if len(mbim_communication_interfaces) != 1: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.1#3') mbim_communication_interface = mbim_communication_interfaces[0] if (ncm_communication_interface.bInterfaceNumber != mbim_communication_interface.bInterfaceNumber): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.1#1') # Test step 2 if (ncm_communication_interface.index > mbim_communication_interface.index): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Alternate setting 1 of the interface must appear after' 'alternate setting 0 of the interface.') # Test step 3 # Get header functional descriptor, union functinoal descriptor, # MBIM functinoal descriptor and MBIM extended functional # descriptor from |ncm_communication_interface|[0]. ncm_communication_interface_bundle = ( usb_descriptors.get_descriptor_bundle(descriptors, ncm_communication_interface)) header_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.HeaderFunctionalDescriptor, ncm_communication_interface_bundle) union_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.UnionFunctionalDescriptor, ncm_communication_interface_bundle) mbim_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.MBIMFunctionalDescriptor, ncm_communication_interface_bundle) mbim_extended_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.MBIMExtendedFunctionalDescriptor, ncm_communication_interface_bundle) if not (header_descriptors and union_descriptors and mbim_descriptors): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#2') # Test step 4 # Check header funcional descriptor. if usb_descriptors.has_distinct_descriptors(header_descriptors): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 unique header functional descriptor.') header_descriptor = header_descriptors[0] if not (header_descriptor.bDescriptorType == 0x24 and header_descriptor.bDescriptorSubtype == 0x00 and header_descriptor.bLength == 5 and header_descriptor.bcdCDC >= 0x0120): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Header functional descriptor: wrong value(s)') # Test step 5 # Check union functional descriptor. if usb_descriptors.has_distinct_descriptors(union_descriptors): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 unique union functional descriptor.') union_descriptor = union_descriptors[0] if union_descriptor.index < header_descriptor.index: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#3') # Get no data data interface. no_data_data_interfaces = usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.NCM_MBIM_DATA_INTERFACE_NO_DATA) if len(no_data_data_interfaces) != 1: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#2') no_data_data_interface = no_data_data_interfaces[0] no_data_data_interface_bundle = usb_descriptors.get_descriptor_bundle( descriptors, no_data_data_interface) endpoint_descriptors = (usb_descriptors.filter_descriptors( usb_descriptors.EndpointDescriptor, no_data_data_interface_bundle)) if endpoint_descriptors: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#4') # Get NCM data interface. ncm_data_interfaces = (usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.NCM_MBIM_DATA_INTERFACE_NCM)) if len(ncm_data_interfaces) != 1: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#2') ncm_data_interface = ncm_data_interfaces[0] if ncm_data_interface.bNumEndpoints != 2: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#4') ncm_data_interface_bundle = (usb_descriptors.get_descriptor_bundle( descriptors, ncm_data_interface)) endpoint_descriptors = (usb_descriptors.filter_descriptors( usb_descriptors.EndpointDescriptor, ncm_data_interface_bundle)) # Check endpoint descriptors in |ncm_data_interface_bundle| # There should be one bulk OUT and one bulk IN. if not usb_descriptors.has_bulk_in_and_bulk_out(endpoint_descriptors): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#4') # Get MBIM data interface. mbim_data_interfaces = usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.NCM_MBIM_DATA_INTERFACE_MBIM) if len(mbim_data_interfaces) != 1: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#3') mbim_data_interface = mbim_data_interfaces[0] if mbim_data_interface.bNumEndpoints != 2: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#4') mbim_data_interface_bundle = (usb_descriptors.get_descriptor_bundle( descriptors, mbim_data_interface)) endpoint_descriptors = (usb_descriptors.filter_descriptors( usb_descriptors.EndpointDescriptor, mbim_data_interface_bundle)) # Check endpoint descriptors in |mbim_data_interface_bundle| # alternate setting 2. There should be one bulk OUT and one bulk IN. if not usb_descriptors.has_bulk_in_and_bulk_out(endpoint_descriptors): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#4') if not (no_data_data_interface.bInterfaceNumber == ncm_data_interface.bInterfaceNumber == mbim_data_interface.bInterfaceNumber): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:3.2.2.4#1') if not (union_descriptor.bLength == 5 and union_descriptor.bControlInterface == (ncm_communication_interface.bInterfaceNumber) and union_descriptors.bSubordinateInterface0 == (no_data_data_interface.bInterfaceNumber)): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#4')
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')
def run_internal(self): """ Run the DES_02 test. """ # Precondition. descriptors = get_descriptors_sequence.GetDescriptorsSequence( self.device_context).run() # Test step 1 # Get MBIM communication interface. interfaces = usb_descriptors.filter_descriptors( usb_descriptors.InterfaceDescriptor, descriptors) mbim_communication_interfaces = ( usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.MBIM_ONLY_COMMUNICATION_INTERFACE)) if not mbim_communication_interfaces: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#1') if len(mbim_communication_interfaces) > 1: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 mbim communication interface, got %d.' % (len(mbim_communication_interfaces))) mbim_communication_interface = mbim_communication_interfaces[0] # Test step 2 # Get header functional descriptor, union functional descriptor, # MBIM functional descriptor and MBIM extended functional # descriptor. mbim_communication_interface_bundle = ( usb_descriptors.get_descriptor_bundle( descriptors, mbim_communication_interface)) header_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.HeaderFunctionalDescriptor, mbim_communication_interface_bundle) union_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.UnionFunctionalDescriptor, mbim_communication_interface_bundle) mbim_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.MBIMFunctionalDescriptor, mbim_communication_interface_bundle) mbim_extended_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.MBIMExtendedFunctionalDescriptor, mbim_communication_interface_bundle) if not (header_descriptors and union_descriptors and mbim_descriptors): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#2') # Test step 3 # Check header functional descriptor. if usb_descriptors.has_distinct_descriptors(header_descriptors): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 unique header functional descriptor.') header_descriptor = header_descriptors[0] if not (header_descriptor.bDescriptorType == 0x24 and header_descriptor.bDescriptorSubtype == 0x00 and header_descriptor.bLength == 5 and header_descriptor.bcdCDC >= 0x0120): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Header functional descriptor: wrong value(s)') # Test step 4 # Check union functional descriptor. if usb_descriptors.has_distinct_descriptors(union_descriptors): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenerisAssertionError, 'Expected 1 unique union functional descriptor.') union_descriptor = union_descriptors[0] if union_descriptor.index < header_descriptor.index: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#3') # Get CDC no data data interface. no_data_data_interfaces = usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.MBIM_ONLY_DATA_INTERFACE_NO_DATA) if not no_data_data_interfaces: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.6#4') if len(no_data_data_interfaces) > 1: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Exactly 1 CDC data interface, got %d.' % (len(no_data_data_interfaces))) no_data_data_interface = no_data_data_interfaces[0] no_data_data_interface_bundle = usb_descriptors.get_descriptor_bundle( descriptors, no_data_data_interface) data_endpoint_descriptors = (usb_descriptors.filter_descriptors( usb_descriptors.EndpointDescriptor, no_data_data_interface_bundle)) if data_endpoint_descriptors: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.6#2') # Get MBIM data interface. mbim_data_interfaces = usb_descriptors.filter_interface_descriptors( interfaces, usb_descriptors.MBIM_ONLY_DATA_INTERFACE_MBIM) if not mbim_data_interfaces: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.6#4') if len(mbim_data_interfaces) > 1: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 MBIM data interface, got %d.' % (len(mbim_data_interfaces))) mbim_data_interface = mbim_data_interfaces[0] # Check if there are two endpoint descriptors. if mbim_data_interface.bNumEndpoints != 2: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.6#3.') mbim_data_interface_bundle = usb_descriptors.get_descriptor_bundle( descriptors, mbim_data_interface) data_endpoint_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.EndpointDescriptor, mbim_data_interface_bundle) # Check the values of fields in endpoint descriptors. # There should be one bulk OUT and one bulk IN. if not usb_descriptors.has_bulk_in_and_bulk_out( data_endpoint_descriptors): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.6#3') # MBIM cdc data interface should have both no data data interface and # MBIM data interface. Therefore two interface numbers should be # the same. if (no_data_data_interface.bInterfaceNumber != mbim_data_interface.bInterfaceNumber): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.6#1') # Check the fields of union functional descriptor if not (union_descriptor.bLength == 5 and (union_descriptor.bControlInterface == mbim_communication_interface.bInterfaceNumber) and (union_descriptor.bSubordinateInterface0 == mbim_data_interface.bInterfaceNumber)): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#4') # Test step 5 # Get MBIM functional descriptor. if usb_descriptors.has_distinct_descriptors(mbim_descriptors): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 unique MBIM functional descriptor.') mbim_descriptor = mbim_descriptors[0] if mbim_descriptor.index < header_descriptor.index: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#3') if mbim_descriptor.bLength != 12: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.4#5') if mbim_descriptor.bcdMBIMVersion != 0x0100: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.4#6') if mbim_descriptor.wMaxControlMessage < 64: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.4#1') if mbim_descriptor.bNumberFilters < 16: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.4#2') if mbim_descriptor.bMaxFilterSize > 192: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.4#3') # TODO(mcchou): Most of vendors set wMaxSegmentSize to be less than # 1500, so this assertion is skipped for now. # #if not mbim_descriptor.wMaxSegmentSize >= 2048: # mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, # 'mbim1.0:6.4#4') # Use a byte as the mask to check if D0, D1, D2, D4, D6 and D7 are # zeros. if (mbim_descriptor.bmNetworkCapabilities & 0b11010111) > 0: mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.4#7') # Test step 6 # Get MBIM extended functional descriptor, which is optional. if len(mbim_extended_descriptors) >= 1: if usb_descriptors.has_distinct_descriptors( mbim_extended_descriptors): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenerisAssertionError, 'Expected 1 unique MBIM extended functional ' 'descriptor.') mbim_extended_descriptor = mbim_extended_descriptors[0] if mbim_extended_descriptor.index < mbim_descriptor.index: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.5#1') if mbim_extended_descriptor.bLength != 8: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.5#2') if mbim_extended_descriptor.bcdMBIMExtendedVersion != 0x0100: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.5#3') if mbim_extended_descriptor.bMaxOutstandingCommandMessages == 0: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.5#4') # Test step 7 # Get the first endpoint for the communication interface. interrupt_endpoint_descriptors = usb_descriptors.filter_descriptors( usb_descriptors.EndpointDescriptor, mbim_communication_interface_bundle) if len(interrupt_endpoint_descriptors) != 1: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 endpoint, got %d.' % (len(interrupt_endpoint_descriptors))) interrupt_endpoint_descriptor = interrupt_endpoint_descriptors[0] if not (interrupt_endpoint_descriptor.bDescriptorType == 0x05 and interrupt_endpoint_descriptor.bLength == 7 and interrupt_endpoint_descriptor.bEndpointAddress >= 0x80 and interrupt_endpoint_descriptor.bmAttributes == 0x03): mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.3#5') appear_before_functional_descriptors = False if mbim_extended_descriptors: if (mbim_extended_descriptor.index > interrupt_endpoint_descriptor.index): appear_before_functional_descriptors = True else: if (mbim_descriptor.index > interrupt_endpoint_descriptor.index or union_descriptor.index > interrupt_endpoint_descriptor.index): appear_before_functional_descriptors = True if appear_before_functional_descriptors: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'All functional descriptors must appear before endpoint' 'descriptors.') # Test step 8 # Get interface association descriptor. interface_association_descriptors = ( usb_descriptors.filter_descriptors( usb_descriptors.InterfaceAssociationDescriptor, descriptors)) if usb_descriptors.has_distinct_descriptors( interface_association_descriptors): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceGenericAssertionError, 'Expected 1 interface association descriptor, got %d.' % (len(interface_association_descriptors))) for association_descriptor in interface_association_descriptors: # Check interface association descriptor if one of the following # condition is met: # 1. bFirstInterface <= bControlInterface < (bFirstInterface + # bInterfaceCount) # 2. bFirstInterface <= bSubordinateInterface0 < ( # bFirstInterface + bInterfaceCount) b_first_interface = association_descriptor.bFirstInterface b_interface_count = association_descriptor.bInterfaceCount b_control_interface = union_descriptor.bControlInterface b_subordinate_interface_0 = ( union_descriptor.bSubordinateInterface0) check_inteface_association_descriptor = False if ((b_first_interface <= b_control_interface < (b_first_interface + b_interface_count)) or (b_first_interface <= b_subordinate_interface_0 < (b_first_interface + b_interface_count))): check_interface_association_descriptor = True if not check_interface_association_descriptor: mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.1#1') if check_interface_association_descriptor: if not ( (b_first_interface == b_control_interface or b_first_interface == b_subordinate_interface_0) and (b_interface_count == 2) and (b_subordinate_interface_0 == b_control_interface + 1 or b_subordinate_interface_0 == b_control_interface - 1) and (association_descriptor.bFunctionClass == 0x02) and (association_descriptor.bFunctionSubClass == 0x0E) and (association_descriptor.bFunctionProtocol == 0x00)): mbim_errors.log_and_raise( mbim_errors.MBIMComplianceAssertionError, 'mbim1.0:6.1#2')