pyftdi icon indicating copy to clipboard operation
pyftdi copied to clipboard

GPIO resets IO after setting when Mpsse.close(freeze=True) on MacOS Sonomo

Open sport-climber opened this issue 9 months ago • 2 comments

This issue was observed on Mac OS Sonoma (Intel 2019) with pyftdi v0.55.4. When a GPIO is set to a low output level the FTDI correctly set the GPIO to low, I've confirmed with DMM the state is correct. When the device is closed with the parameter freeze=True the GPIO is reset on the device. In generally this is the experience but every once in a while it does remain in the low output level as intended.

This problem is not seen when testing on a Linux Ubuntu host with pyftdi v0.55.4 of the same version.

The FTDI chip is FTDI232HQ Part on AdaFruit board.

I set a break point just before the: pyftdi.gpio.GpioMpsseController.close(freeze=True)

This is the state of the GpioMpsseController prior to closing:

Image

Why is the close sometimes successful but more often then not it fails?

sport-climber avatar Mar 13 '25 16:03 sport-climber

I cloned the repo and traced the failing call down to when the attach_kernel_driver(self._index-1) is called from ftdi.py:

def close(self, freeze: bool = False) -> None:
        """Close the FTDI interface/port.

           :param freeze: if set, FTDI port is not reset to its default
                          state on close. This means the port is left with
                          its current configuration and output signals.
                          This feature should not be used except for very
                          specific needs.
        """
        if self._usb_dev:
            dev = self._usb_dev
            if self._is_pyusb_handle_active():
                # Do not attempt to execute the following calls if the
                # device has been closed: the ResourceManager may attempt
                # to re-open the device that has been already closed, and
                # this may lead to a (native) crash in libusb.
                try:
                    if not freeze:
                        self.set_bitmode(0, Ftdi.BitMode.RESET)
                        self.set_latency_timer(self.LATENCY_MAX)
                    release_interface(dev, self._index - 1)
                except FtdiError as exc:
                    self.log.warning('FTDI device may be gone: %s', exc)
                try:
                    self._usb_dev.attach_kernel_driver(self._index - 1)
                except (NotImplementedError, USBError):
                    pass
            self._usb_dev = None
            UsbTools.release_device(dev)

sport-climber avatar Mar 13 '25 16:03 sport-climber

I would not be surprised that once the device is returned to the kernel, it re-initializes it as it supports FTDI device as USB-Serial adapters (the macOS equivalent of ftdi_sio.ko on Linux)...

It used to be possible to use kextunload on mac to disable a kernel extension, I'm not sure it is still feasible. Maybe com.apple.driver.usb.serial with kextunload ?

eblot avatar Mar 13 '25 17:03 eblot