# Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import struct
from usb import control
import common
from autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors
from autotest_lib.client.cros.cellular.mbim_compliance.sequences \
import sequence
# The maximun datagram size used in SetMaxDatagramSize request.
MAX_DATAGRAM_SIZE = 1514
#TODO(rpius): Move to a more appropriate location. Maybe a utility file?
class NtbParameters(object):
""" The class for NTB Parameter Structure. """
_FIELDS = [('H','wLength'),
('H','bmNtbFormatsSupported'),
('I','dwNtbInMaxSize'),
('H','wNdpInDivisor'),
('H','wNdpInPayloadRemainder'),
('H','wNdpInAlignment'),
('H','reserved'),
('I','dwNtbOutMaxSize'),
('H','wNdpOutDivisor'),
('H','wNdpOutPayloadRemainder'),
('H','wNdpOutAlignment'),
('H','wNtbOutMaxDatagrams')]
def __init__(self, *args):
_, field_names = zip(*self._FIELDS)
if len(args) != len(field_names):
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceError,
'Expected %d arguments for %s constructor, got %d.' % (
len(field_names),self.__class__.__name__,len(args)))
fields = zip(field_names, args)
for field in fields:
setattr(self, field[0], field[1])
@classmethod
def get_format_string(cls):
"""
@returns The format string composed of concatenated field formats.
"""
field_formats, _ = zip(*cls._FIELDS)
return ''.join(field_format for field_format in field_formats)
class OpenSequence(sequence.Sequence):
""" Base case for all MBIM open sequneces. """
def set_alternate_setting(self, interface_number, alternate_setting):
"""
Set alternate setting to |alternate_setting| for the target interface.
@param inteface_number: the index of target interface
@param alternate_setting: expected value of alternate setting
"""
logging.debug('SetInterface request: %d to interface-%d.',
alternate_setting, interface_number)
control.set_interface(self.device_context.device,
interface_number,
alternate_setting)
def reset_function(self, interface_number):
"""
Send ResetFunction() request to the target interface.
@param interface_number: the index of target interface
"""
logging.debug('ResetFunction request to interface-%d.',
interface_number)
self.device_context.device.ctrl_transfer(bmRequestType=0b00100001,
bRequest=0x05,
wValue=0,
wIndex=interface_number,
data_or_wLength=None)
def get_ntb_parameters(self, interface_number):
"""
Retrieve NTB parameters of the target interface.
@param interface_number: the index of target interface
@returns NTB parameters in byte stream.
"""
logging.debug('GetNtbParameters request to interface-%d.',
interface_number)
ntb_parameters = self.device_context.device.ctrl_transfer(
bmRequestType=0b10100001,
bRequest=0x80,
wValue=0,
wIndex=interface_number,
data_or_wLength=28)
logging.debug('Response: %s', ntb_parameters)
format_string = NtbParameters.get_format_string()
return NtbParameters(
*struct.unpack_from('<' + format_string, ntb_parameters))
def set_ntb_format(self, interface_number, ntb_format):
"""
Send SetNtbFormat() request to the target interface.
@param interface_number: the index of target interface
@param ntb_format: The NTB format should be either |NTB_16| or |NTB_32|.
"""
logging.debug('SetNtbFormat request: %d to interface-%d.',
ntb_format, interface_number)
response = self.device_context.device.ctrl_transfer(
bmRequestType=0b00100001,
bRequest=0x84,
wValue=ntb_format,
wIndex=interface_number,
data_or_wLength=None)
logging.debug('Response: %s', response)
def get_ntb_format(self, interface_number):
"""
Send GetNtbFormat() request to the target interface.
@param interface_number: the index of target interface
@returns ntb_format: The NTB format currently set.
"""
logging.debug('GetNtbFormat request to interface-%d.',
interface_number)
response = self.device_context.device.ctrl_transfer(
bmRequestType=0b10100001,
bRequest=0x83,
wValue=0,
wIndex=interface_number,
data_or_wLength=2)
logging.debug('Response: %s', response)
return response
def set_ntb_input_size(self, interface_number, dw_ntb_in_max_size):
"""
Send SetNtbInputSize() request to the target interface.
@param interface_number:the index of target interface
@param dw_ntb_in_max_size: The maxinum NTB size to set.
"""
logging.debug('SetNtbInputSize request: %d to interface-%d.',
dw_ntb_in_max_size, interface_number)
data = struct.pack('<I', dw_ntb_in_max_size)
response = self.device_context.device.ctrl_transfer(
bmRequestType=0b00100001,
bRequest=0x86,
wIndex=interface_number,
data_or_wLength=data)
logging.debug('Response: %s', response)
def set_max_datagram_size(self, interface_number):
"""
Send SetMaxDatagramSize() request to the target interface.
@param interface_number: the index of target interface
"""
logging.debug('SetMaxDatagramSize request: %d to interface-%d.',
MAX_DATAGRAM_SIZE, interface_number)
data = struct.pack('<H', MAX_DATAGRAM_SIZE)
response = self.device_context.device.ctrl_transfer(
bmRequestType=0b00100001,
bRequest=0x88,
wIndex=interface_number,
data_or_wLength=data)
logging.debug('Response: %s', response)