| # 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) |