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 5import logging 6import struct 7from usb import control 8 9import common 10from autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors 11from autotest_lib.client.cros.cellular.mbim_compliance.sequences \ 12 import sequence 13 14# The maximun datagram size used in SetMaxDatagramSize request. 15MAX_DATAGRAM_SIZE = 1514 16 17 18#TODO(rpius): Move to a more appropriate location. Maybe a utility file? 19class NtbParameters(object): 20 """ The class for NTB Parameter Structure. """ 21 22 _FIELDS = [('H','wLength'), 23 ('H','bmNtbFormatsSupported'), 24 ('I','dwNtbInMaxSize'), 25 ('H','wNdpInDivisor'), 26 ('H','wNdpInPayloadRemainder'), 27 ('H','wNdpInAlignment'), 28 ('H','reserved'), 29 ('I','dwNtbOutMaxSize'), 30 ('H','wNdpOutDivisor'), 31 ('H','wNdpOutPayloadRemainder'), 32 ('H','wNdpOutAlignment'), 33 ('H','wNtbOutMaxDatagrams')] 34 35 36 def __init__(self, *args): 37 _, field_names = zip(*self._FIELDS) 38 if len(args) != len(field_names): 39 mbim_errors.log_and_raise( 40 mbim_errors.MBIMComplianceError, 41 'Expected %d arguments for %s constructor, got %d.' % ( 42 len(field_names),self.__class__.__name__,len(args))) 43 44 fields = zip(field_names, args) 45 for field in fields: 46 setattr(self, field[0], field[1]) 47 48 49 @classmethod 50 def get_format_string(cls): 51 """ 52 @returns The format string composed of concatenated field formats. 53 """ 54 field_formats, _ = zip(*cls._FIELDS) 55 return ''.join(field_format for field_format in field_formats) 56 57 58class OpenSequence(sequence.Sequence): 59 """ Base case for all MBIM open sequneces. """ 60 61 def set_alternate_setting(self, interface_number, alternate_setting): 62 """ 63 Set alternate setting to |alternate_setting| for the target interface. 64 65 @param inteface_number: the index of target interface 66 @param alternate_setting: expected value of alternate setting 67 68 """ 69 logging.debug('SetInterface request: %d to interface-%d.', 70 alternate_setting, interface_number) 71 control.set_interface(self.device_context.device, 72 interface_number, 73 alternate_setting) 74 75 76 def reset_function(self, interface_number): 77 """ 78 Send ResetFunction() request to the target interface. 79 80 @param interface_number: the index of target interface 81 82 """ 83 logging.debug('ResetFunction request to interface-%d.', 84 interface_number) 85 self.device_context.device.ctrl_transfer(bmRequestType=0b00100001, 86 bRequest=0x05, 87 wValue=0, 88 wIndex=interface_number, 89 data_or_wLength=None) 90 91 92 def get_ntb_parameters(self, interface_number): 93 """ 94 Retrieve NTB parameters of the target interface. 95 96 @param interface_number: the index of target interface 97 @returns NTB parameters in byte stream. 98 99 """ 100 logging.debug('GetNtbParameters request to interface-%d.', 101 interface_number) 102 ntb_parameters = self.device_context.device.ctrl_transfer( 103 bmRequestType=0b10100001, 104 bRequest=0x80, 105 wValue=0, 106 wIndex=interface_number, 107 data_or_wLength=28) 108 logging.debug('Response: %s', ntb_parameters) 109 format_string = NtbParameters.get_format_string() 110 return NtbParameters( 111 *struct.unpack_from('<' + format_string, ntb_parameters)) 112 113 114 def set_ntb_format(self, interface_number, ntb_format): 115 """ 116 Send SetNtbFormat() request to the target interface. 117 118 @param interface_number: the index of target interface 119 @param ntb_format: The NTB format should be either |NTB_16| or |NTB_32|. 120 121 """ 122 logging.debug('SetNtbFormat request: %d to interface-%d.', 123 ntb_format, interface_number) 124 response = self.device_context.device.ctrl_transfer( 125 bmRequestType=0b00100001, 126 bRequest=0x84, 127 wValue=ntb_format, 128 wIndex=interface_number, 129 data_or_wLength=None) 130 logging.debug('Response: %s', response) 131 132 133 def get_ntb_format(self, interface_number): 134 """ 135 Send GetNtbFormat() request to the target interface. 136 137 @param interface_number: the index of target interface 138 @returns ntb_format: The NTB format currently set. 139 140 """ 141 logging.debug('GetNtbFormat request to interface-%d.', 142 interface_number) 143 response = self.device_context.device.ctrl_transfer( 144 bmRequestType=0b10100001, 145 bRequest=0x83, 146 wValue=0, 147 wIndex=interface_number, 148 data_or_wLength=2) 149 logging.debug('Response: %s', response) 150 return response 151 152 153 def set_ntb_input_size(self, interface_number, dw_ntb_in_max_size): 154 """ 155 Send SetNtbInputSize() request to the target interface. 156 157 @param interface_number:the index of target interface 158 @param dw_ntb_in_max_size: The maxinum NTB size to set. 159 160 """ 161 logging.debug('SetNtbInputSize request: %d to interface-%d.', 162 dw_ntb_in_max_size, interface_number) 163 data = struct.pack('<I', dw_ntb_in_max_size) 164 response = self.device_context.device.ctrl_transfer( 165 bmRequestType=0b00100001, 166 bRequest=0x86, 167 wIndex=interface_number, 168 data_or_wLength=data) 169 logging.debug('Response: %s', response) 170 171 172 def set_max_datagram_size(self, interface_number): 173 """ 174 Send SetMaxDatagramSize() request to the target interface. 175 176 @param interface_number: the index of target interface 177 178 """ 179 logging.debug('SetMaxDatagramSize request: %d to interface-%d.', 180 MAX_DATAGRAM_SIZE, interface_number) 181 data = struct.pack('<H', MAX_DATAGRAM_SIZE) 182 response = self.device_context.device.ctrl_transfer( 183 bmRequestType=0b00100001, 184 bRequest=0x88, 185 wIndex=interface_number, 186 data_or_wLength=data) 187 logging.debug('Response: %s', response) 188