| """Utility class representing a CfM USB device. |
| |
| This class represents actual data found by running the usb-device command. |
| """ |
| |
| class UsbDevice(object): |
| """Utility class representing a CfM USB device.""" |
| |
| def __init__(self, |
| vid, |
| pid, |
| product, |
| interfaces, |
| bus, |
| port, |
| level, |
| parent=None): |
| """ |
| Constructor. |
| |
| @param vid: Vendor ID. String. |
| @param pid: Product ID. String. |
| @param product: Product description. String |
| @param interfaces: List of strings. |
| @param bus: The bus this device is connected to. Number. |
| @param port: The port number as specified in /sys/bus/usb/devices/usb*. |
| Number. |
| @param level: The level in the device hierarchy this device is connected |
| at. A device connected directly to a port is typically at level 1. |
| @param parent: Optional parent UsbDevice. A parent device is a device that |
| this device is connected to, typically a USB Hub. |
| """ |
| self._vid = vid |
| self._pid = pid |
| self._product = product |
| self._interfaces = interfaces |
| self._bus = bus |
| self._port = port |
| self._level = level |
| self._parent = parent |
| |
| @property |
| def vendor_id(self): |
| """Returns the vendor id for this USB device.""" |
| return self._vid |
| |
| @property |
| def product_id(self): |
| """Returns the product id for this USB device.""" |
| return self._pid |
| |
| @property |
| def vid_pid(self): |
| """Return the <vendor_id>:<product_id> as a string.""" |
| return '%s:%s' % (self._vid, self._pid) |
| |
| @property |
| def product(self): |
| """Returns the product name.""" |
| return self._product |
| |
| @property |
| def interfaces(self): |
| """Returns the list of interfaces.""" |
| return self._interfaces |
| |
| @property |
| def port(self): |
| """Returns the port this USB device is connected to.""" |
| return self._port |
| |
| @property |
| def bus(self): |
| """Returns the bus this USB device is connected to.""" |
| return self._bus |
| |
| @property |
| def level(self): |
| """Returns the level of this USB Device.""" |
| return self._level |
| |
| @property |
| def parent(self): |
| """ |
| Returns the parent device of this device. |
| |
| Or None if this is the top level device. |
| @returns the parent or None. |
| """ |
| return self._parent |
| |
| @parent.setter |
| def parent(self, value): |
| """ |
| Sets the parent device of this device. |
| |
| We allow setting parents to make it easier to create the device tree. |
| @param value the new parent. |
| """ |
| self._parent = value |
| |
| def interfaces_match_spec(self, usb_device_spec): |
| """ |
| Checks that the interfaces of this device matches those of the given spec. |
| |
| @param usb_device_spec an instance of UsbDeviceSpec |
| @returns True or False |
| """ |
| # 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_spec.interfaces) |
| length = len(expected_interfaces) |
| actual_interfaces = sorted(self.interfaces) |
| return actual_interfaces[0:length] == expected_interfaces |
| |
| def get_parent(self, level): |
| """ |
| Gets the parent device at the specified level. |
| |
| Devices are connected in a hierarchy. Typically like this: |
| Level 0: Machine's internal USB hub |
| | |
| +--+ Level 1: Device connected to the machine's physical ports. |
| | |
| +--+ Level 2: If level 1 is a Hub, this is a device connected to |
| that Hub. |
| |
| A typical application of this method is when power cycling. Then we get a |
| device's parent at level 1 to locate the port that should be power cycled. |
| |
| @param level the level of the parent to return. |
| @returns A UsbDevice instance of the parent at the specified level. |
| @raises ValueError if we did not find a device at the specified level. |
| """ |
| device = self |
| while device != None: |
| if device.level < level: |
| raise ValueError( |
| 'Reached lower level without finding level %d', level) |
| if device.level == level: |
| return device |
| device = device.parent |
| |
| def __str__(self): |
| return "%s (%s)" % (self._product, self.vid_pid) |
| |
| def __repr__(self): |
| return "%s (%s), bus=%s, port=%s, parent=%s" % ( |
| self._product, self.vid_pid, self._bus, self._port, self.parent) |