0

I'm trying to work with an FTDI-based USB device and I'm getting a -32 (EPIPE) error:

08-06 16:32:16.328: WARN/System.err(15547): ftdi_usb_open_dev()
08-06 16:32:16.328: WARN/System.err(15547): usb_detach_kernel_driver_np()libusb: 0.029116 debug [libusb_detach_kernel_driver] interface 0
08-06 16:32:16.328: WARN/System.err(15547): ftdi claim interface ...
08-06 16:32:16.328: WARN/System.err(15547): libusb-compat debug: usb_claim_interface: interface 0
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.030246 debug [libusb_claim_interface] interface 0
08-06 16:32:16.328: WARN/System.err(15547): claiming interface using fd = 4
08-06 16:32:16.328: WARN/System.err(15547): ftdi_usb_reset ...
08-06 16:32:16.328: WARN/System.err(15547): libusb-compat debug: usb_control_msg: RQT=40 RQ=0 V=0 I=0 len=0 timeout=300
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.031222 debug [libusb_get_next_timeout] next timeout in 0.300000s
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.031527 debug [libusb_handle_events_timeout_completed] doing our own event handling
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.032046 debug [handle_events] poll() 2 fds with timeout in 300ms
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.033023 debug [handle_events] poll() returned 1
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.033389 debug [reap_for_handle] urb type=2 status=-32 transferred=0
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.033755 debug [handle_control_completion] handling completion status -32
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.034091 debug [handle_control_completion] unsupported control request
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.034366 debug [usbi_handle_transfer_completion] transfer 0x2915e0 has callback 0x5ccb4
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.034732 debug [ctrl_transfer_cb] actual_length=0

The USB request seems to be exactly as it is required according to FTDI Chip Commands.

FTDI context is initialized without errors, usb_dev is not null and it seems to be okay. The cable is okay as I can use it for uploading Arduino sketches to Duemilanove (FTDI) boards.

So I'm completely stuck.. What should I do?

My code

struct ftdi_context *ftdi_ctx;
struct usb_device *dev;
usb_dev_handle *udev;

// ...
ftdi_ctx = ftdi_new();
    if (ftdi_ctx == NULL) {
      fprintf(stderr, "error init ftdi context\n");
      return 1;
    }
    ftdi_ctx->usb_write_timeout = 0;
    ftdi_ctx->usb_read_timeout = 0;
// ...
udev = usb_open(dev);
int ret = ftdi_usb_open_dev(ftdi_ctx, dev, udev);
              if (ret < 0) {
                fprintf(stderr, "error opening ftdi device\n");
                return ret;
              }

ftdi_usb_open_dev() is slightly modified to get ready usb_device and don't do usb_open inside:

libftdi-0.1 code (ftdi.c):

