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