blob: eeff4dfcd7b8ca300a62c75c27cd67d3b8b79f47 [file] [log] [blame]
# Copyright 2014 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.
from autotest_lib.client.cros.cellular.mbim_compliance import mbim_errors
from autotest_lib.client.cros.cellular.mbim_compliance import usb_descriptors
class MbimDescriptorCache(object):
"""
Class used to store a cache of the most frequently used MBIM descriptors.
This caching of descriptors avoids frequent access to the device for
any control information.
"""
def __init__(self, descriptors):
"""
Store the the relevant descriptors from the list of descriptors.
@param descriptors: Raw descriptor set obtained from the device.
Type: Array of |usb_descriptors.Descriptor| objects.
"""
if self._check_ncm_mbim_device(descriptors):
self._update_ncm_mbim_cache(descriptors)
else:
self._update_mbim_cache(descriptors)
def _update_mbim_cache(self, descriptors):
"""
Parse and cache given raw |descriptors| as MBIM descriptors.
"""
self.is_mbim_only = True
# Fetch the MBIM communication interface
interfaces = usb_descriptors.filter_descriptors(
usb_descriptors.InterfaceDescriptor, descriptors)
mbim_communication_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.MBIM_ONLY_COMMUNICATION_INTERFACE))
if not mbim_communication_interfaces:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No MBIM communication interface descriptor found')
# Fetch the MBIM no_data data interface
no_data_data_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.MBIM_ONLY_DATA_INTERFACE_NO_DATA))
if not no_data_data_interfaces:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No No_Data data interface descriptor found')
# Fetch the MBIM data interface
mbim_data_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.MBIM_ONLY_DATA_INTERFACE_MBIM))
if not mbim_data_interfaces:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No MBIM data interface descriptor found')
# Fetch the MBIM function
mbim_communication_interface_bundle = (
usb_descriptors.get_descriptor_bundle(
descriptors, mbim_communication_interfaces[0]))
mbim_descriptors = usb_descriptors.filter_descriptors(
usb_descriptors.MBIMFunctionalDescriptor,
mbim_communication_interface_bundle)
if not mbim_descriptors:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No MBIM functional descriptor found')
# Fetch the MBIM interrupt enpoint
interrupt_endpoint_descriptors = usb_descriptors.filter_descriptors(
usb_descriptors.EndpointDescriptor,
mbim_communication_interface_bundle)
if not interrupt_endpoint_descriptors:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No MBIM Interrupt Endpoint descriptor found')
# Update with MBIM function settings.
self.ncm_communication_interface = None
self.mbim_communication_interface = mbim_communication_interfaces[0]
self.no_data_data_interface = no_data_data_interfaces[0]
self.ncm_data_interface = None
self.mbim_data_interface = mbim_data_interfaces[0]
self.mbim_functional = mbim_descriptors[0]
self.interrupt_endpoint = interrupt_endpoint_descriptors[0]
def _update_ncm_mbim_cache(self, descriptors):
"""
Parse and cache given raw |descriptors| as NCM + MBIM descriptors.
"""
self.is_mbim_only = False
# Fetch the NCM communication interface
interfaces = usb_descriptors.filter_descriptors(
usb_descriptors.InterfaceDescriptor, descriptors)
ncm_communication_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.NCM_MBIM_COMMUNICATION_INTERFACE_NCM))
# Fetch the MBIM communication interface
mbim_communication_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.NCM_MBIM_COMMUNICATION_INTERFACE_MBIM))
if not mbim_communication_interfaces:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No MBIM communication interface descriptor found')
# Fetch the NCM + MBIM no_data data interface
no_data_data_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.NCM_MBIM_DATA_INTERFACE_NO_DATA))
if not no_data_data_interfaces:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No No_Data data interface descriptor found')
# Fetch the NCM data interface
ncm_data_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.NCM_MBIM_DATA_INTERFACE_NCM))
if not ncm_data_interfaces:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No NCM data interface descriptor found')
# Fetch the MBIM data interface
mbim_data_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.NCM_MBIM_DATA_INTERFACE_MBIM))
if not mbim_data_interfaces:
mbim_errors.log_and_raise(
mbim_errors.MBIMComplianceTestError,
'No MBIM data interface descriptor found')
# Update with NCM + MBIM function settings.
self.ncm_communication_interface = ncm_communication_interfaces[0]
self.mbim_communication_interface = mbim_communication_interfaces[0]
self.no_data_data_interface = no_data_data_interfaces[0]
self.ncm_data_interface = ncm_data_interfaces[0]
self.mbim_data_interface = mbim_data_interfaces[0]
self.interrupt_endpoint = None
def _check_ncm_mbim_device(self, descriptors):
"""
Checks whether the connected device supports NCM + MBIM or MBIM only.
@returns True if the device supports NCM + MBIM, else False
"""
# Only a dual NCM/MBIM device has an NCM communication interface
# in its descriptors
interfaces = usb_descriptors.filter_descriptors(
usb_descriptors.InterfaceDescriptor, descriptors)
ncm_communication_interfaces = (
usb_descriptors.filter_interface_descriptors(
interfaces,
usb_descriptors.NCM_MBIM_COMMUNICATION_INTERFACE_NCM))
return bool(ncm_communication_interfaces)