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
5import common
6from autotest_lib.client.cros.cellular.mbim_compliance.sequences \
7        import get_descriptors_sequence
8from autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors
9from autotest_lib.client.cros.cellular.mbim_compliance \
10        import mbim_test_base
11from autotest_lib.client.cros.cellular.mbim_compliance import usb_descriptors
12
13
14class cellular_MbimComplianceDES01(mbim_test_base.MbimTestBase):
15    """
16    DES_01 Descriptors Validation for NCM/MBIM Functions
17
18    This test validates descriptors for the combination NCM/MBIM functions.
19
20    Reference:
21        [1] Universal Serial Bus Communication Class MBIM Compliance Testing: 23
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_01 test. """
29        # Precondition.
30        descriptors = get_descriptors_sequence.GetDescriptorsSequence(
31                self.device_context).run()
32
33        # Test step 1
34        # Get ncm communication interface and mbim communication interface.
35        interfaces = usb_descriptors.filter_descriptors(
36                usb_descriptors.InterfaceDescriptor, descriptors)
37
38        ncm_communication_interfaces = (
39                usb_descriptors.filter_interface_descriptors(
40                        interfaces,
41                        usb_descriptors.NCM_MBIM_COMMUNICATION_INTERFACE_NCM))
42
43        mbim_communication_interfaces = (
44                usb_descriptors.filter_interface_descriptors(
45                        interfaces,
46                        usb_descriptors.NCM_MBIM_COMMUNICATION_INTERFACE_MBIM))
47
48        # If we don't find both NCM and MBIM interfaces, then we should bail
49        # out of this test
50        if (not ncm_communication_interfaces or
51            not mbim_communication_interfaces):
52            return
53
54        if len(ncm_communication_interfaces) != 1:
55            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
56                                      'mbim1.0:3.2.1#2')
57        ncm_communication_interface = ncm_communication_interfaces[0]
58
59        if len(mbim_communication_interfaces) != 1:
60            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
61                                      'mbim1.0:3.2.1#3')
62        mbim_communication_interface = mbim_communication_interfaces[0]
63
64        if (ncm_communication_interface.bInterfaceNumber !=
65            mbim_communication_interface.bInterfaceNumber):
66            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
67                                      'mbim1.0:3.2.1#1')
68
69        # Test step 2
70        if (ncm_communication_interface.index >
71            mbim_communication_interface.index):
72            mbim_errors.log_and_raise(
73                    mbim_errors.MBIMComplianceGenericAssertionError,
74                    'Alternate setting 1 of the interface must appear after'
75                    'alternate setting 0 of the interface.')
76
77        # Test step 3
78        # Get header functional descriptor, union functinoal descriptor,
79        # MBIM functinoal descriptor and MBIM extended functional
80        # descriptor from |ncm_communication_interface|[0].
81        ncm_communication_interface_bundle = (
82                usb_descriptors.get_descriptor_bundle(
83                        descriptors, ncm_communication_interface))
84
85        header_descriptors = usb_descriptors.filter_descriptors(
86                usb_descriptors.HeaderFunctionalDescriptor,
87                ncm_communication_interface_bundle)
88        union_descriptors = usb_descriptors.filter_descriptors(
89                usb_descriptors.UnionFunctionalDescriptor,
90                ncm_communication_interface_bundle)
91        mbim_descriptors = usb_descriptors.filter_descriptors(
92                usb_descriptors.MBIMFunctionalDescriptor,
93                ncm_communication_interface_bundle)
94        mbim_extended_descriptors = usb_descriptors.filter_descriptors(
95                usb_descriptors.MBIMExtendedFunctionalDescriptor,
96                ncm_communication_interface_bundle)
97        if not(header_descriptors and union_descriptors and mbim_descriptors):
98            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
99                                      'mbim1.0:6.3#2')
100
101        # Test step 4
102        # Check header funcional descriptor.
103        if usb_descriptors.has_distinct_descriptors(header_descriptors):
104            mbim_errors.log_and_raise(
105                    mbim_errors.MBIMComplianceGenericAssertionError,
106                    'Expected 1 unique header functional descriptor.')
107        header_descriptor = header_descriptors[0]
108        if not(header_descriptor.bDescriptorType == 0x24 and
109               header_descriptor.bDescriptorSubtype == 0x00 and
110               header_descriptor.bLength == 5 and
111               header_descriptor.bcdCDC >= 0x0120):
112            mbim_errors.log_and_raise(
113                    mbim_errors.MBIMComplianceGenericAssertionError,
114                    'Header functional descriptor: wrong value(s)')
115
116        # Test step 5
117        # Check union functional descriptor.
118        if usb_descriptors.has_distinct_descriptors(union_descriptors):
119            mbim_errors.log_and_raise(
120                    mbim_errors.MBIMComplianceGenericAssertionError,
121                    'Expected 1 unique union functional descriptor.')
122
123        union_descriptor = union_descriptors[0]
124        if union_descriptor.index < header_descriptor.index:
125            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
126                                      'mbim1.0:6.3#3')
127        # Get no data data interface.
128        no_data_data_interfaces = usb_descriptors.filter_interface_descriptors(
129                interfaces, usb_descriptors.NCM_MBIM_DATA_INTERFACE_NO_DATA)
130
131        if len(no_data_data_interfaces) != 1:
132            mbim_errors.log_and_raise(
133                    mbim_errors.MBIMComplianceAssertionError,
134                    'mbim1.0:3.2.2.4#2')
135
136        no_data_data_interface = no_data_data_interfaces[0]
137        no_data_data_interface_bundle = usb_descriptors.get_descriptor_bundle(
138                descriptors, no_data_data_interface)
139        endpoint_descriptors = (
140                usb_descriptors.filter_descriptors(
141                        usb_descriptors.EndpointDescriptor,
142                        no_data_data_interface_bundle))
143
144        if endpoint_descriptors:
145            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
146                                      'mbim1.0:3.2.2.4#4')
147
148        # Get NCM data interface.
149        ncm_data_interfaces = (
150                usb_descriptors.filter_interface_descriptors(
151                        interfaces,
152                        usb_descriptors.NCM_MBIM_DATA_INTERFACE_NCM))
153
154        if len(ncm_data_interfaces) != 1:
155            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
156                                      'mbim1.0:3.2.2.4#2')
157        ncm_data_interface = ncm_data_interfaces[0]
158        if ncm_data_interface.bNumEndpoints != 2:
159            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
160                                      'mbim1.0:3.2.2.4#4')
161        ncm_data_interface_bundle = (
162                usb_descriptors.get_descriptor_bundle(descriptors,
163                                                      ncm_data_interface))
164        endpoint_descriptors = (
165                usb_descriptors.filter_descriptors(
166                        usb_descriptors.EndpointDescriptor,
167                        ncm_data_interface_bundle))
168        # Check endpoint descriptors in |ncm_data_interface_bundle|
169        # There should be one bulk OUT and one bulk IN.
170        if not usb_descriptors.has_bulk_in_and_bulk_out(endpoint_descriptors):
171            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
172                                      'mbim1.0:3.2.2.4#4')
173
174        # Get MBIM data interface.
175        mbim_data_interfaces = usb_descriptors.filter_interface_descriptors(
176                interfaces, usb_descriptors.NCM_MBIM_DATA_INTERFACE_MBIM)
177
178        if len(mbim_data_interfaces) != 1:
179           mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
180                                     'mbim1.0:3.2.2.4#3')
181        mbim_data_interface = mbim_data_interfaces[0]
182        if mbim_data_interface.bNumEndpoints != 2:
183            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
184                                      'mbim1.0:3.2.2.4#4')
185
186        mbim_data_interface_bundle = (
187                usb_descriptors.get_descriptor_bundle(descriptors,
188                                                      mbim_data_interface))
189        endpoint_descriptors = (
190                usb_descriptors.filter_descriptors(
191                        usb_descriptors.EndpointDescriptor,
192                        mbim_data_interface_bundle))
193        # Check endpoint descriptors in |mbim_data_interface_bundle|
194        # alternate setting 2. There should be one bulk OUT and one bulk IN.
195        if not usb_descriptors.has_bulk_in_and_bulk_out(endpoint_descriptors):
196            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
197                                      'mbim1.0:3.2.2.4#4')
198
199        if not(no_data_data_interface.bInterfaceNumber ==
200               ncm_data_interface.bInterfaceNumber ==
201               mbim_data_interface.bInterfaceNumber):
202            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
203                                      'mbim1.0:3.2.2.4#1')
204
205        if not(union_descriptor.bLength == 5 and
206               union_descriptor.bControlInterface == (
207                       ncm_communication_interface.bInterfaceNumber) and
208               union_descriptors.bSubordinateInterface0 == (
209                       no_data_data_interface.bInterfaceNumber)):
210            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
211                                      'mbim1.0:6.3#4')
212        # TODO(mcchou): Continue the remaining test steps.
213
214    # End of run_internal()
215