def __init__(self, device, setting, name=None, default_timeout_ms=None): """Initialize a local libusb-based USB Handle. Arguments: device: libusb device to connect to. setting: libusb setting with the endpoints to use for data reads/writes. name: Name for the device, used for log messages only. default_timeout_ms: Default timeout, in milliseconds, for reads/writes. Raises: InvalidEndpointsError: If the setting provided does not have exactly one in endpoint and one out endpoint. Currently, this is the only type of interface supported. IOError: If the device has been disconnected. """ super(LibUsbHandle, self).__init__(device.getSerialNumber(), name=name, default_timeout_ms=default_timeout_ms) self._setting = setting self._device = device self._read_endpoint = None self._write_endpoint = None self._handle = None for endpoint in self._setting.iterEndpoints(): address = endpoint.getAddress() if address & libusb1.USB_ENDPOINT_DIR_MASK == libusb1.LIBUSB_ENDPOINT_IN: if self._read_endpoint is not None: raise usb_exceptions.InvalidEndpointsError( 'Multiple in endpoints found') self._read_endpoint = address else: if self._write_endpoint is not None: raise usb_exceptions.InvalidEndpointsError( 'Multiple out endpoints found') self._write_endpoint = address if self._read_endpoint is None: raise usb_exceptions.InvalidEndpointsError('Missing in endpoint') if self._write_endpoint is None: raise usb_exceptions.InvalidEndpointsError('Missing out endpoint') handle = self._device.open() iface_number = self._setting.getNumber() try: if handle.kernelDriverActive(iface_number): handle.detachKernelDriver(iface_number) except libusb1.USBError as exception: if exception.value == libusb1.LIBUSB_ERROR_NOT_FOUND: _LOG.warning('Kernel driver not found for interface: %s.', iface_number) else: raise usb_exceptions.LibusbWrappingError( exception, '%s failed to detach kernel driver', self) # Try to claim the interface, if the device is gone, raise an IOError try: handle.claimInterface(iface_number) except libusb1.USBError as exception: raise usb_exceptions.LibusbWrappingError( exception, '%s failed to claim interface: %d', self, iface_number) self._handle = handle self._interface_number = iface_number
def iter_open(cls, name=None, interface_class=None, interface_subclass=None, interface_protocol=None, serial_number=None, port_path=None, default_timeout_ms=None): """Find and yield locally connected devices that match. Note that devices are opened (and interfaces claimd) as they are yielded. Any devices yielded must be Close()'d. Args: name: Name to give *all* returned handles, used for logging only. interface_class: USB interface_class to match. interface_subclass: USB interface_subclass to match. interface_protocol: USB interface_protocol to match. serial_number: USB serial_number to match. port_path: USB Port path to match, like X-X.X.X default_timeout_ms: Default timeout in milliseconds of reads/writes on the handles yielded. Yields: UsbHandle instances that match any non-None args given. Raises: LibusbWrappingError: When a libusb call errors during open. """ ctx = usb1.USBContext() try: devices = ctx.getDeviceList(skip_on_error=True) except libusb1.USBError as exception: raise usb_exceptions.LibusbWrappingError( exception, 'Open(name=%s, class=%s, subclass=%s, protocol=%s, ' 'serial=%s, port=%s) failed', name, interface_class, interface_subclass, interface_protocol, serial_number, port_path) for device in devices: try: if (serial_number is not None and device.getSerialNumber() != serial_number): continue if (port_path is not None and cls._device_to_sysfs_path(device) != port_path): continue for setting in device.iterSettings(): if (interface_class is not None and setting.getClass() != interface_class): continue if (interface_subclass is not None and setting.getSubClass() != interface_subclass): continue if (interface_protocol is not None and setting.getProtocol() != interface_protocol): continue yield cls(device, setting, name=name, default_timeout_ms=default_timeout_ms) except libusb1.USBError as exception: if (exception.value != libusb1.libusb_error. forward_dict['LIBUSB_ERROR_ACCESS']): raise