# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import traceback
import common
from autotest_lib.client.common_lib import error
class MBIMComplianceError(error.TestFail):
""" Base class for all errors overtly raised in the suite. """
pass
class MBIMComplianceFrameworkError(MBIMComplianceError):
"""
Errors raised by any of the framework code.
These errors are raised by code that is not part of a test / sequence /
assertion.
"""
pass
class MBIMComplianceChannelError(MBIMComplianceError):
""" Errors raised in the MBIM communication channel. """
pass
class MBIMComplianceControlMessageError(MBIMComplianceError):
""" Errors raised in the MBIM control module. """
pass
class MBIMComplianceDataTransferError(MBIMComplianceError):
""" Errors raised in the MBIM data transfer module. """
pass
class MBIMComplianceNtbError(MBIMComplianceError):
""" Errors raised in the MBIM NTB module. """
pass
class MBIMComplianceTestError(MBIMComplianceError):
""" Errors raised by compliance suite tests. """
pass
class MBIMComplianceSequenceError(MBIMComplianceError):
""" Errors raised by compliance suite sequences. """
pass
class MBIMComplianceAssertionError(MBIMComplianceError):
""" Errors raised by compliance suite assertions. """
MBIM_ASSERTIONS = {
# This key should not be used directly.
# Raise |MBIMComplianceGenericAssertionError| instead.
'no_code': '',
# Assertion group: 3.x.x#x
'mbim1.0:3.2.1#1': 'Functions that implement both NCM 1.0 and MBIM '
'shall provide two alternate settings for the '
'Communication Interface.',
'mbim1.0:3.2.1#2': 'For alternate setting 0 of the Communication '
'Interface of an NCM/MBIM function: interface, '
'functional and endpoint descriptors shall be '
'constructed according to the rules given in '
'[USBNCM10].',
'mbim1.0:3.2.1#3': 'For alternate setting 1 of the Communication '
'Interface of an NCM/MBIM function: interface, '
'functional and endpoint descriptors shall be '
'constructed according to the rules given in '
'[MBIM 1.0] section 6.',
'mbim1.0:3.2.1#4': 'When alternate setting 0 of the Communiation'
'Interface of an NCM/MBIM function is selected, '
'the function shall operator according to the '
'NCM rules given in [USBNCM10].',
'mbim1.0:3.2.1#5': 'When alternate setting 1 of the Communiation'
'Interface of an NCM/MBIM function is selected, '
'the function shall operator according to the '
'MBIM rules given in [MBIM1.0].',
'mbim1.0:3.2.2.1#1': 'If an Interface Association Descriptor is '
'used to form an NCM/MBIM function, its '
'interface class, subclass, and protocol '
'codes shall match those given in alternate '
'setting 0 of the Communication Interface. ',
'mbim1.0:3.2.2.4#1': 'Functions that implement both NCM 1.0 and '
'MBIM (an "NCM/MBIM function") shall provide '
'three alternate settings for the Data '
'Interface.',
'mbim1.0:3.2.2.4#2': 'For an NCM/MBIM function, the Data Interface '
'descriptors for alternate settings 0 and 1 '
'must have bInterfaceSubClass == 00h, and '
'bInterfaceProtocol == 01h.',
'mbim1.0:3.2.2.4#3': 'For an NCM/MBIM function, the Data Interface '
'descriptor for alternate setting 2 must have '
'bInterfaceSubClass == 00h, and '
'bInterfaceProtocol == 02h.',
'mbim1.0:3.2.2.4#4': 'For an NCM/MBIM function there must be no '
'endpoints for alternate setting 0 of the '
'Data Interface. For each of the other two '
'alternate settings (1 and 2) there must be '
'exactly two endpoints: one Bulk IN and one '
'Bulk OUT.',
# Assertion group: 6.x#x
'mbim1.0:6.1#1': 'If an Interface Association Descriptor (IAD) is '
'provided for the MBIM function, the IAD and the '
'mandatory CDC Union Functional Descriptor '
'specified for the MBIM function shall group '
'together the same interfaces.',
'mbim1.0:6.1#2': 'If an Interface Association Descriptor (IAD) is '
'provided for the MBIM only function, its '
'interface class, subclass, and protocol codes '
'shall match those given in the Communication '
'Interface descriptor.',
'mbim1.0:6.3#1': 'The descriptor for alternate setting 0 of the '
'Communication Interface of an MBIM only function '
'shall have bInterfaceClass == 02h, '
'bInterfaceSubClass == 0Eh, and '
'bInterfaceProtocol == 00h.',
'mbim1.0:6.3#2': 'MBIM Communication Interface description shall '
'include the following functional descriptors: '
'CDC Header Functional Descriptor, CDC Union '
'Functional Descriptor, and MBIM Functional '
'Descriptor. Refer to Table 6.2 of [USBMBIM10].',
'mbim1.0:6.3#3': 'CDC Header Functional Descriptor shall appear '
'before CDC Union Functional Descriptor and '
'before MBIM Functional Descriptor.',
'mbim1.0:6.3#4': 'CDC Union Functional Descriptor for an MBIM '
'function shall group together the MBIM '
'Communication Interface and the MBIM Data '
'Interface.',
'mbim1.0:6.3#5': 'The class-specific descriptors must be followed '
'by an Interrupt IN endpoint descriptor.',
'mbim1.0:6.4#1': 'Field wMaxControlMessage of MBIM Functional '
'Descriptor must not be smaller than 64.',
'mbim1.0:6.4#2': 'Field bNumberFilters of MBIM Functional '
'Descriptor must not be smaller than 16.',
'mbim1.0:6.4#3': 'Field bMaxFilterSize of MBIM Functional '
'Descriptor must not exceed 192.',
'mbim1.0:6.4#4': 'Field wMaxSegmentSize of MBIM Functional '
'Descriptor must not be smaller than 2048.',
'mbim1.0:6.4#5': 'Field bFunctionLength of MBIM Functional '
'Descriptor must be 12 representing the size of '
'the descriptor.',
'mbim1.0:6.4#6': 'Field bcdMBIMVersion of MBIM Functional '
'Descriptor must be 0x0100 in little endian '
'format.',
'mbim1.0:6.4#7': 'Field bmNetworkCapabilities of MBIM Functional '
'Descriptor should have the following bits set to '
'zero: D0, D1, D2, D4, D6 and D7.',
'mbim1.0:6.5#1': 'If MBIM Extended Functional Descriptor is '
'provided, it must appear after MBIM Functional '
'Descriptor.',
'mbim1.0:6.5#2': 'Field bFunctionLength of MBIM Extended '
'Functional Descriptor must be 8 representing the '
'size of the descriptor.',
'mbim1.0:6.5#3': 'Field bcdMBIMEFDVersion of MBIM Extended '
'Functional Descriptor must be 0x0100 in little '
'endian format.',
'mbim1.0:6.5#4': 'Field bMaxOutstandingCommandMessages of MBIM '
'Extended Functional Descriptor shall be greater '
'than 0.',
'mbim1.0:6.6#1': 'The Data Interface for an MBIM only function '
'shall provide two alternate settings.',
'mbim1.0:6.6#2': 'The first alternate setting for the Data '
'Interface of an MBIM only function (the default '
'interface setting, alternate setting 0) shall '
'include no endpoints.',
'mbim1.0:6.6#3': 'The second alternate setting for the Data '
'Interface of an MBIM only function (alternate '
'setting 1) is used for normal operation, and '
'shall include one Bulk IN endpoint and one Bulk '
'OUT endpoint.',
'mbim1.0:6.6#4': 'For an MBIM only function the Data Interface '
'descriptors for alternate settings 0 and 1 must '
'have bInterfaceSubClass == 00h, and '
'bInterfaceProtocol == 02h. Refer to Table 6.4 of '
'[USBMBIM10].',
# Assertion Groups: 7.x.x#x
'mbim1.0:7#1': 'To distinguish among the data streams, the last '
'character of the dwSignature in the NDP16 header '
'shall be coded with the index SessionId specified'
' by the host in the MBIM_CID_CONNECT. The first '
'three symbols are encoded as ASCII characters in '
'little-endian form plus a last byte in HEX '
'(binary) format: "IPS"<SessionId>.',
'mbim1.0:7#3': 'To distinguish among the data streams, the last '
'character of the dwSignature in the NDP32 header '
'shall be coded with the index SessionId specified'
' by the host in the MBIM_CID_CONNECT. The first '
'three symbols are encoded as ASCII characters in '
'little-endian form plus a last byte in HEX '
'(binary) format: "ips"<SessionId>.',
# Assertion Groups: 8.x.x#x
'mbim1.0:8.1.2#2': 'The function must use a separate '
'GET_ENCAPSULATED_RESPONSE transfer for each '
'control message it has to send to the host.',
'mbim1.0:8.1.2#3': 'The function must send a RESPONSE_AVAILABLE '
'notification for each available fragment of '
'ENCAPSULATED_RESPONSE to be read from the '
'default pipe.',
# Assertion Groups: 9.x#x, 9.x.x and 9.x.x#x
'mbim1.0:9.1#1': 'For notifications, the TransactionId must be '
'set to 0 by the function.',
'mbim1.0:9.1#2': 'MessageLength in MBIM_MESSAGE_HEADER must be >='
' 0x0C.',
'mbim1.0:9.2': 'Function should fragment responses based on '
'MaxControlTransfer value from MBIM_OPEN_MSG.',
'mbim1.0:9.3.1#1': 'In case MBIM_OPEN_MSG message is sent to a '
'function that is already opened, the function '
'shall interpret this as that the host and the '
'function are out of synchronization. The '
'function shall then perform the actions '
'dictated by the MBIM_CLOSE_MSG before it '
'performs the actions dictated by this '
'command.The function shall not send the '
'MBIM_CLOSE_DONE when the transition to the '
'Closed state has been completed. Only the '
' MBIM_OPEN_DONE message is sent upon '
'successful completion of this message.',
'mbim1.0:9.3.2#1': 'Between the host\'s sending MBIM_CLOSE_MSG '
'message and the function\'s completing the '
'request (acknowledged with MBIM_CLOSE_DONE), '
'the function shall ignore any MBIM control '
'messages it receives on the control plane or '
'the data on the bulk pipes.',
'mbim1.0:9.3.2#2': 'The function shall not send any MBIM control '
'messages on the control plane or data on the '
'bulk pipes after completing '
'MBIM_CLOSE_MSG message (acknowledging it with '
'the MBIM_CLOSE_DONE message) with one '
'exception and that is MBIM_ERROR_NOT_OPENED.',
'mbim1.0:9.3.2#3': 'On MBIM_CLOSE_MSG, any active context between '
'the function and the host shall be terminated ',
'mbim1.0:9.3.4#2': 'An MBIM_FUNCTION_ERROR_MSG shall not make use '
'of a DataBuffer, so it cannot send any data '
'payload.',
'mbim1.0:9.3.4#3': 'MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE shall be '
'sent by the function if it detects a fragmented'
' message out of sequence.',
'mbim1.0:9.3.4.2#2': 'For MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE, the'
' TransactionId of the responding message must '
'match the TransactionId in the faulty '
'fragmented sequence.',
'mbim1.0:9.3.4.2#3': 'In case of an out of a sequence error, the '
'function shall discard all the packets with '
'the same TransactionId as the faulty message '
'sequence.',
'mbim1.0:9.3.4.2#4': 'If the function gets one more message that '
'is out of order for the same TransactionId, it '
'shall send a new error message with the same '
'TransactionId once more.',
'mbim1.0:9.4.1#1': 'The function shall respond to the '
'MBIM_OPEN_MSG message with an MBIM_OPEN_DONE '
'message in which the TransactionId must match '
'the TransactionId in the MBIM_OPEN_MSG.',
'mbim1.0:9.4.1#2': 'The Status field of MBIM_OPEN_DONE shall be '
'set to MBIM_STATUS_SUCCESS if the function '
'initialized successfully.',
'mbim1.0:9.4.2#1': 'The function shall respond to the '
'MBIM_CLOSE_MSG message with an '
'MBIM_CLOSE_DONE message in which the '
'TransactionId must match the TransactionId in '
'the MBIM_CLOSE_MSG.',
'mbim1.0:9.4.2#2': 'The Status field of MBIM_CLOSE_DONE shall '
'always be set to MBIM_STATUS_SUCCESS.',
'mbim1.0:9.4.3': 'The function shall respond to '
'the MBIM_COMMAND_MSG message with an '
'MBIM_COMMAND_DONE message in which the '
'TransactionId must match the TransactionId in '
'the MBIM_COMMAND_MSG.',
'mbim1.0:9.4.5#1': 'If the CID is successful, the function shall '
'set the Status field to MBIM_STATUS_SUCCESS '
'in the MBIM_COMMAND_DONE.',
'mbim1.0:9.4.5#2': 'If the function does not implement the CID, '
'then the function shall fail the request with '
'MBIM_STATUS_NO_DEVICE_SUPPORT.',
'mbim1.0:9.4.5#3': 'If the Status field returned to the host is '
'not equal to MBIM_STATUS_SUCCESS, the function '
'must set the Information BufferLength to 0, '
'indicating an empty InformationBuffer except '
'the following CIDs: MBIM_CID_REGISTER_STATE, '
'MBIM_CID_PACKET_SERVICE, MBIM_CID_CONNECT, '
'MBIM_CID_SERVICE_ACTIVATION.',
'mbim1.0:9.5#1': 'Function should transmit fragmented message to '
'host without intermixing fragments from other '
'messages.',
'mbim1.0:10.3#2': 'The function shall reject incoming messages '
'that dont follow the rules for variable-length'
' encoding by setting '
'MBIM_STATUS_INVALID_PARAMETERS as the status '
'code in the MBIM_COMMAND_DONE message.',
'mbim1.0:10.5.1.3#1': 'Functions that support CDMA must specify '
'MBIMCtrlCapsCdmaMobileIP or '
'MBIMCtrlCapsCdmaSimpleIP or both flags to '
'inform the host about the type of IP that the '
'function supports.',
# NCM Assertion group: 3.x.x#x
'ncm1.0:3.2.1#1': 'The first four bytes in NTH16 shall be '
'0x484D434E in little-endian format ("NCMH").',
'ncm1.0:3.2.1#2': 'wHeaderLength value in NTH16 shall be 0x000C.',
'ncm1.0:3.2.1#3': 'wSequence in NTH16 shall be set to zero by the '
'function in the first NTB transferred after '
'every "function reset" event.',
'ncm1.0:3.2.1#4': 'wSequence value in NTH16 shall be incremented '
'for every NTB subsequent transfer.',
'ncm1.0:3.2.1#5': 'NTB size (IN) shall not exceed dwNtbInMaxSize.',
'ncm1.0:3.2.1#6': 'wNdpIndex value in NTH16 must be a multiple of '
'4, and must be >= 0x000C, in little endian.',
'ncm1.0:3.2.2#1': 'The first four bytes in NTH32 shall be '
'0x686D636E in little-endian format ("ncmh").',
'ncm1.0:3.2.2#2': 'wHeaderLength value in NTH32 shall be 0x0010.',
'ncm1.0:3.2.2#3': 'wSequence in NTH32 shall be set to zero by the '
'function in the first NTB transferred after '
'every "function reset" event.',
'ncm1.0:3.2.2#4': 'wSequence value in NTH32 shall be incremented '
'for every NTB subsequent transfer.',
'ncm1.0:3.2.2#5': 'NTB size (IN) shall not exceed dwNtbInMaxSize.',
'ncm1.0:3.2.2#6': 'dwNdpIndex value in NTH32 must be a multiple of'
' 4, and must be >= 0x0010, in little endian.',
'ncm1.0:3.3.1#1': 'wLength value in the NDP16 must be a multiple '
'of 4, and must be at least 16d (0x0010).',
'ncm1.0:3.3.1#2': 'wDatagramIndex[0] value in NDP16 must be >= '
'0x000C (because it must point past the NTH16).',
'ncm1.0:3.3.1#3': 'wDatagramLength[0] value in NDP16 must be >= '
'20d if datagram payload is IPv4 and >= 40d if '
'datagram payload is IPv6.',
'ncm1.0:3.3.1#4': 'wDatagramIndex[(wLength-8)/4 - 1] value in '
'NDP16 must be zero.',
'ncm1.0:3.3.1#5': 'wDatagramLength[(wLength-8)/4 - 1] value in '
'NDP16 must be zero.',
'ncm1.0:3.3.2#1': 'wLength value in the NDP32 must be a multiple '
'of 8, and must be at least 16d (0x0020).',
'ncm1.0:3.3.2#2': 'dwDatagramIndex[0] value in NDP32 must be >= '
'0x0010 (because it must point past the NTH32).',
'ncm1.0:3.3.2#3': 'dwDatagramLength[0] value in NDP32 must be >= '
'20d if datagram payload is IPv4 and >= 40d if '
'datagram payload is IPv6.',
'ncm1.0:3.3.2#4': 'dwDatagramIndex[(wLength-8)/4 - 1] value in '
'NDP32 must be zero.',
'ncm1.0:3.3.2#5': 'dwDatagramLength[(wLength-8)/4 - 1] value in '
'NDP32 must be zero.',
}
def __init__(self, assertion_id, error_string=None):
"""
@param assertion_id: A str that must be a key in the MBIM_ASSERTIONS map
defined in this class.
@param error_string: An optional str to be appended to the error
description.
For example,
MBIMComplianceAssertionError('mbim1.0:3.2.1#1')
raises an error associated with assertion [MBIM 1.0]-3.2.1#1
"""
if assertion_id not in self.MBIM_ASSERTIONS:
log_and_raise(MBIMComplianceFrameworkError,
'Unknown assertion id "%s"' % assertion_id)
message = '[%s]: %s' % (assertion_id,
self.MBIM_ASSERTIONS[assertion_id])
if error_string:
message += ': %s' % error_string
super(MBIMComplianceAssertionError, self).__init__(message)
class MBIMComplianceGenericAssertionError(MBIMComplianceAssertionError):
""" Assertion errors that don't map directly to an MBIM assertion. """
def __init__(self, error_string):
"""
@param error_string: A description of the error.
"""
super(MBIMComplianceGenericAssertionError, self).__init__(
'no_code',
error_string)
def log_and_raise(error_class, *args):
"""
Log and raise an error.
This function should be used to raise all errors.
@param error_class: An Exception subclass to raise.
@param *args: Arguments to be passed to the error class constructor.
@raises: |error_class|.
"""
error_object = error_class(*args)
logging.error(error_object)
trace = traceback.format_stack()
# Get rid of the current frame from trace
trace = trace[:len(trace)-1]
logging.error('Traceback:\n' + ''.join(trace))
raise error_object