int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev, struct usb_dev_handle *usb_dev)
{
    int detach_errno = 0;
    int config_val = 1;

    fprintf(stderr, "ftdi_usb_open_dev()\n");

    if (ftdi == NULL) {
        fprintf(stderr, "ftdi context invalid\n");
        ftdi_error_return(-8, "ftdi context invalid");
    }

    // 4ntoine (no need to open device if usb_dev is already passed)
    if (usb_dev == NULL) {
        if (!(ftdi->usb_dev = usb_open(dev)))
            ftdi_error_return(-4, "usb_open() failed");
    } else {
        ftdi->usb_dev = usb_dev;
    }

    #ifdef LIBUSB_HAS_GET_DRIVER_NP
        // Try to detach ftdi_sio kernel module.
        // Returns ENODATA if driver is not loaded.
        //
        // The return code is kept in a separate variable and only parsed
        // if usb_set_configuration() or usb_claim_interface() fails as the
        // detach operation might be denied and everything still works fine.
        // Likely scenario is a static ftdi_sio kernel module.
        fprintf(stderr, "detaching kernel driver... \n");
        if (ftdi->module_detach_mode == AUTO_DETACH_SIO_MODULE)
        {
            fprintf(stderr, "usb_detach_kernel_driver_np() ...\n");
            if (usb_detach_kernel_driver_np(ftdi->usb_dev, ftdi->interface) != 0 && errno != ENODATA) {
                fprintf(stderr, "failed to detach\n");
                detach_errno = errno;
            }
        }
    #endif

    fprintf(stderr, "ftdi claim interface ...\n");
    if (usb_claim_interface(ftdi->usb_dev, ftdi->interface) != 0)
    {
        fprintf(stderr, "failed to claim interface\n");
        ftdi_usb_close_internal (ftdi);
        if (detach_errno == EPERM)
        {
            ftdi_error_return(-8, "inappropriate permissions on device!");
        }
        else
        {
            ftdi_error_return(-5, "unable to claim usb device. Make sure the default FTDI driver is not in use");
        }
    }
    fprintf(stderr, "ftdi claimed interface\n");

    fprintf(stderr, "ftdi_usb_reset ...\n");
    if (ftdi_usb_reset (ftdi) != 0)
    {
        ftdi_usb_close_internal (ftdi);
        ftdi_error_return(-6, "ftdi_usb_reset failed");
    }

I've tested it with another FTDI-board (Arduino Nano v3) and still the same error, so the problem is not in the board most likely...

I've tested it on another Android device with USB host support too and another Android OS version (4.0.x) and still the same error...

Community
  • 1
  • 1
4ntoine
  • 19,816
  • 21
  • 96
  • 220

2 Answers2

2

Is your host system Windows or Linux?

It seems that the device failed to respond to the control message issued by ftdi_usb_reset(). And the ftdi_usb_reset() is actually called by ftdi_usb_open_dev().

If checking the libftdi source code: http://www.intra2net.com/en/developer/libftdi/documentation/ftdi_8c_source.html#l00522

We found that it shall return -6 if ftdi_usb_reset() fails. The entire error log is not posted here, so I wonder if it is what truly happened finally. And maybe there are more interesting things to go see there.

Maybe showing your code here can help get a better understanding. :)

If possible on your side, when trying to do the same thing with D2XX driver provided by ftdichip.com, will the result be the same?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shan Song
  • 41
  • 2
  • the system is actually Android (linux). I've updated the question with code. PS. i'm using libusb-0.x and libftdi-0.x – 4ntoine Aug 07 '13 at 11:43
1

Correct me if my understanding is wrong: You are developing native code that works on Android (the underlying Linux system) that calls libftdi and libusb, right? And I assume the purpose is to use Android devices through libusb without root needed?

A little search on Google tells me that there is no "official" Android port for libusb. Some platform works with libusb while some cannot. People are having different kinds of feedbacks.

So if going back to basics, say, using only the functions in libusb, without the libftdi code you've modified, can you perform device open, close, and send control message to your FTDI device through basic libusb functions?

Or, if possible, try with an unmodified libftdi. Will it to the job it is supposed to do?

And by the way, why libftdi0.1? I knew it should be version 1.0 by now. Older versions could be buggy...

I just try to provide something that is worth trying. It could be a libusb problem, a libftdi problem, or simply a problem of the sequence how you operate the device. So if not sure where it goes wrong, then break them down to pieces and identify what are correct would be what I would try.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shan Song
  • 41
  • 2
  • I'm modifying avrdude to make it working on android. For this i modified libusb and it works just perfect for cdc-devices without rooting. I'm able to open device, read, write and close, so that's why i believe getting usb_dev is okay since exactly the same code is used for passing to libftdi. – 4ntoine Aug 08 '13 at 04:31
  • The point is that the only change to libftdi is that i pass ready usb_dev pointer instead of opening it in `ftdi_usb_open_dev`. I thought it will work out-of-box but i was wrong, so now i'm trying to understand what's wrong. I'm using libusb-0.x and libftdi-0.x as avrdude uses libusb-0.x and i'd like to leave avrdude code as-is. Probably i should try to rewrite it to use libusb-1 and libftdi-1.. – 4ntoine Aug 08 '13 at 04:32
  • i've found interesting comment in libftdi code: // Try to detach ftdi_sio kernel module. // // The return code is kept in a separate variable and only parsed // if usb_set_configuration() or usb_claim_interface() fails as the // detach operation might be denied and everything still works fine. // Likely scenario is a static ftdi_sio kernel module. then i tried to set configuration 1, but it fails. it makes me think that kernel driver is not detached actually, but the result is okay. – 4ntoine Aug 08 '13 at 05:36