Home | History | Annotate | Download | only in usb
      1 """Utility class representing a CfM USB device.
      2 
      3 This class represents actual data found by running the usb-device command.
      4 """
      5 
      6 class UsbDevice(object):
      7   """Utility class representing a CfM USB device."""
      8 
      9   def __init__(self,
     10                vid,
     11                pid,
     12                product,
     13                interfaces,
     14                bus,
     15                port,
     16                level,
     17                parent=None):
     18       """
     19       Constructor.
     20 
     21       @param vid: Vendor ID. String.
     22       @param pid: Product ID. String.
     23       @param product: Product description. String
     24       @param interfaces: List of strings.
     25       @param bus: The bus this device is connected to. Number.
     26       @param port: The port number as specified in /sys/bus/usb/devices/usb*.
     27           Number.
     28       @param level: The level in the device hierarchy this device is connected
     29           at. A device connected directly to a port is typically at level 1.
     30       @param parent: Optional parent UsbDevice. A parent device is a device that
     31           this device is connected to, typically a USB Hub.
     32       """
     33       self._vid = vid
     34       self._pid = pid
     35       self._product = product
     36       self._interfaces = interfaces
     37       self._bus = bus
     38       self._port = port
     39       self._level = level
     40       self._parent = parent
     41 
     42   @property
     43   def vendor_id(self):
     44       """Returns the vendor id for this USB device."""
     45       return self._vid
     46 
     47   @property
     48   def product_id(self):
     49       """Returns the product id for this USB device."""
     50       return self._pid
     51 
     52   @property
     53   def vid_pid(self):
     54       """Return the <vendor_id>:<product_id> as a string."""
     55       return '%s:%s' % (self._vid, self._pid)
     56 
     57   @property
     58   def product(self):
     59       """Returns the product name."""
     60       return self._product
     61 
     62   @property
     63   def interfaces(self):
     64       """Returns the list of interfaces."""
     65       return self._interfaces
     66 
     67   @property
     68   def port(self):
     69       """Returns the port this USB device is connected to."""
     70       return self._port
     71 
     72   @property
     73   def bus(self):
     74       """Returns the bus this USB device is connected to."""
     75       return self._bus
     76 
     77   @property
     78   def level(self):
     79       """Returns the level of this USB Device."""
     80       return self._level
     81 
     82   @property
     83   def parent(self):
     84       """
     85       Returns the parent device of this device.
     86 
     87       Or None if this is the top level device.
     88       @returns the parent or None.
     89       """
     90       return self._parent
     91 
     92   @parent.setter
     93   def parent(self, value):
     94       """
     95       Sets the parent device of this device.
     96 
     97       We allow setting parents to make it easier to create the device tree.
     98       @param value the new parent.
     99       """
    100       self._parent = value
    101 
    102   def interfaces_match_spec(self, usb_device_spec):
    103       """
    104       Checks that the interfaces of this device matches those of the given spec.
    105 
    106       @param usb_device_spec an instance of UsbDeviceSpec
    107       @returns True or False
    108       """
    109       # List of expected interfaces. This might be a sublist of the actual
    110       # list of interfaces. Note: we have to use lists and not sets since
    111       # the list of interfaces might contain duplicates.
    112       expected_interfaces = sorted(usb_device_spec.interfaces)
    113       length = len(expected_interfaces)
    114       actual_interfaces = sorted(self.interfaces)
    115       return actual_interfaces[0:length] == expected_interfaces
    116 
    117   def get_parent(self, level):
    118       """
    119       Gets the parent device at the specified level.
    120 
    121       Devices are connected in a hierarchy. Typically like this:
    122       Level 0: Machine's internal USB hub
    123        |
    124        +--+ Level 1: Device connected to the machine's physical ports.
    125          |
    126          +--+ Level 2: If level 1 is a Hub, this is a device connected to
    127                        that Hub.
    128 
    129       A typical application of this method is when power cycling. Then we get a
    130       device's parent at level 1 to locate the port that should be power cycled.
    131 
    132       @param level the level of the parent to return.
    133       @returns A UsbDevice instance of the parent at the specified level.
    134       @raises ValueError if we did not find a device at the specified level.
    135       """
    136       device = self
    137       while device != None:
    138           if device.level < level:
    139               raise ValueError(
    140                   'Reached lower level without finding level %d', level)
    141           if device.level == level:
    142               return device
    143           device = device.parent
    144 
    145   def __str__(self):
    146       return "%s (%s)" % (self._product, self.vid_pid)
    147 
    148   def __repr__(self):
    149       return "%s (%s), bus=%s, port=%s, parent=%s" % (
    150               self._product, self.vid_pid, self._bus, self._port, self.parent)
    151