xref: /aosp_15_r20/external/autotest/client/common_lib/cros/manual/get_usb_devices.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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