132694e182daed32e30dbc9d13d8af0154660cf1cRoshan Pius# Copyright 2015 The Chromium OS Authors. All rights reserved.
2e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius# Use of this source code is governed by a BSD-style license that can be
3e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius# found in the LICENSE file.
4e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius"""
5e938ff00845c29f56935f2b973dd677793b8d834Roshan PiusAll of the MBIM response message type definitions are in this file. These
6e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusdefinitions inherit from MBIMControlMessage.
7e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
8e938ff00845c29f56935f2b973dd677793b8d834Roshan PiusReference:
9e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    [1] Universal Serial Bus Communications Class Subclass Specification for
10e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        Mobile Broadband Interface Model
11e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        http://www.usb.org/developers/docs/devclass_docs/
12e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        MBIM10Errata1_073013.zip
13e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius"""
14e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusimport logging
15e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
16e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusfrom autotest_lib.client.cros.cellular.mbim_compliance import mbim_constants
17e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Piusfrom autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors
18e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusfrom autotest_lib.client.cros.cellular.mbim_compliance import mbim_message
19e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
20e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
21e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMControlMessageResponse(mbim_message.MBIMControlMessage):
22e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ MBIMMessage Response Message base class. """
23e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius
24e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    MESSAGE_TYPE = mbim_message.MESSAGE_TYPE_RESPONSE
25e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _FIELDS = (('I', 'message_type', mbim_message.FIELD_TYPE_PAYLOAD_ID),
26e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius               ('I', 'message_length', mbim_message.FIELD_TYPE_TOTAL_LEN),
27e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'transaction_id', ''))
28e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
29e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius
30e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMOpenDone(MBIMControlMessageResponse):
31e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ The class for MBIM_OPEN_DONE. """
32e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
33e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _FIELDS = (('I', 'status_codes', ''),)
34e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _IDENTIFIERS = {'message_type': mbim_constants.MBIM_OPEN_DONE}
35e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
36e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
37e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMCloseDone(MBIMControlMessageResponse):
38e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ The class for MBIM_CLOSE_DONE. """
39e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
40e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _FIELDS = (('I', 'status_codes', ''),)
41e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _IDENTIFIERS = {'message_type': mbim_constants.MBIM_CLOSE_DONE}
42e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
43e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
44e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMCommandDoneSecondary(MBIMControlMessageResponse):
45e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ The class for MBIM_COMMAND_DONE. """
46e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
47e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    _FIELDS = (('I', 'total_fragments', mbim_message.FIELD_TYPE_NUM_FRAGMENTS),
48e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'current_fragment', ''))
49e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
50e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
51e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMCommandDone(MBIMControlMessageResponse):
52e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ The class for MBIM_COMMAND_DONE. """
53e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
54e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    _FIELDS = (('I', 'total_fragments', mbim_message.FIELD_TYPE_NUM_FRAGMENTS),
55e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'current_fragment', ''),
56e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('16s', 'device_service_id', mbim_message.FIELD_TYPE_PAYLOAD_ID),
57e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'cid', mbim_message.FIELD_TYPE_PAYLOAD_ID),
58e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'status_codes', ''),
59e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius               ('I', 'information_buffer_length',
60e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                mbim_message.FIELD_TYPE_PAYLOAD_LEN))
61e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _IDENTIFIERS = {'message_type': mbim_constants.MBIM_COMMAND_DONE}
62e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _SECONDARY_FRAGMENT = MBIMCommandDoneSecondary
63e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
64e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
65e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMIndicateStatusSecondary(MBIMControlMessageResponse):
66e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ The class for MBIM_INDICATE_STATUS_MSG. """
67e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
68e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    _FIELDS = (('I', 'total_fragments', mbim_message.FIELD_TYPE_NUM_FRAGMENTS),
69e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'current_fragment', ''))
70e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
71e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
72e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMIndicateStatus(MBIMControlMessageResponse):
73e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ The class for MBIM_INDICATE_STATUS_MSG. """
74e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
75e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    _FIELDS = (('I', 'total_fragments', mbim_message.FIELD_TYPE_NUM_FRAGMENTS),
76e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'current_fragment', ''),
77e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('16s', 'device_service_id', mbim_message.FIELD_TYPE_PAYLOAD_ID),
78e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius               ('I', 'cid', mbim_message.FIELD_TYPE_PAYLOAD_ID),
79e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius               ('I', 'information_buffer_length',
80e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                mbim_message.FIELD_TYPE_PAYLOAD_LEN))
81e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _IDENTIFIERS = {'message_type': mbim_constants.MBIM_INDICATE_STATUS_MSG}
82e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _SECONDARY_FRAGMENT = MBIMIndicateStatusSecondary
83e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
84e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
85e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusclass MBIMFunctionError(MBIMControlMessageResponse):
86e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """ The class for MBIM_FUNCTION_ERROR_MSG. """
87e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
88e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _FIELDS = (('I', 'error_status_code', ''),)
89e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    _IDENTIFIERS = {'message_type': mbim_constants.MBIM_FUNCTION_ERROR_MSG}
90e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
91e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
92e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusdef reassemble_response_packets(primary_fragment, secondary_packets):
93e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """
94e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    Reassembles fragmented response messages into a single object.
95e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
96e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    It parses all the secondary fragments as |secondary_frag_class| and
97e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    merges all the payload_buffer fields into the primary fragment.
98e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
99e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    @param primary_fragment: Primary fragment message object.
100e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    @param secondary_packets: Array of the raw byte array response received
101e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius                               from device.
102e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    @returns Reassembled Response Message object.
103e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
104e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """
105e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    secondary_frag_class = primary_fragment.get_secondary_fragment()
106e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    # Check if we can reassemble at this tree level or not. If there is
107e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    # no associated _SECONDARY_FRAG_CLASS, we need to go down the tree further
108e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    # to reassemble.
109e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    if not secondary_frag_class:
110e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius        return None
111e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
112e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    for packet in secondary_packets:
113e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        secondary_fragment = secondary_frag_class(raw_data=packet)
114e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        primary_fragment.payload_buffer.extend(
115e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius            secondary_fragment.payload_buffer)
116e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius
117e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    payload_len = primary_fragment.get_payload_len()
118e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    num_fragments = primary_fragment.get_num_fragments()
119e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    if ((num_fragments != len(secondary_packets) + 1) or
120e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius        (payload_len != len(primary_fragment.payload_buffer))):
121e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius        mbim_errors.log_and_raise(mbim_errors.MBIMComplianceAssertionError,
122e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                                  'mbim1.0:9.2')
123e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    total_length = primary_fragment.calculate_total_len()
124e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    primary_fragment =  primary_fragment.copy(message_length=total_length)
125e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    logging.debug('Reassembled response-> Fragments: %d, Payload length: %d',
126e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                  num_fragments, payload_len)
127e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    return primary_fragment
128e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
129e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
130e938ff00845c29f56935f2b973dd677793b8d834Roshan Piusdef parse_response_packets(packets):
131e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """
132e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    Parses the incoming raw data |packets| into corresponding message response
133e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    object.
134e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
135e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    The function starts the at the root of the message hierarchy tree
136e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    and then goes down the root to find the exact leaf node message class. If
137e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    there are multiple frgaments expected at any level, it will reassemble the
138e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    secondary fragments before proceeding.
139e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
140e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    @param packets: Array of the raw byte array response received from device.
141e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    @returns Response Message object.
142e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius
143e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    """
144e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    # Start with the root class for all responses and then go down the tree.
145e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    message_class = MBIMControlMessageResponse
146e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    parse_packets = packets
147e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius
148e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    while message_class is not None:
149e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius        first_packet = parse_packets[0]
150e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius        message = message_class(raw_data=first_packet)
151e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        # If there are secondary fragments expected at this level,
152e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        # let's reassemble the payload together before traversing down the
153e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        # message heirarchy.
154e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius        if len(parse_packets) > 1:
155e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius            reassembled_message = reassemble_response_packets(message,
156e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                                                              parse_packets[1:])
157e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius            if reassembled_message is not None:
158e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                message = reassembled_message
159e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                reassembled_packet = message.create_raw_data()
160e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius                parse_packets = [reassembled_packet]
161e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius        message_class = message.find_payload_class()
162e234d66871ea1b7e1e2280a10f48a85eaa9a734cRoshan Pius    logging.debug("Response Message parsed: %s", message)
163e938ff00845c29f56935f2b973dd677793b8d834Roshan Pius    return message
164