Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions pyftdi/ftdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from typing import Callable, Optional, List, Sequence, TextIO, Tuple, Union
from usb.core import (Configuration as UsbConfiguration, Device as UsbDevice,
USBError)
from usb.util import (build_request_type, release_interface, CTRL_IN, CTRL_OUT,
CTRL_TYPE_VENDOR, CTRL_RECIPIENT_DEVICE)
from usb.util import (build_request_type, claim_interface, release_interface,
CTRL_IN, CTRL_OUT, CTRL_TYPE_VENDOR, CTRL_RECIPIENT_DEVICE)
from .misc import to_bool
from .usbtools import UsbDeviceDescriptor, UsbTools

Expand Down Expand Up @@ -522,7 +522,8 @@ def open(self, vendor: int, product: int, bus: Optional[int] = None,
self.open_from_device(device, interface)

def open_from_device(self, device: UsbDevice,
interface: int = 1) -> None:
interface: int = 1,
reset_bitmode: bool = True) -> None:
"""Open a new interface from an existing USB device.

:param device: FTDI USB device (PyUSB instance)
Expand All @@ -531,12 +532,10 @@ def open_from_device(self, device: UsbDevice,
if not isinstance(device, UsbDevice):
raise FtdiError(f"Device '{device}' is not a PyUSB device")
self._usb_dev = device
try:
self._usb_dev.set_configuration()
except USBError:
pass
cfg0 = device[0].bConfigurationValue
# detect invalid interface as early as possible
config = self._usb_dev.get_active_configuration()
cfg = config.bConfigurationValue
if interface > config.bNumInterfaces:
raise FtdiError(f'No such FTDI port: {interface}')
self._set_interface(config, interface)
Expand All @@ -546,10 +545,18 @@ def open_from_device(self, device: UsbDevice,
self._readbuffer = bytearray()
# Drain input buffer
self.purge_buffers()
# Claim the interface
if device.bNumConfigurations > 0 and cfg0 != cfg:
try:
device.set_configuration()
except USBError:
pass
claim_interface(device, self._index - 1)
# Shallow reset
self._reset_device()
# Reset feature mode
self.set_bitmode(0, Ftdi.BitMode.RESET)
if reset_bitmode:
self.set_bitmode(0, Ftdi.BitMode.RESET)
# Init latency
self._latency_threshold = None
self.set_latency_timer(self.LATENCY_MIN)
Expand Down Expand Up @@ -579,7 +586,8 @@ def close(self, freeze: bool = False) -> None:
except FtdiError as exc:
self.log.warning('FTDI device may be gone: %s', exc)
try:
self._usb_dev.attach_kernel_driver(self._index - 1)
if not freeze:
self._usb_dev.attach_kernel_driver(self._index - 1)
except (NotImplementedError, USBError):
pass
self._usb_dev = None
Expand Down Expand Up @@ -838,7 +846,7 @@ def open_bitbang_from_device(self, device: UsbDevice,
:param sync: whether to use synchronous or asynchronous bitbang
:return: actual bitbang baudrate in bps
"""
self.open_from_device(device, interface)
self.open_from_device(device, interface, reset_bitmode=False)
# Set latency timer
self.set_latency_timer(latency)
# Set chunk size
Expand Down
Loading