1# Copyright (c) 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"""
6Get Descriptor Sequence
7
8Reference:
9  [1] Universal Serial Bus Communication Class MBIM Compliance Testing: 18
10      http://www.usb.org/developers/docs/devclass_docs/MBIM-Compliance-1.0.pdf
11"""
12
13from usb import control
14from usb import util
15
16import common
17from autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors
18from autotest_lib.client.cros.cellular.mbim_compliance.sequences import sequence
19from autotest_lib.client.cros.cellular.mbim_compliance.usb_descriptors import \
20  DescriptorParser
21
22
23class GetDescriptorsSequence(sequence.Sequence):
24    """
25    Implement the Get Descriptor Sequence.
26    Given the vendor and product id for a USB device, obtains the USB
27    descriptors for that device.
28    """
29
30    def run_internal(self):
31        """
32        Run the Get Descriptor Sequence.
33
34        @returns a list of descriptor objects.
35
36        """
37        if self.device_context is None:
38            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceFrameworkError,
39                                      'Test context not found')
40        device = self.device_context.device
41        if device is None:
42            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceFrameworkError,
43                                      'Device %04X:%04X not found' %
44                                      (self.device_context.id_vendor,
45                                       self.device_context.id_product))
46
47        configuration = device.get_active_configuration()
48
49        # Get the actual wTotalLength by retrieving partial descriptor.
50        # desc_index corresponds to the index of a configuration. Note that
51        # index is of 0 base while configuration is of 1 base.
52        descriptors_byte_stream = control.get_descriptor(
53                dev=device,
54                desc_size=9,
55                desc_type=util.DESC_TYPE_CONFIG,
56                desc_index=configuration.bConfigurationValue - 1,
57                wIndex=0)
58        if descriptors_byte_stream is None:
59            mbim_errors.log_and_raise(
60                    mbim_errors.MBIMComplianceSequenceError,
61                    'Failed to find configuration descriptor '
62                    'for active configuration of device '
63                    '%04X:%04X' % (device.idVendor, device.idProduct))
64
65        # Verify returned data is the requested size.
66        descriptor_length = descriptors_byte_stream[0]
67        if descriptor_length != 9:
68            mbim_errors.log_and_raise(mbim_errors.MBIMComplianceSequenceError,
69                                      'Expected bLength to be 9, got %d.' % (
70                                      descriptor_length))
71
72        descriptors_byte_stream = control.get_descriptor(
73                dev=device,
74                desc_size=descriptors_byte_stream[2],
75                desc_type=util.DESC_TYPE_CONFIG,
76                desc_index=configuration.bConfigurationValue - 1,
77                wIndex=0)
78        descriptors = [descriptor for descriptor
79                                  in DescriptorParser(descriptors_byte_stream)]
80        return descriptors
81