blob: 8b40897a24bf5e98ef413f964e6bb2319d7459bc [file] [log] [blame]
# Copyright 2017 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.
#
# """extract data from output of use-devices on linux box"""
# The parser takes output of "usb-devices" as rawdata, and has capablities to
# 1. Populate usb data into dictionary
# 3. Extract defined peripheral devices based on CAMERA_MAP, SPEAKER_MAP.
# 4. As of now only one type touch panel is defined here, which is Mimo.
# 5. Check usb devices's interface.
# 6. Retrieve usb device based on product and manufacturer.
import cStringIO
import textfsm
from autotest_lib.client.common_lib.cros.cfm import cfm_usb_devices
USB_DEVICES_TPLT = (
'Value Required Vendor ([0-9a-fA-F]+)\n'
'Value Required ProdID ([0-9A-Fa-f]+)\n'
'Value Required prev ([0-9a-fA-Z.]+)\n'
'Value Manufacturer (.+)\n'
'Value Product (.+)\n'
'Value serialnumber ([0-9a-fA-Z\:\-]+)\n'
'Value cinterfaces (\d)\n'
'Value List intindex ([0-9])\n'
'Value List intdriver ([A-Za-z-\(\)]+)\n\n'
'Start\n'
' ^USB-Device -> Continue.Record\n'
' ^P:\s+Vendor=${Vendor}\s+ProdID=${ProdID}\sRev=${prev}\n'
' ^S:\s+Manufacturer=${Manufacturer}\n'
' ^S:\s+Product=${Product}\n'
' ^S:\s+SerialNumber=${serialnumber}\n'
' ^C:\s+\#Ifs=\s+${cinterfaces}\n'
' ^I:\s+If\#=\s+${intindex}.*Driver=${intdriver}\n'
)
def _extract_usb_data(rawdata):
"""populate usb data into list dictionary
@param rawdata The output of "usb-devices" on CfM.
@returns list of dictionary, examples:
{'Manufacturer': 'USBest Technology', 'Product': 'SiS HID Touch Controller',
'Vendor': '266e', 'intindex': ['0'], 'tport': '00', 'tcnt': '01',
'serialnumber': '', 'tlev': '03', 'tdev': '18', 'dver': '',
'intdriver': ['usbhid'], 'tbus': '01', 'prev': '03.00',
'cinterfaces': '1', 'ProdID': '0110', 'tprnt': '14'}
"""
usbdata = []
rawdata += '\n'
re_table = textfsm.TextFSM(cStringIO.StringIO(USB_DEVICES_TPLT))
fsm_results = re_table.ParseText(rawdata)
usbdata = [dict(zip(re_table.header, row)) for row in fsm_results]
return usbdata
def _extract_peri_device(usbdata, vid_pids):
"""retrieve the list of dictionary for certain types of VID_PID
@param usbdata list of dictionary for usb devices
@param vid_pids list of vid_pid combination
@returns the list of dictionary for certain types of VID_PID
"""
vid_pid_usb_list = []
for vid_pid in vid_pids:
vid_pid_usb_list.extend(_filter_by_vid_pid(usbdata, vid_pid))
return vid_pid_usb_list
def _get_list_audio_device(usbdata):
"""retrieve the list of dictionary for all audio devices
@param usbdata list of dictionary for usb devices
@returns the list of dictionary for all audio devices
"""
audio_device_list = []
for _data in usbdata:
if "snd-usb-audio" in _data['intdriver']:
audio_device_list.append(_data)
return audio_device_list
def _get_list_video_device(usbdata):
"""retrieve the list of dictionary for all video devices
@param usbdata list of dictionary for usb devices
@returns the list of dictionary for all video devices
"""
video_device_list = []
for _data in usbdata:
if "uvcvideo" in _data['intdriver']:
video_device_list.append(_data)
return video_device_list
def _get_list_mimo_device(usbdata):
"""retrieve the list of dictionary for all touch panel devices
@param usbdata list of dictionary for usb devices
@returns the lists of dictionary
one for displaylink, the other for touch controller
"""
displaylink_list = []
touchcontroller_list = []
for _data in usbdata:
if "udl" in _data['intdriver']:
displaylink_list.append(_data)
if "SiS HID Touch Controller" == _data['Product']:
touchcontroller_list.append(_data)
return displaylink_list, touchcontroller_list
def _get_list_by_product(usbdata, product_name):
"""retrieve the list of dictionary based on product_name
@param usbdata list of dictionary for usb devices
@returns the list of dictionary
"""
usb_list_by_product = []
for _data in usbdata:
if product_name == _data['Product']:
usb_list_by_product.append(_data)
return usb_list_by_product
def _get_list_by_manufacturer(usbdata, manufacturer_name):
"""retrieve the list of dictionary based on manufacturer_name
@param usbdata list of dictionary for usb devices
@returns the list of dictionary
"""
usb_list_by_manufacturer = []
for _data in usbdata:
if manufacturer_name == _data['Manufacturer']:
usb_list_by_manufacturer.append(_data)
return usb_list_by_manufacturer
def _get_vid_and_pid(vid_pid):
"""Parses out Vendor ID and Product ID from vid:pid string.
@param vid_pid String on format vid:pid.
@returns (vid,pid) tuple
"""
assert ':' in vid_pid
return vid_pid.split(':')
def _verify_usb_device_ok(usbdata, vid_pid):
"""
Verifies that usb device has expected usb interfaces.
@param usbdata list of dictionary for usb devices
@param vid_pid VID, PID combination for the USB device to check.
"""
device_found = False
# Retrieve a spec for this vid:pid
usb_device = cfm_usb_devices.get_usb_device(vid_pid)
# List of expected interfaces. This might be a sublist of the actual list of
# interfaces. Note: we have to use lists and not sets since the list of
# interfaces might contain duplicates.
expected_interfaces = sorted(usb_device.interfaces)
length = len(expected_interfaces)
# Find all actual UsbDevices matching the vid:pid
for _data in _filter_by_vid_pid(usbdata, vid_pid):
device_found = True
actual_interfaces = sorted(_data['intdriver'])[0:length]
if not actual_interfaces == expected_interfaces:
raise RuntimeError(
'Device %s has unexpected interfaces.' % vid_pid)
if not device_found:
raise RuntimeError('Expected at least one %s connected.' % vid_pid)
def _get_speakers(usbdata):
"""get number of speaker for each type
@param usbdata list of dictionary for usb devices
@returns list of dictionary, key is VID_PID, value is number of speakers
"""
number_speaker = {}
for speaker in cfm_usb_devices.get_speakers():
_number = len(_filter_by_vid_pid(usbdata, speaker.vid_pid))
number_speaker[speaker.vid_pid] = _number
return number_speaker
def _get_cameras(usbdata):
"""get number of camera for each type
@param usbdata list of dictionary for usb devices
@returns list of dictionary, key is VID_PID, value is number of cameras
"""
number_camera = {}
for camera in cfm_usb_devices.get_cameras():
_number = len(_filter_by_vid_pid(usbdata, camera.vid_pid))
number_camera[camera.vid_pid] = _number
return number_camera
def _get_display_mimo(usbdata):
"""get number of displaylink in Mimo for each type
@param usbdata list of dictionary for usb devices
@returns list of dictionary, key is VID_PID, value
is number of displaylink
"""
number_display = {}
for _display in cfm_usb_devices.get_mimo_displays():
_number = len(_filter_by_vid_pid(usbdata, _display.vid_pid))
number_display[_display.vid_pid] = _number
return number_display
def _get_controller_mimo(usbdata):
"""get number of touch controller Mimo for each type
@param usbdata list of dictionary for usb devices
@returns list of dictionary, key is VID_PID, value
is number of touch controller
"""
number_controller = {}
for _controller in cfm_usb_devices.get_mimo_controllers():
_number = len(_filter_by_vid_pid(usbdata, _controller.vid_pid))
number_controller[_controller.vid_pid] = _number
return number_controller
def _get_preferred_speaker(peripherals):
"""
Get string for the 1st speakers in the device list
@param peripheral dictionary for usb devices
@returns name of preferred speaker
"""
for vid_pid in peripherals:
return next((s.full_name for s in cfm_usb_devices.get_speakers()
if s.vid_pid == vid_pid), None)
def _get_preferred_camera(peripherals):
"""
Get string for the 1st camera in the device list
@param peripheral dictionary for usb devices
@returns name of preferred camera
"""
for vid_pid in peripherals:
return next((c.full_name for c in cfm_usb_devices.get_cameras()
if c.vid_pid == vid_pid), None)
def _get_device_prod(vid_pid):
"""
Get product for vid_pid
@param vid_pid vid and pid combo for device
@returns product
"""
device = next((s for s in cfm_usb_devices.get_speakers()
if s.vid_pid == vid_pid), None)
if device:
return device
return next((c for c in cfm_usb_devices.get_cameras()
if c.vid_pid == vid_pid), None)
def _filter_by_vid_pid(usbdata, vid_pid):
"""
Utility method for filter out items by vid and pid.
@param usbdata list of dictionaries with usb device data
@param vid_pid list of vid_pid combination
@return list of dictionaries with usb devices with the
the given vid and pid
"""
vid, pid = _get_vid_and_pid(vid_pid)
return [u for u in usbdata if
vid == u['Vendor'] and pid == u['ProdID']]