• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"""
5Connect Sequence
6
7Reference:
8    [1] Universal Serial Bus Communication Class MBIM Compliance Testing: 20
9        http://www.usb.org/developers/docs/devclass_docs/MBIM-Compliance-1.0.pdf
10"""
11import array
12import common
13
14from autotest_lib.client.cros.cellular.mbim_compliance import mbim_channel
15from autotest_lib.client.cros.cellular.mbim_compliance \
16        import mbim_command_message
17from autotest_lib.client.cros.cellular.mbim_compliance import mbim_constants
18from autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors
19from autotest_lib.client.cros.cellular.mbim_compliance \
20        import mbim_message_request
21from autotest_lib.client.cros.cellular.mbim_compliance \
22        import mbim_message_response
23from autotest_lib.client.cros.cellular.mbim_compliance.sequences \
24        import sequence
25
26
27class ConnectSequence(sequence.Sequence):
28    """ Implement the Connect Sequence. """
29
30    def run_internal(self,
31                     introduce_error_in_access_offset=False,
32                     introduce_error_in_packets_order=None,
33                     raise_exception_on_failure=True):
34        """
35        Run the Connect Sequence.
36
37        Once the command message is sent, there should be at least one
38        notification received apart from the command done message.
39
40        @param introduce_error_in_access_offset: Whether to introduce an
41                error in the access_string offset or not.
42        @param introduce_error_in_packets_order: Whether to introduce an
43                error in the order of packets sent or not. It's a user provided
44                list of packet sequence numbers to reorder, repeat or remove
45                packets generated for connect before sending it to the device.
46        @param raise_exception_on_failure: Whether to raise an exception or not.
47        @returns tuple of (command_message, response_message, notifications):
48                command_message: The command message sent to device.
49                |command_message| is a MBIMCommandMessage object.
50                response_message: The response to the |command_message|.
51                |response_message| is a MBIMCommandDoneMessage object.
52                notifications: The list of notifications message sent from the
53                modem to the host. |notifications| is a list of
54                |MBIMIndicateStatusMessage| objects.
55        """
56        # Step 1
57        # Send MBIM_COMMAND_MSG.
58        context_type = mbim_constants.MBIM_CONTEXT_TYPE_INTERNET.bytes
59        data_buffer = array.array('B', 'loopback'.encode('utf-16le'))
60        information_buffer_length = (
61                mbim_command_message.MBIMSetConnect.get_struct_len())
62        information_buffer_length += len(data_buffer)
63        device_context = self.device_context
64        descriptor_cache = device_context.descriptor_cache
65        if introduce_error_in_access_offset:
66            access_string_offset = 0
67        else:
68            access_string_offset = 60
69        command_message = (
70                mbim_command_message.MBIMSetConnect(session_id=0,
71                        activation_command=1,
72                        access_string_offset=access_string_offset,
73                        access_string_size=16,
74                        user_name_offset=0,
75                        user_name_size=0,
76                        password_offset=0,
77                        password_size=0,
78                        compression=0,
79                        auth_protocol=0,
80                        ip_type=1,
81                        context_type=context_type,
82                        information_buffer_length=information_buffer_length,
83                        payload_buffer=data_buffer))
84        packets = mbim_message_request.generate_request_packets(
85                command_message,
86                device_context.max_control_transfer_size)
87        channel = mbim_channel.MBIMChannel(
88                device_context._device,
89                descriptor_cache.mbim_communication_interface.bInterfaceNumber,
90                descriptor_cache.interrupt_endpoint.bEndpointAddress,
91                device_context.max_control_transfer_size)
92        if introduce_error_in_packets_order is not None:
93            packets = [packets[i] for i in introduce_error_in_packets_order]
94        response_packets = channel.bidirectional_transaction(*packets)
95        notifications_packets = channel.get_outstanding_packets();
96        channel.close()
97
98        # Step 2
99        response_message = mbim_message_response.parse_response_packets(
100                response_packets)
101        notifications = []
102        for notification_packets in notifications_packets:
103            notifications.append(
104                    mbim_message_response.parse_response_packets(
105                            notification_packets))
106
107        # Step 3
108        if (response_message.message_type != mbim_constants.MBIM_COMMAND_DONE or
109            response_message.status_codes != mbim_constants.MBIM_STATUS_SUCCESS):
110            if raise_exception_on_failure:
111                mbim_errors.log_and_raise(
112                        mbim_errors.MBIMComplianceSequenceError,
113                        'Connect sequence failed.')
114
115        return command_message, response_message, notifications
116