92 lines
3.2 KiB
Python
92 lines
3.2 KiB
Python
import re
|
|
import logging
|
|
import serial.tools.list_ports
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class USBSerialDeviceInfo(object):
|
|
"""
|
|
Contains the information about a usb device in an easy to use way.
|
|
"""
|
|
device_name = None # Name of the usb device
|
|
port_name = None # Name of serial port to which the device is connected
|
|
vendor_id = None # USB vendor id
|
|
product_id = None # USB product id
|
|
|
|
def __str__(self):
|
|
if self.vendor_id is None:
|
|
vendor_id = str(self.vendor_id)
|
|
else:
|
|
vendor_id = '0x{:04x}'.format(self.vendor_id)
|
|
if self.product_id is None:
|
|
product_id = str(self.product_id)
|
|
else:
|
|
product_id = '0x{:04x}'.format(self.product_id)
|
|
return (self.device_name + ' VID=' + vendor_id + ' PID=' + product_id +
|
|
' on ' + self.port_name)
|
|
|
|
|
|
def extract_vid_pid(info_string):
|
|
"""
|
|
Try different methods of extracting vendor and product IDs from a string.
|
|
|
|
The output from serial.tools.list_ports.comports() varies so
|
|
widely from machine to machine and OS to OS, the only option we
|
|
have right now is to add to a list of patterns that we have seen so
|
|
far and compare the output.
|
|
|
|
info_string -- the string possibly containing vendor and product IDs.
|
|
|
|
Returns a tuple of (vendor ID, product ID) if a device is found.
|
|
If an ID isn't found, returns None.
|
|
"""
|
|
|
|
DEVICE_STRING_PATTERNS = [
|
|
# '...VID:PID=XXXX:XXXX...'
|
|
re.compile('.*VID:PID=([0-9A-Fa-f]{0,4}):([0-9A-Fa-f]{0,4}).*'),
|
|
|
|
# '...VID_XXXX...PID_XXXX...'
|
|
re.compile('.*VID_([0-9A-Fa-f]{0,4}).*PID_([0-9A-Fa-f]{0,4}).*')
|
|
]
|
|
|
|
for p in DEVICE_STRING_PATTERNS:
|
|
match = p.match(info_string)
|
|
if match:
|
|
return int(match.group(1), 16), int(match.group(2), 16)
|
|
return None
|
|
|
|
|
|
def find_usb_serial_devices(vendor_id=None, product_id=None):
|
|
"""
|
|
Discovers USB serial device(s) connected to the machine matching the input
|
|
arguments. If no arguments are given or both are None, returns all devices
|
|
found.
|
|
|
|
vendor_id -- the USB vendor id to match.
|
|
product_id -- the USB product id to match.
|
|
|
|
Returns a list of USBDeviceInfo objects matching the criteria given.
|
|
"""
|
|
devices = []
|
|
raw_devices = list(serial.tools.list_ports.comports())
|
|
log.debug("Found %d serial USB devices", len(raw_devices))
|
|
for device in raw_devices:
|
|
log.debug("Checking serial USB device: %s", device)
|
|
dev = USBSerialDeviceInfo()
|
|
dev.port_name = device[0]
|
|
dev.device_name = device[1]
|
|
found_device = extract_vid_pid(device[2])
|
|
if found_device is not None:
|
|
dev.vendor_id, dev.product_id = found_device
|
|
if vendor_id is None and product_id is None:
|
|
devices.append(dev)
|
|
elif dev.vendor_id == vendor_id and product_id is None:
|
|
devices.append(dev)
|
|
elif dev.product_id == product_id and vendor_id is None:
|
|
devices.append(dev)
|
|
elif dev.product_id == product_id and dev.vendor_id == vendor_id:
|
|
devices.append(dev)
|
|
log.debug("USB device: %s", dev)
|
|
return devices
|