2

I am using a custom board with an FTDI chip (FT4232) to get four serials communication over USB on a Linux system (Fedora 24). When the board is plugged, it is working great, the communication ports appear, and I am able to communicate.

However, I also need to read some data in EEPROM, and as soon as I use libftdi1 to communicate or anything, the communication port that I connected to disappear. This is the output of lsusb -t:

|__ Port 2: Dev 46, If 2, Class=Vendor Specific Class, Driver=ftdi_sio, 480M
|__ Port 2: Dev 46, If 0, Class=Vendor Specific Class, Driver=, 480M
|__ Port 2: Dev 46, If 3, Class=Vendor Specific Class, Driver=ftdi_sio, 480M
|__ Port 2: Dev 46, If 1, Class=Vendor Specific Class, Driver=ftdi_sio, 480M

So we see the driver has been detached. I tried to reattach the kernel driver as proposed in this question, but without any success. Here is a minimal example of code to execute to reproduce the behavior:

#include <stdio.h>
#include <libftdi1/ftdi.h>
#include <libusb-1.0/libusb.h>

int main(int argc, char * argv[])
{
    struct ftdi_context ftdic;
    libusb_device_handle * dev;

    ftdi_init(&ftdic);

    ftdi_usb_open(&ftdic, 0x0403, 0x6011);

    dev = ftdic.usb_dev;

    // Return error -6: LIBUSB_ERROR_BUSY
    printf("%d\n", libusb_attach_kernel_driver(dev, 0));

    ftdi_usb_close(&ftdic);

    // Return error -99: LIBUSB_ERROR_OTHER
    printf("%d\n", libusb_attach_kernel_driver(dev, 0));

    return 0;
}

In short: How can I do to reattach the kernel driver after using libftdi1? I would prefer a c solution, but a bash one would also be nice.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Puck
  • 2,080
  • 4
  • 19
  • 30

1 Answers1

1

after using libftdi is possible to retach the original driver using libusb and the libusb_attach_kernel_driver function.


#define DEVICE_VID 0x0403
#define DEVICE_PID 0x6015

int libftdireset() {
  libusb_context * context = NULL;
  libusb_device_handle * dev_handle = NULL;
  int rc = 0;
  rc = libusb_init( &context);

  dev_handle = libusb_open_device_with_vid_pid(context, DEVICE_VID, DEVICE_PID);
  /*Check if kenel driver attached*/
  if (libusb_kernel_driver_active(dev_handle, 0)) {
    rc = libusb_detach_kernel_driver(dev_handle, 0); // detach driver
  }
  libusb_reset_device(dev_handle);
  libusb_attach_kernel_driver(dev_handle, 0);
  libusb_close(dev_handle);
  libusb_exit(context);
  return 0;
}
  • As I don't have access to hardware to test since I asked this question 3 years ago but it looks like it would work... Thanks – Puck Jul 02 '21 at 13:54