1# Copyright 2017 The Chromium OS Authors. All rights reserved. 2# # Use of this source code is governed by a BSD-style license that can be 3# # found in the LICENSE file. 4# 5# """extract data from output of use-devices on linux box""" 6# The parser takes output of "usb-devices" as rawdata, and has capablities to 7# 1. Populate usb data into dictionary 8# 3. Extract defined peripheral devices based on CAMERA_LIST, SPEAKER_LIST. 9# 4. As of now only one type touch panel is defined here, which is Mimo. 10# 5. Check usb devices's interface. 11# 6. Retrieve usb device based on product and manufacture. 12# 13import cStringIO 14from autotest_lib.client.common_lib.cros import textfsm 15 16USB_DEVICES_TPLT = ( 17 'Value Required Vendor ([0-9a-fA-F]+)\n' 18 'Value Required ProdID ([0-9A-Fa-f]+)\n' 19 'Value Required prev ([0-9a-fA-Z.]+)\n' 20 'Value Manufacturer (.+)\n' 21 'Value Product (.+)\n' 22 'Value serialnumber ([0-9a-fA-Z\:\-]+)\n' 23 'Value cinterfaces (\d)\n' 24 'Value List intindex ([0-9])\n' 25 'Value List intdriver ([A-Za-z-\(\)]+)\n\n' 26 'Start\n' 27 ' ^USB-Device -> Continue.Record\n' 28 ' ^P:\s+Vendor=${Vendor}\s+ProdID=${ProdID}\sRev=${prev}\n' 29 ' ^S:\s+Manufacturer=${Manufacturer}\n' 30 ' ^S:\s+Product=${Product}\n' 31 ' ^S:\s+SerialNumber=${serialnumber}\n' 32 ' ^C:\s+\#Ifs=\s+${cinterfaces}\n' 33 ' ^I:\s+If\#=\s+${intindex}.*Driver=${intdriver}\n' 34) 35 36# As of now there are certain types of cameras, speakers and touch-panel. 37# New devices can be added to these global variables. 38CAMERA_LIST = ['2bd9:0011', '046d:0843', '046d:082d', '046d:0853', '064e:9405', 39 '046d:085f'] 40CAMERA_MAP = {'2bd9:0011':'Huddly GO', 41 '046d:0843':'Logitech Webcam C930e', 42 '046d:082d':'HD Pro Webcam C920', 43 '046d:0853':'PTZ Pro Camera', 44 '046d:085f':'PTZ Pro 2', 45 '064e:9405':'HD WebCam'} 46 47SPEAKER_LIST = ['18d1:8001', '0b0e:0412', '2abf:0505'] 48SPEAKER_MAP = {'18d1:8001':'Hangouts Meet speakermic', 49 '0b0e:0412':'Jabra SPEAK 410', 50 '2abf:0505':'FLX UC 500'} 51 52TOUCH_DISPLAY_LIST = ['17e9:016b','17e9:416d'] 53TOUCH_CONTROLLER_LIST = ['266e:0110'] 54 55DISPLAY_PANEL_MAP = {'17e9:016b':'DisplayLink', 56 '17e9:416d':'DisplayLink'} 57 58TOUCH_PANEL_MAP = {'266e:0110':'SiS HID Touch Controller'} 59 60 61INTERFACES_LIST = {'2bd9:0011':['uvcvideo', 'uvcvideo', 62 'uvcvideo', 'uvcvideo'], 63 '046d:0843':['uvcvideo', 'uvcvideo', 64 'snd-usb-audio', 'snd-usb-audio'], 65 '046d:082d':['uvcvideo', 'uvcvideo', 66 'snd-usb-audio', 'snd-usb-audio'], 67 '046d:085f': ['uvcvideo', 'uvcvideo','usbhid'], 68 '0b0e:0412':['snd-usb-audio', 'snd-usb-audio', 69 'snd-usb-audio'], 70 '18d1:8001':['snd-usb-audio', 'snd-usb-audio', 71 'snd-usb-audio', 'usbhid'], 72 '17e9:016b':['udl'], 73 '17e9:416d':['udl'], 74 '266e:0110':['usbhid'], 75 '046d:0853':['uvcvideo', 'uvcvideo','usbhid'], 76 '064e:9405':['uvcvideo', 'uvcvideo'], 77 '2abf:0505':['snd-usb-audio', 'snd-usb-audio', 78 'snd-usb-audio', 'usbhid'] 79 } 80 81 82def extract_usb_data(rawdata): 83 """populate usb data into list dictionary 84 @param rawdata: The output of "usb-devices" on CfM. 85 @returns list of dictionary, examples: 86 {'Manufacturer': 'USBest Technology', 'Product': 'SiS HID Touch Controller', 87 'Vendor': '266e', 'intindex': ['0'], 'tport': '00', 'tcnt': '01', 88 'serialnumber': '', 'tlev': '03', 'tdev': '18', 'dver': '', 89 'intdriver': ['usbhid'], 'tbus': '01', 'prev': '03.00', 90 'cinterfaces': '1', 'ProdID': '0110', 'tprnt': '14'} 91 """ 92 usbdata = [] 93 rawdata += '\n' 94 re_table = textfsm.TextFSM(cStringIO.StringIO(USB_DEVICES_TPLT)) 95 fsm_results = re_table.ParseText(rawdata) 96 usbdata = [dict(zip(re_table.header, row)) for row in fsm_results] 97 return usbdata 98 99 100def extract_peri_device(usbdata, vid_pid): 101 """retrive the list of dictionary for certain types of VID_PID 102 @param usbdata: list of dictionary for usb devices 103 @param vid_pid: list of vid_pid combination 104 @returns the list of dictionary for certain types of VID_PID 105 """ 106 vid_pid_usb_list = [] 107 for _vid_pid in vid_pid: 108 vid = _vid_pid.split(':')[0] 109 pid = _vid_pid.split(':')[1] 110 for _data in usbdata: 111 if vid == _data['Vendor'] and pid == _data['ProdID']: 112 vid_pid_usb_list.append(_data) 113 return vid_pid_usb_list 114 115 116def get_list_audio_device(usbdata): 117 """retrive the list of dictionary for all audio devices 118 @param usbdata: list of dictionary for usb devices 119 @returns the list of dictionary for all audio devices 120 """ 121 audio_device_list = [] 122 for _data in usbdata: 123 if "snd-usb-audio" in _data['intdriver']: 124 audio_device_list.append(_data) 125 return audio_device_list 126 127 128def get_list_video_device(usbdata): 129 """retrive the list of dictionary for all video devices 130 @param usbdata: list of dictionary for usb devices 131 @returns the list of dictionary for all video devices 132 """ 133 video_device_list = [] 134 for _data in usbdata: 135 if "uvcvideo" in _data['intdriver']: 136 video_device_list.append(_data) 137 return video_device_list 138 139 140def get_list_mimo_device(usbdata): 141 """retrive the list of dictionary for all touch panel devices 142 @param usbdata: list of dictionary for usb devices 143 @returns the lists of dictionary 144 one for displaylink, the other for touch controller 145 """ 146 displaylink_list = [] 147 touchcontroller_list = [] 148 for _data in usbdata: 149 if "udl" in _data['intdriver']: 150 displaylink_list.append(_data) 151 if "SiS HID Touch Controller" == _data['Product']: 152 touchcontroller_list.append(_data) 153 return displaylink_list, touchcontroller_list 154 155 156def get_list_by_product(usbdata, product_name): 157 """retrive the list of dictionary based on product_name 158 @param usbdata: list of dictionary for usb devices 159 @returns the list of dictionary 160 """ 161 usb_list_by_product = [] 162 for _data in usbdata: 163 if product_name == _data['Product']: 164 usb_list_by_product.append(_data) 165 return usb_list_by_product 166 167 168def get_list_by_manufacturer(usbdata, manufacturer_name): 169 """retrive the list of dictionary based on manufacturer_name 170 @param usbdata: list of dictionary for usb devices 171 @returns the list of dictionary 172 """ 173 usb_list_by_manufacturer = [] 174 for _data in usbdata: 175 if manufacturer_name == _data['Manufacturer']: 176 usb_list_by_manufacturer.append(_data) 177 return usb_list_by_manufacturer 178 179 180def is_usb_device_ok(usbdata, vid_pid): 181 """check usb device has expected usb interface 182 @param usbdata: list of dictionary for usb devices 183 @vid_pid: VID, PID combination for each type of USB device 184 @returns: 185 int: number of device 186 boolean: usb interfaces expected or not? 187 """ 188 number_of_device = 0 189 device_health = [] 190 vid = vid_pid[0:4] 191 pid = vid_pid[-4:] 192 for _data in usbdata: 193 if vid == _data['Vendor'] and pid == _data['ProdID']: 194 number_of_device += 1 195 compare_list = _data['intdriver'][0:len(INTERFACES_LIST[vid_pid])] 196 if cmp(compare_list, INTERFACES_LIST[vid_pid]) == 0: 197 device_health.append('1') 198 else: 199 device_health.append('0') 200 return number_of_device, device_health 201 202 203def get_speakers(usbdata): 204 """get number of speaker for each type 205 @param usbdata: list of dictionary for usb devices 206 @returns: list of dictionary, key is VID_PID, value is number of speakers 207 """ 208 number_speaker = {} 209 for _speaker in SPEAKER_LIST: 210 vid = _speaker.split(':')[0] 211 pid = _speaker.split(':')[1] 212 _number = 0 213 for _data in usbdata: 214 if _data['Vendor'] == vid and _data['ProdID'] == pid: 215 _number += 1 216 number_speaker[_speaker] = _number 217 return number_speaker 218 219 220def get_dual_speaker(usbdata): 221 """check whether dual speakers are present 222 @param usbdata: list of dictionary for usb devices 223 @returns: True or False 224 """ 225 dual_speaker = None 226 speaker_dict = get_speakers(usbdata) 227 for _key in speaker_dict.keys(): 228 if speaker_dict[_key] == 2: 229 dual_speaker = _key 230 break 231 return dual_speaker 232 233 234def get_cameras(usbdata): 235 """get number of camera for each type 236 @param usbdata: list of dictionary for usb devices 237 @returns: list of dictionary, key is VID_PID, value is number of cameras 238 """ 239 number_camera = {} 240 for _camera in CAMERA_LIST: 241 vid = _camera.split(':')[0] 242 pid = _camera.split(':')[1] 243 _number = 0 244 for _data in usbdata: 245 if _data['Vendor'] == vid and _data['ProdID'] == pid: 246 _number += 1 247 number_camera[_camera] = _number 248 return number_camera 249 250def get_display_mimo(usbdata): 251 """get number of displaylink in Mimo for each type 252 @param usbdata: list of dictionary for usb devices 253 @returns: list of dictionary, key is VID_PID, value 254 is number of displaylink 255 """ 256 number_display = {} 257 for _display in TOUCH_DISPLAY_LIST: 258 vid = _display.split(':')[0] 259 pid = _display.split(':')[1] 260 _number = 0 261 for _data in usbdata: 262 if _data['Vendor'] == vid and _data['ProdID'] == pid: 263 _number += 1 264 number_display[_display] = _number 265 return number_display 266 267def get_controller_mimo(usbdata): 268 """get number of touch controller Mimo for each type 269 @param usbdata: list of dictionary for usb devices 270 @returns: list of dictionary, key is VID_PID, value 271 is number of touch controller 272 """ 273 number_controller = {} 274 for _controller in TOUCH_CONTROLLER_LIST: 275 vid = _controller.split(':')[0] 276 pid = _controller.split(':')[1] 277 _number = 0 278 for _data in usbdata: 279 if _data['Vendor'] == vid and _data['ProdID'] == pid: 280 _number += 1 281 number_controller[_controller] = _number 282 return number_controller 283 284def get_preferred_speaker(peripheral): 285 """get string for the 1st speakers in the device list 286 @param peripheral: of dictionary for usb devices 287 @returns: string for name of preferred speake 288 """ 289 for _key in peripheral: 290 if _key in SPEAKER_LIST: 291 speaker_name = SPEAKER_MAP[_key]+' ('+_key+')' 292 return speaker_name 293 294def get_preferred_camera(peripheral): 295 """get string for the 1st cameras in the device list 296 @param peripheral: of dictionary for usb devices 297 @returns: string for name of preferred camera 298 """ 299 for _key in peripheral: 300 if _key in CAMERA_LIST: 301 camera_name = CAMERA_MAP[_key]+' ('+_key+')' 302 return camera_name 303 304def get_device_prod(vid_pid): 305 """get product for vid_pid 306 @param vid_pid: vid and pid combo for device 307 @returns: product 308 """ 309 for _key in SPEAKER_MAP.keys(): 310 if _key == vid_pid: 311 return SPEAKER_MAP[_key] 312 for _key in CAMERA_MAP.keys(): 313 if _key == vid_pid: 314 return CAMERA_MAP[_key] 315 for _key in DISPLAY_PANEL_MAP.keys(): 316 if _key == vid_pid: 317 return DISPLAY_PANEL_MAP[_key] 318 for _key in TOUCH_PANEL_MAP.keys(): 319 if _key == vid_pid: 320 return TOUCH_PANEL_MAP[_key] 321 return None 322