Home | History | Annotate | Download | only in cellular_MbimComplianceDescriptor
      1 # Copyright 2014 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 common
      6 from autotest_lib.client.cros.cellular.mbim_compliance.sequences \
      7         import get_descriptors_sequence
      8 from autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors
      9 from autotest_lib.client.cros.cellular.mbim_compliance \
     10         import mbim_test_base
     11 from autotest_lib.client.cros.cellular.mbim_compliance import usb_descriptors
     12 
     13 
     14 class cellular_MbimComplianceDES02(mbim_test_base.MbimTestBase):
     15     """
     16     DES_02 Descriptors Validation for MBIM Only Functions
     17 
     18     This test validates descriptors for MBIM only functions.
     19 
     20     Reference:
     21         [1] Universal Serial Bus Communication Class MBIM Compliance Testing: 26
     22         http://www.usb.org/developers/docs/devclass_docs/MBIM-Compliance-1.0.pdf
     23 
     24     """
     25     version = 1
     26 
     27     def run_internal(self):
     28         """ Run the DES_02 test. """
     29         # Precondition.
     30         descriptors = get_descriptors_sequence.GetDescriptorsSequence(
     31                 self.device_context).run()
     32 
     33         # Test step 1
     34         # Get MBIM communication interface.
     35         interfaces = usb_descriptors.filter_descriptors(
     36                 usb_descriptors.InterfaceDescriptor, descriptors)
     37 
     38         mbim_communication_interfaces = (
     39                 usb_descriptors.filter_interface_descriptors(
     40                         interfaces,
     41                         usb_descriptors.MBIM_ONLY_COMMUNICATION_INTERFACE))
     42 
     43         if not mbim_communication_interfaces:
     44             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
     45                                       'mbim1.0:6.3#1')
     46 
     47         if len(mbim_communication_interfaces) > 1:
     48             mbim_errors.log_and_raise(
     49                     mbim_errors.MBIMComplianceGenericAssertionError,
     50                     'Expected 1 mbim communication interface, got %d.' % (
     51                             len(mbim_communication_interfaces)))
     52         mbim_communication_interface = mbim_communication_interfaces[0]
     53 
     54         # Test step 2
     55         # Get header functional descriptor, union functional descriptor,
     56         # MBIM functional descriptor and MBIM extended functional
     57         # descriptor.
     58         mbim_communication_interface_bundle = (
     59                 usb_descriptors.get_descriptor_bundle(
     60                         descriptors, mbim_communication_interface))
     61 
     62         header_descriptors = usb_descriptors.filter_descriptors(
     63                 usb_descriptors.HeaderFunctionalDescriptor,
     64                 mbim_communication_interface_bundle)
     65         union_descriptors = usb_descriptors.filter_descriptors(
     66                 usb_descriptors.UnionFunctionalDescriptor,
     67                 mbim_communication_interface_bundle)
     68         mbim_descriptors = usb_descriptors.filter_descriptors(
     69                 usb_descriptors.MBIMFunctionalDescriptor,
     70                 mbim_communication_interface_bundle)
     71         mbim_extended_descriptors = usb_descriptors.filter_descriptors(
     72                 usb_descriptors.MBIMExtendedFunctionalDescriptor,
     73                 mbim_communication_interface_bundle)
     74         if not(header_descriptors and union_descriptors and mbim_descriptors):
     75             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
     76                                       'mbim1.0:6.3#2')
     77 
     78         # Test step 3
     79         # Check header functional descriptor.
     80         if usb_descriptors.has_distinct_descriptors(header_descriptors):
     81             mbim_errors.log_and_raise(
     82                     mbim_errors.MBIMComplianceGenericAssertionError,
     83                     'Expected 1 unique header functional descriptor.')
     84         header_descriptor = header_descriptors[0]
     85         if not(header_descriptor.bDescriptorType == 0x24 and
     86                header_descriptor.bDescriptorSubtype == 0x00 and
     87                header_descriptor.bLength == 5 and
     88                header_descriptor.bcdCDC >= 0x0120):
     89             mbim_errors.log_and_raise(
     90                 mbim_errors.MBIMComplianceGenericAssertionError,
     91                 'Header functional descriptor: wrong value(s)')
     92 
     93         # Test step 4
     94         # Check union functional descriptor.
     95         if usb_descriptors.has_distinct_descriptors(union_descriptors):
     96             mbim_errors.log_and_raise(
     97                     mbim_errors.MBIMComplianceGenerisAssertionError,
     98                     'Expected 1 unique union functional descriptor.')
     99         union_descriptor = union_descriptors[0]
    100         if union_descriptor.index < header_descriptor.index:
    101             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    102                                       'mbim1.0:6.3#3')
    103 
    104         # Get CDC no data data interface.
    105         no_data_data_interfaces = usb_descriptors.filter_interface_descriptors(
    106                 interfaces, usb_descriptors.MBIM_ONLY_DATA_INTERFACE_NO_DATA)
    107         if not no_data_data_interfaces:
    108             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    109                                       'mbim1.0:6.6#4')
    110         if len(no_data_data_interfaces) > 1:
    111             mbim_errors.log_and_raise(
    112                     mbim_errors.MBIMComplianceGenericAssertionError,
    113                     'Exactly 1 CDC data interface, got %d.' % (
    114                             len(no_data_data_interfaces)))
    115         no_data_data_interface = no_data_data_interfaces[0]
    116         no_data_data_interface_bundle = usb_descriptors.get_descriptor_bundle(
    117                 descriptors, no_data_data_interface)
    118         data_endpoint_descriptors = (
    119                 usb_descriptors.filter_descriptors(
    120                         usb_descriptors.EndpointDescriptor,
    121                         no_data_data_interface_bundle))
    122         if data_endpoint_descriptors:
    123             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    124                                       'mbim1.0:6.6#2')
    125 
    126         # Get MBIM data interface.
    127         mbim_data_interfaces = usb_descriptors.filter_interface_descriptors(
    128                 interfaces, usb_descriptors.MBIM_ONLY_DATA_INTERFACE_MBIM)
    129         if not mbim_data_interfaces:
    130             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    131                                       'mbim1.0:6.6#4')
    132         if len(mbim_data_interfaces) > 1:
    133             mbim_errors.log_and_raise(
    134                     mbim_errors.MBIMComplianceGenericAssertionError,
    135                     'Expected 1 MBIM data interface, got %d.' % (
    136                             len(mbim_data_interfaces)))
    137         mbim_data_interface = mbim_data_interfaces[0]
    138 
    139         # Check if there are two endpoint descriptors.
    140         if mbim_data_interface.bNumEndpoints != 2:
    141             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    142                                       'mbim1.0:6.6#3.')
    143 
    144         mbim_data_interface_bundle = usb_descriptors.get_descriptor_bundle(
    145                 descriptors, mbim_data_interface)
    146         data_endpoint_descriptors = usb_descriptors.filter_descriptors(
    147                 usb_descriptors.EndpointDescriptor,
    148                 mbim_data_interface_bundle)
    149 
    150         # Check the values of fields in endpoint descriptors.
    151         # There should be one bulk OUT and one bulk IN.
    152         if not usb_descriptors.has_bulk_in_and_bulk_out(
    153                 data_endpoint_descriptors):
    154             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    155                                       'mbim1.0:6.6#3')
    156 
    157         # MBIM cdc data interface should have both no data data interface and
    158         # MBIM data interface. Therefore two interface numbers should be
    159         # the same.
    160         if (no_data_data_interface.bInterfaceNumber !=
    161             mbim_data_interface.bInterfaceNumber):
    162             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    163                                       'mbim1.0:6.6#1')
    164 
    165         # Check the fields of union functional descriptor
    166         if not(union_descriptor.bLength == 5 and
    167                (union_descriptor.bControlInterface ==
    168                 mbim_communication_interface.bInterfaceNumber) and
    169                (union_descriptor.bSubordinateInterface0 ==
    170                 mbim_data_interface.bInterfaceNumber)):
    171             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    172                                       'mbim1.0:6.3#4')
    173 
    174         # Test step 5
    175         # Get MBIM functional descriptor.
    176         if usb_descriptors.has_distinct_descriptors(mbim_descriptors):
    177             mbim_errors.log_and_raise(
    178                     mbim_errors.MBIMComplianceGenericAssertionError,
    179                     'Expected 1 unique MBIM functional descriptor.')
    180         mbim_descriptor = mbim_descriptors[0]
    181 
    182         if mbim_descriptor.index < header_descriptor.index:
    183             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    184                                       'mbim1.0:6.3#3')
    185 
    186         if mbim_descriptor.bLength != 12:
    187             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    188                                       'mbim1.0:6.4#5')
    189 
    190         if mbim_descriptor.bcdMBIMVersion != 0x0100:
    191             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    192                                       'mbim1.0:6.4#6')
    193 
    194         if mbim_descriptor.wMaxControlMessage < 64:
    195             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    196                                       'mbim1.0:6.4#1')
    197 
    198         if mbim_descriptor.bNumberFilters < 16:
    199             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    200                                       'mbim1.0:6.4#2')
    201 
    202         if mbim_descriptor.bMaxFilterSize > 192:
    203             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    204                                       'mbim1.0:6.4#3')
    205 
    206         # TODO(mcchou): Most of vendors set wMaxSegmentSize to be less than
    207         # 1500, so this assertion is skipped for now.
    208         #
    209         #if not mbim_descriptor.wMaxSegmentSize >= 2048:
    210         #    mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    211         #                              'mbim1.0:6.4#4')
    212 
    213         # Use a byte as the mask to check if D0, D1, D2, D4, D6 and D7 are
    214         # zeros.
    215         if (mbim_descriptor.bmNetworkCapabilities & 0b11010111) > 0:
    216             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    217                                       'mbim1.0:6.4#7')
    218 
    219         # Test step 6
    220         # Get MBIM extended functional descriptor, which is optional.
    221         if len(mbim_extended_descriptors) >= 1:
    222             if usb_descriptors.has_distinct_descriptors(
    223                     mbim_extended_descriptors):
    224                 mbim_errors.log_and_raise(
    225                         mbim_errors.MBIMComplianceGenerisAssertionError,
    226                         'Expected 1 unique MBIM extended functional '
    227                         'descriptor.')
    228             mbim_extended_descriptor = mbim_extended_descriptors[0]
    229 
    230             if mbim_extended_descriptor.index < mbim_descriptor.index:
    231                 mbim_errors.log_and_raise(
    232                         mbim_errors.MBIMComplianceAssertionError,
    233                         'mbim1.0:6.5#1')
    234 
    235             if mbim_extended_descriptor.bLength != 8:
    236                 mbim_errors.log_and_raise(
    237                         mbim_errors.MBIMComplianceAssertionError,
    238                         'mbim1.0:6.5#2')
    239 
    240             if mbim_extended_descriptor.bcdMBIMExtendedVersion != 0x0100:
    241                 mbim_errors.log_and_raise(
    242                         mbim_errors.MBIMComplianceAssertionError,
    243                         'mbim1.0:6.5#3')
    244 
    245             if mbim_extended_descriptor.bMaxOutstandingCommandMessages == 0:
    246                 mbim_errors.log_and_raise(
    247                         mbim_errors.MBIMComplianceAssertionError,
    248                         'mbim1.0:6.5#4')
    249 
    250         # Test step 7
    251         # Get the first endpoint for the communication interface.
    252         interrupt_endpoint_descriptors = usb_descriptors.filter_descriptors(
    253                 usb_descriptors.EndpointDescriptor,
    254                 mbim_communication_interface_bundle)
    255 
    256         if len(interrupt_endpoint_descriptors) != 1:
    257             mbim_errors.log_and_raise(
    258                     mbim_errors.MBIMComplianceGenericAssertionError,
    259                     'Expected 1 endpoint, got %d.' % (
    260                             len(interrupt_endpoint_descriptors)))
    261         interrupt_endpoint_descriptor = interrupt_endpoint_descriptors[0]
    262         if not (interrupt_endpoint_descriptor.bDescriptorType == 0x05 and
    263                 interrupt_endpoint_descriptor.bLength == 7 and
    264                 interrupt_endpoint_descriptor.bEndpointAddress >= 0x80 and
    265                 interrupt_endpoint_descriptor.bmAttributes == 0x03):
    266             mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
    267                                       'mbim1.0:6.3#5')
    268 
    269         appear_before_functional_descriptors = False
    270         if mbim_extended_descriptors:
    271             if (mbim_extended_descriptor.index >
    272                 interrupt_endpoint_descriptor.index):
    273                 appear_before_functional_descriptors = True
    274         else:
    275             if (mbim_descriptor.index > interrupt_endpoint_descriptor.index or
    276                 union_descriptor.index > interrupt_endpoint_descriptor.index):
    277                 appear_before_functional_descriptors = True
    278         if appear_before_functional_descriptors:
    279             mbim_errors.log_and_raise(
    280                     mbim_errors.MBIMComplianceGenericAssertionError,
    281                     'All functional descriptors must appear before endpoint'
    282                     'descriptors.')
    283 
    284         # Test step 8
    285         # Get interface association descriptor.
    286         interface_association_descriptors = (
    287                 usb_descriptors.filter_descriptors(
    288                         usb_descriptors.InterfaceAssociationDescriptor,
    289                         descriptors))
    290 
    291         if usb_descriptors.has_distinct_descriptors(
    292                 interface_association_descriptors):
    293             mbim_errors.log_and_raise(
    294                     mbim_errors.MBIMComplianceGenericAssertionError,
    295                     'Expected 1 interface association descriptor, got %d.' % (
    296                             len(interface_association_descriptors)))
    297 
    298         for association_descriptor in interface_association_descriptors:
    299             # Check interface association descriptor if one of the following
    300             # condition is met:
    301             # 1. bFirstInterface <= bControlInterface < (bFirstInterface +
    302             #                                            bInterfaceCount)
    303             # 2. bFirstInterface <= bSubordinateInterface0 < (
    304             #            bFirstInterface + bInterfaceCount)
    305             b_first_interface = association_descriptor.bFirstInterface
    306             b_interface_count = association_descriptor.bInterfaceCount
    307             b_control_interface = union_descriptor.bControlInterface
    308             b_subordinate_interface_0 = (
    309                     union_descriptor.bSubordinateInterface0)
    310             check_inteface_association_descriptor = False
    311 
    312             if ((b_first_interface <= b_control_interface < (
    313                          b_first_interface + b_interface_count)) or
    314                 (b_first_interface <= b_subordinate_interface_0 < (
    315                          b_first_interface + b_interface_count))):
    316                 check_interface_association_descriptor = True
    317 
    318             if not check_interface_association_descriptor:
    319                 mbim_errors.log_and_raise(
    320                         mbim_errors.MBIMComplianceAssertionError,
    321                         'mbim1.0:6.1#1')
    322 
    323             if check_interface_association_descriptor:
    324                 if not((b_first_interface == b_control_interface or
    325                         b_first_interface == b_subordinate_interface_0) and
    326                        (b_interface_count == 2) and
    327                        (b_subordinate_interface_0 == b_control_interface + 1 or
    328                         b_subordinate_interface_0 ==
    329                         b_control_interface - 1) and
    330                        (association_descriptor.bFunctionClass == 0x02) and
    331                        (association_descriptor.bFunctionSubClass == 0x0E) and
    332                        (association_descriptor.bFunctionProtocol == 0x00)):
    333                     mbim_errors.log_and_raise(
    334                             mbim_errors.MBIMComplianceAssertionError,
    335                             'mbim1.0:6.1#2')
    336 
    337     # End of run_internal().
    338