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