Home | History | Annotate | Download | only in mbim_compliance
      1 # Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging
      6 import traceback
      7 
      8 import common
      9 from autotest_lib.client.common_lib import error
     10 
     11 
     12 class MBIMComplianceError(error.TestFail):
     13     """ Base class for all errors overtly raised in the suite. """
     14     pass
     15 
     16 
     17 class MBIMComplianceFrameworkError(MBIMComplianceError):
     18     """
     19     Errors raised by any of the framework code.
     20 
     21     These errors are raised by code that is not part of a test / sequence /
     22     assertion.
     23 
     24     """
     25     pass
     26 
     27 
     28 class MBIMComplianceChannelError(MBIMComplianceError):
     29     """ Errors raised in the MBIM communication channel. """
     30     pass
     31 
     32 
     33 class MBIMComplianceControlMessageError(MBIMComplianceError):
     34     """ Errors raised in the MBIM control module. """
     35     pass
     36 
     37 
     38 class MBIMComplianceDataTransferError(MBIMComplianceError):
     39     """ Errors raised in the MBIM data transfer module. """
     40     pass
     41 
     42 
     43 class MBIMComplianceNtbError(MBIMComplianceError):
     44     """ Errors raised in the MBIM NTB module. """
     45     pass
     46 
     47 
     48 class MBIMComplianceTestError(MBIMComplianceError):
     49     """ Errors raised by compliance suite tests. """
     50     pass
     51 
     52 
     53 class MBIMComplianceSequenceError(MBIMComplianceError):
     54     """ Errors raised by compliance suite sequences. """
     55     pass
     56 
     57 
     58 class MBIMComplianceAssertionError(MBIMComplianceError):
     59     """ Errors raised by compliance suite assertions. """
     60 
     61     MBIM_ASSERTIONS = {
     62             # This key should not be used directly.
     63             # Raise |MBIMComplianceGenericAssertionError| instead.
     64             'no_code': '',
     65 
     66             # Assertion group: 3.x.x#x
     67             'mbim1.0:3.2.1#1': 'Functions that implement both NCM 1.0 and MBIM '
     68                                'shall provide two alternate settings for the '
     69                                'Communication Interface.',
     70             'mbim1.0:3.2.1#2': 'For alternate setting 0 of the Communication '
     71                                'Interface of an NCM/MBIM function: interface, '
     72                                'functional and endpoint descriptors shall be '
     73                                'constructed according to the rules given in '
     74                                '[USBNCM10].',
     75             'mbim1.0:3.2.1#3': 'For alternate setting 1 of the Communication '
     76                                'Interface of an NCM/MBIM function: interface, '
     77                                'functional and endpoint descriptors shall be '
     78                                'constructed according to the rules given in '
     79                                '[MBIM 1.0] section 6.',
     80             'mbim1.0:3.2.1#4': 'When alternate setting 0 of the Communiation'
     81                                'Interface of an NCM/MBIM function is selected, '
     82                                'the function shall operator according to the '
     83                                'NCM rules given in [USBNCM10].',
     84             'mbim1.0:3.2.1#5': 'When alternate setting 1 of the Communiation'
     85                                'Interface of an NCM/MBIM function is selected, '
     86                                'the function shall operator according to the '
     87                                'MBIM rules given in [MBIM1.0].',
     88             'mbim1.0:3.2.2.1#1': 'If an Interface Association Descriptor is '
     89                                  'used to form an NCM/MBIM function, its '
     90                                  'interface class, subclass, and protocol '
     91                                  'codes shall match those given in alternate '
     92                                  'setting 0 of the Communication Interface. ',
     93             'mbim1.0:3.2.2.4#1': 'Functions that implement both NCM 1.0 and '
     94                                  'MBIM (an "NCM/MBIM function") shall provide '
     95                                  'three alternate settings for the Data '
     96                                  'Interface.',
     97             'mbim1.0:3.2.2.4#2': 'For an NCM/MBIM function, the Data Interface '
     98                                  'descriptors for alternate settings 0 and 1 '
     99                                  'must have bInterfaceSubClass == 00h, and '
    100                                  'bInterfaceProtocol == 01h.',
    101             'mbim1.0:3.2.2.4#3': 'For an NCM/MBIM function, the Data Interface '
    102                                  'descriptor for alternate setting 2 must have '
    103                                  'bInterfaceSubClass == 00h, and '
    104                                  'bInterfaceProtocol == 02h.',
    105             'mbim1.0:3.2.2.4#4': 'For an NCM/MBIM function there must be no '
    106                                  'endpoints for alternate setting 0 of the '
    107                                  'Data Interface. For each of the other two '
    108                                  'alternate settings (1 and 2) there must be '
    109                                  'exactly two endpoints: one Bulk IN and one '
    110                                  'Bulk OUT.',
    111 
    112             # Assertion group: 6.x#x
    113             'mbim1.0:6.1#1': 'If an Interface Association Descriptor (IAD) is '
    114                              'provided for the MBIM function, the IAD and the '
    115                              'mandatory CDC Union Functional Descriptor '
    116                              'specified for the MBIM function shall group '
    117                              'together the same interfaces.',
    118             'mbim1.0:6.1#2': 'If an Interface Association Descriptor (IAD) is '
    119                              'provided for the MBIM only function, its '
    120                              'interface class, subclass, and protocol codes '
    121                              'shall match those given in the Communication '
    122                              'Interface descriptor.',
    123             'mbim1.0:6.3#1': 'The descriptor for alternate setting 0 of the '
    124                              'Communication Interface of an MBIM only function '
    125                              'shall have bInterfaceClass == 02h, '
    126                              'bInterfaceSubClass == 0Eh, and '
    127                              'bInterfaceProtocol == 00h.',
    128             'mbim1.0:6.3#2': 'MBIM Communication Interface description shall '
    129                              'include the following functional descriptors: '
    130                              'CDC Header Functional Descriptor, CDC Union '
    131                              'Functional Descriptor, and MBIM Functional '
    132                              'Descriptor. Refer to Table 6.2 of [USBMBIM10].',
    133             'mbim1.0:6.3#3': 'CDC Header Functional Descriptor shall appear '
    134                              'before CDC Union Functional Descriptor and '
    135                              'before MBIM Functional Descriptor.',
    136             'mbim1.0:6.3#4': 'CDC Union Functional Descriptor for an MBIM '
    137                              'function shall group together the MBIM '
    138                              'Communication Interface and the MBIM Data '
    139                              'Interface.',
    140             'mbim1.0:6.3#5': 'The class-specific descriptors must be followed '
    141                              'by an Interrupt IN endpoint descriptor.',
    142             'mbim1.0:6.4#1': 'Field wMaxControlMessage of MBIM Functional '
    143                              'Descriptor must not be smaller than 64.',
    144             'mbim1.0:6.4#2': 'Field bNumberFilters of MBIM Functional '
    145                              'Descriptor must not be smaller than 16.',
    146             'mbim1.0:6.4#3': 'Field bMaxFilterSize of MBIM Functional '
    147                              'Descriptor must not exceed 192.',
    148             'mbim1.0:6.4#4': 'Field wMaxSegmentSize of MBIM Functional '
    149                              'Descriptor must not be smaller than 2048.',
    150             'mbim1.0:6.4#5': 'Field bFunctionLength of MBIM Functional '
    151                              'Descriptor must be 12 representing the size of '
    152                              'the descriptor.',
    153             'mbim1.0:6.4#6': 'Field bcdMBIMVersion of MBIM Functional '
    154                              'Descriptor must be 0x0100 in little endian '
    155                              'format.',
    156             'mbim1.0:6.4#7': 'Field bmNetworkCapabilities of MBIM Functional '
    157                              'Descriptor should have the following bits set to '
    158                              'zero: D0, D1, D2, D4, D6 and D7.',
    159             'mbim1.0:6.5#1': 'If MBIM Extended Functional Descriptor is '
    160                              'provided, it must appear after MBIM Functional '
    161                              'Descriptor.',
    162             'mbim1.0:6.5#2': 'Field bFunctionLength of MBIM Extended '
    163                              'Functional Descriptor must be 8 representing the '
    164                              'size of the descriptor.',
    165             'mbim1.0:6.5#3': 'Field bcdMBIMEFDVersion of MBIM Extended '
    166                              'Functional Descriptor must be 0x0100 in little '
    167                              'endian format.',
    168             'mbim1.0:6.5#4': 'Field bMaxOutstandingCommandMessages of MBIM '
    169                              'Extended Functional Descriptor shall be greater '
    170                              'than 0.',
    171             'mbim1.0:6.6#1': 'The Data Interface for an MBIM only function '
    172                              'shall provide two alternate settings.',
    173             'mbim1.0:6.6#2': 'The first alternate setting for the Data '
    174                              'Interface of an MBIM only function (the default '
    175                              'interface setting, alternate setting 0) shall '
    176                              'include no endpoints.',
    177             'mbim1.0:6.6#3': 'The second alternate setting for the Data '
    178                              'Interface of an MBIM only function (alternate '
    179                              'setting 1) is used for normal operation, and '
    180                              'shall include one Bulk IN endpoint and one Bulk '
    181                              'OUT endpoint.',
    182             'mbim1.0:6.6#4': 'For an MBIM only function the Data Interface '
    183                              'descriptors for alternate settings 0 and 1 must '
    184                              'have bInterfaceSubClass == 00h, and '
    185                              'bInterfaceProtocol == 02h. Refer to Table 6.4 of '
    186                              '[USBMBIM10].',
    187 
    188             # Assertion Groups: 7.x.x#x
    189             'mbim1.0:7#1':   'To distinguish among the data streams, the last '
    190                              'character of the dwSignature in the NDP16 header '
    191                              'shall be coded with the index SessionId specified'
    192                              ' by the host in the MBIM_CID_CONNECT. The first '
    193                              'three symbols are encoded as ASCII characters in '
    194                              'little-endian form plus a last byte in HEX '
    195                              '(binary) format: "IPS"<SessionId>.',
    196             'mbim1.0:7#3':   'To distinguish among the data streams, the last '
    197                              'character of the dwSignature in the NDP32 header '
    198                              'shall be coded with the index SessionId specified'
    199                              ' by the host in the MBIM_CID_CONNECT. The first '
    200                              'three symbols are encoded as ASCII characters in '
    201                              'little-endian form plus a last byte in HEX '
    202                              '(binary) format: "ips"<SessionId>.',
    203 
    204             # Assertion Groups: 8.x.x#x
    205             'mbim1.0:8.1.2#2': 'The function must use a separate '
    206                                'GET_ENCAPSULATED_RESPONSE transfer for each '
    207                                'control message it has to send to the host.',
    208             'mbim1.0:8.1.2#3': 'The function must send a RESPONSE_AVAILABLE '
    209                                'notification for each available fragment of '
    210                                'ENCAPSULATED_RESPONSE to be read from the '
    211                                'default pipe.',
    212 
    213             # Assertion Groups: 9.x#x, 9.x.x and 9.x.x#x
    214             'mbim1.0:9.1#1':   'For notifications, the TransactionId must be '
    215                                'set to 0 by the function.',
    216             'mbim1.0:9.1#2':   'MessageLength in MBIM_MESSAGE_HEADER must be >='
    217                                ' 0x0C.',
    218             'mbim1.0:9.2':     'Function should fragment responses based on '
    219                                'MaxControlTransfer value from MBIM_OPEN_MSG.',
    220             'mbim1.0:9.3.1#1': 'In case MBIM_OPEN_MSG message is sent to a '
    221                                'function that is already opened, the function '
    222                                'shall interpret this as that the host and the '
    223                                'function are out of synchronization. The '
    224                                'function shall then perform the actions '
    225                                'dictated by the MBIM_CLOSE_MSG before it '
    226                                'performs the actions dictated by this '
    227                                'command.The function shall not send the '
    228                                'MBIM_CLOSE_DONE when the transition to the '
    229                                'Closed state has been completed. Only the '
    230                                ' MBIM_OPEN_DONE message is sent upon '
    231                                'successful completion of this message.',
    232             'mbim1.0:9.3.2#1': 'Between the host\'s sending MBIM_CLOSE_MSG '
    233                                'message and the function\'s completing the '
    234                                'request (acknowledged with MBIM_CLOSE_DONE), '
    235                                'the function shall ignore any MBIM control '
    236                                'messages it receives on the control plane or '
    237                                'the data on the bulk pipes.',
    238             'mbim1.0:9.3.2#2': 'The function shall not send any MBIM control '
    239                                'messages on the control plane or data on the '
    240                                'bulk pipes after completing '
    241                                'MBIM_CLOSE_MSG message (acknowledging it with '
    242                                'the MBIM_CLOSE_DONE message) with one '
    243                                'exception and that is MBIM_ERROR_NOT_OPENED.',
    244             'mbim1.0:9.3.2#3': 'On MBIM_CLOSE_MSG, any active context between '
    245                                'the function and the host shall be terminated ',
    246             'mbim1.0:9.3.4#2': 'An MBIM_FUNCTION_ERROR_MSG shall not make use '
    247                                'of a DataBuffer, so it cannot send any data '
    248                                'payload.',
    249             'mbim1.0:9.3.4#3': 'MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE shall be '
    250                                'sent by the function if it detects a fragmented'
    251                                ' message out of sequence.',
    252             'mbim1.0:9.3.4.2#2': 'For MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE, the'
    253                                ' TransactionId of the responding message must '
    254                                'match the TransactionId in the faulty '
    255                                'fragmented sequence.',
    256             'mbim1.0:9.3.4.2#3': 'In case of an out of a sequence error, the '
    257                                'function shall discard all the packets with '
    258                                'the same TransactionId as the faulty message '
    259                                'sequence.',
    260             'mbim1.0:9.3.4.2#4': 'If the function gets one more message that '
    261                                'is out of order for the same TransactionId, it '
    262                                'shall send a new error message with the same '
    263                                'TransactionId once more.',
    264             'mbim1.0:9.4.1#1': 'The function shall respond to the '
    265                                'MBIM_OPEN_MSG message with an MBIM_OPEN_DONE '
    266                                'message in which the TransactionId must match '
    267                                'the TransactionId in the MBIM_OPEN_MSG.',
    268             'mbim1.0:9.4.1#2': 'The Status field of MBIM_OPEN_DONE shall be '
    269                                'set to MBIM_STATUS_SUCCESS if the function '
    270                                'initialized successfully.',
    271             'mbim1.0:9.4.2#1': 'The function shall respond to the '
    272                                'MBIM_CLOSE_MSG message with an '
    273                                'MBIM_CLOSE_DONE message in which the '
    274                                'TransactionId must match the TransactionId in '
    275                                'the MBIM_CLOSE_MSG.',
    276             'mbim1.0:9.4.2#2': 'The Status field of MBIM_CLOSE_DONE shall '
    277                                'always be set to MBIM_STATUS_SUCCESS.',
    278             'mbim1.0:9.4.3': 'The function shall respond to '
    279                              'the MBIM_COMMAND_MSG message with an '
    280                              'MBIM_COMMAND_DONE message in which the '
    281                              'TransactionId must match the TransactionId in '
    282                              'the MBIM_COMMAND_MSG.',
    283             'mbim1.0:9.4.5#1': 'If the CID is successful, the function shall '
    284                                'set the Status field to MBIM_STATUS_SUCCESS '
    285                                'in the MBIM_COMMAND_DONE.',
    286             'mbim1.0:9.4.5#2': 'If the function does not implement the CID, '
    287                                'then the function shall fail the request with '
    288                                'MBIM_STATUS_NO_DEVICE_SUPPORT.',
    289             'mbim1.0:9.4.5#3': 'If the Status field returned to the host is '
    290                                'not equal to MBIM_STATUS_SUCCESS, the function '
    291                                'must set the Information BufferLength to 0, '
    292                                'indicating an empty InformationBuffer except '
    293                                'the following CIDs: MBIM_CID_REGISTER_STATE, '
    294                                'MBIM_CID_PACKET_SERVICE, MBIM_CID_CONNECT, '
    295                                'MBIM_CID_SERVICE_ACTIVATION.',
    296             'mbim1.0:9.5#1':   'Function should transmit fragmented message to '
    297                                'host without intermixing fragments from other '
    298                                'messages.',
    299             'mbim1.0:10.3#2':  'The function shall reject incoming messages '
    300                                'that dont follow the rules for variable-length'
    301                                ' encoding by setting '
    302                                'MBIM_STATUS_INVALID_PARAMETERS as the status '
    303                                'code in the MBIM_COMMAND_DONE message.',
    304             'mbim1.0:10.5.1.3#1': 'Functions that support CDMA must specify '
    305                                'MBIMCtrlCapsCdmaMobileIP or '
    306                                'MBIMCtrlCapsCdmaSimpleIP or both flags to '
    307                                'inform the host about the type of IP that the '
    308                                'function supports.',
    309 
    310             # NCM Assertion group: 3.x.x#x
    311             'ncm1.0:3.2.1#1':  'The first four bytes in NTH16 shall be '
    312                                '0x484D434E in little-endian format ("NCMH").',
    313             'ncm1.0:3.2.1#2':  'wHeaderLength value in NTH16 shall be 0x000C.',
    314             'ncm1.0:3.2.1#3':  'wSequence in NTH16 shall be set to zero by the '
    315                                'function in the first NTB transferred after '
    316                                'every "function reset" event.',
    317             'ncm1.0:3.2.1#4':  'wSequence value in NTH16 shall be incremented '
    318                                'for every NTB subsequent transfer.',
    319             'ncm1.0:3.2.1#5':  'NTB size (IN) shall not exceed dwNtbInMaxSize.',
    320             'ncm1.0:3.2.1#6':  'wNdpIndex value in NTH16 must be a multiple of '
    321                                '4, and must be >= 0x000C, in little endian.',
    322             'ncm1.0:3.2.2#1':  'The first four bytes in NTH32 shall be '
    323                                '0x686D636E in little-endian format ("ncmh").',
    324             'ncm1.0:3.2.2#2':  'wHeaderLength value in NTH32 shall be 0x0010.',
    325             'ncm1.0:3.2.2#3':  'wSequence in NTH32 shall be set to zero by the '
    326                                'function in the first NTB transferred after '
    327                                'every "function reset" event.',
    328             'ncm1.0:3.2.2#4':  'wSequence value in NTH32 shall be incremented '
    329                                'for every NTB subsequent transfer.',
    330             'ncm1.0:3.2.2#5':  'NTB size (IN) shall not exceed dwNtbInMaxSize.',
    331             'ncm1.0:3.2.2#6':  'dwNdpIndex value in NTH32 must be a multiple of'
    332                                ' 4, and must be >= 0x0010, in little endian.',
    333             'ncm1.0:3.3.1#1':  'wLength value in the NDP16 must be a multiple '
    334                                'of 4, and must be at least 16d (0x0010).',
    335             'ncm1.0:3.3.1#2':  'wDatagramIndex[0] value in NDP16 must be >= '
    336                                '0x000C (because it must point past the NTH16).',
    337             'ncm1.0:3.3.1#3':  'wDatagramLength[0] value in NDP16 must be >= '
    338                                '20d if datagram payload is IPv4 and >= 40d if '
    339                                'datagram payload is IPv6.',
    340             'ncm1.0:3.3.1#4':  'wDatagramIndex[(wLength-8)/4 - 1] value in '
    341                                'NDP16 must be zero.',
    342             'ncm1.0:3.3.1#5':  'wDatagramLength[(wLength-8)/4 - 1] value in '
    343                                'NDP16 must be zero.',
    344             'ncm1.0:3.3.2#1':  'wLength value in the NDP32 must be a multiple '
    345                                'of 8, and must be at least 16d (0x0020).',
    346             'ncm1.0:3.3.2#2':  'dwDatagramIndex[0] value in NDP32 must be >= '
    347                                '0x0010 (because it must point past the NTH32).',
    348             'ncm1.0:3.3.2#3':  'dwDatagramLength[0] value in NDP32 must be >= '
    349                                '20d if datagram payload is IPv4 and >= 40d if '
    350                                'datagram payload is IPv6.',
    351             'ncm1.0:3.3.2#4':  'dwDatagramIndex[(wLength-8)/4 - 1] value in '
    352                                'NDP32 must be zero.',
    353             'ncm1.0:3.3.2#5':  'dwDatagramLength[(wLength-8)/4 - 1] value in '
    354                                'NDP32 must be zero.',
    355     }
    356 
    357     def __init__(self, assertion_id, error_string=None):
    358         """
    359         @param assertion_id: A str that must be a key in the MBIM_ASSERTIONS map
    360                 defined in this class.
    361         @param error_string: An optional str to be appended to the error
    362                 description.
    363 
    364         For example,
    365             MBIMComplianceAssertionError('mbim1.0:3.2.1#1')
    366             raises an error associated with assertion [MBIM 1.0]-3.2.1#1
    367 
    368         """
    369         if assertion_id not in self.MBIM_ASSERTIONS:
    370             log_and_raise(MBIMComplianceFrameworkError,
    371                           'Unknown assertion id "%s"' % assertion_id)
    372 
    373         message = '[%s]: %s' % (assertion_id,
    374                                 self.MBIM_ASSERTIONS[assertion_id])
    375         if error_string:
    376             message += ': %s' % error_string
    377 
    378         super(MBIMComplianceAssertionError, self).__init__(message)
    379 
    380 
    381 class MBIMComplianceGenericAssertionError(MBIMComplianceAssertionError):
    382     """ Assertion errors that don't map directly to an MBIM assertion. """
    383     def __init__(self, error_string):
    384         """
    385         @param error_string: A description of the error.
    386         """
    387         super(MBIMComplianceGenericAssertionError, self).__init__(
    388                 'no_code',
    389                 error_string)
    390 
    391 
    392 def log_and_raise(error_class, *args):
    393     """
    394     Log and raise an error.
    395 
    396     This function should be used to raise all errors.
    397 
    398     @param error_class: An Exception subclass to raise.
    399     @param *args: Arguments to be passed to the error class constructor.
    400     @raises: |error_class|.
    401 
    402     """
    403     error_object = error_class(*args)
    404     logging.error(error_object)
    405     trace = traceback.format_stack()
    406     # Get rid of the current frame from trace
    407     trace = trace[:len(trace)-1]
    408     logging.error('Traceback:\n' + ''.join(trace))
    409     raise error_object
    410