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