libftdi Archives

Subject: (Resent with code) : Strange observations with USBDEVFS_REAPURBNDELAY

From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Date: Thu, 23 Jul 2009 22:11:20 +0200
Hello,

find appended a small test program. Compile like
gcc -g -o test main.c -lftdi -l usb
and run if you have a FT2232(H) connected. 

Even without anything connected to the low nibble of the low byte, the
programm should terminate and perhaps print 0xffffffff or 0. If the pins are
connected in the MPSSE-Jtag way, the IDs of the devices connected in the
JTAG chain should get printed bit reversed.

However on fast repeated runs, the programm soemtimes doesn't terminate. I
verified on two different machines with two differrent USB Chipsets
(Intel/AMD). If you change the #if 0 to #if 1, it always terminates.

Could people perhaps try to reproduce my observation or point me to
errors/flaws in my code. In short I observe in an strace of the program,
that the program stumbles after sequences like

14389 gettimeofday({1248377804, 892023}, NULL) = 0
14389 ioctl(3, USBDEVFS_SUBMITURB, 0xbf8ad934) = 0
14389 ioctl(3, USBDEVFS_REAPURBNDELAY, 0xbf8ad978) = -1 EAGAIN (Resource 
temporarily unavailable)
14389 select(4, NULL, [3], NULL, {0, 1000}) = 1 (out [3], left {0, 1000})
14389 gettimeofday({1248377804, 893493}, NULL) = 0

I also think that libftdi doesn't handle EAGAIN right. It should't return to
the user program, but handle EAGAIN internally.

Thanks
Hello,

find appended a small test program. Compile like
gcc -g -o test main.c -lftdi -l usb
and run if you have a FT2232(H) connected. 

Even without anything connected to the low nibble of the low byte, the
programm should terminate and perhaps print 0xffffffff or 0. If the pins are
connected in the MPSSE-Jtag way, the IDs of the devices connected in the
JTAG chain should get printed bit reversed.

However on fast repeated runs, the programm soemtimes doesn't terminate. I
verified on two different machines with two differrent USB Chipsets
(Intel/AMD). If you change the #if 0 to #if 1, it always terminates.

Could people perhaps try to reproduce my observation or point me to
errors/flaws in my code. In short I observe in an strace of the program,
that the program stumbles after sequences like

14389 gettimeofday({1248377804, 892023}, NULL) = 0
14389 ioctl(3, USBDEVFS_SUBMITURB, 0xbf8ad934) = 0
14389 ioctl(3, USBDEVFS_REAPURBNDELAY, 0xbf8ad978) = -1 EAGAIN (Resource 
temporarily unavailable)
14389 select(4, NULL, [3], NULL, {0, 1000}) = 1 (out [3], left {0, 1000})
14389 gettimeofday({1248377804, 893493}, NULL) = 0

I also think that libftdi doesn't handle EAGAIN right. It should't return to
the user program, but handle EAGAIN internally.

Thanks

-- 
Uwe Bonnes                bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
#include <ftdi.h>
#include <usb.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

#define VENDOR 0x0403
#define PRODUCT 0x6010

/* Sampe libftdi code to show the need for a dummy read

Compile like
gcc -g -o test main.c -lftdi -l usb
*/
int main(void)
{
  struct ftdi_context ftdi;
  unsigned long id;
  int i, j, read=0, to_read, last_read, retries = 0;
  unsigned char buf[256] = { SET_BITS_LOW, 0x08, 0x0b,
                                 TCK_DIVISOR,  0x01, 0x00 ,
                                 SET_BITS_HIGH, ~0x04, 0x04};
  ftdi_init(&ftdi);
  ftdi_set_interface(&ftdi, INTERFACE_A);
  if (ftdi_usb_open_desc(&ftdi, VENDOR, PRODUCT, 0, 0) < 0)
    {
      printf("Can't open device\n");
      return 1;
    }
  ftdi_set_latency_timer(&ftdi, 2);
  ftdi_set_bitmode(&ftdi, 0xfb, BITMODE_MPSSE);
  ftdi_usb_purge_buffers(&ftdi);
  ftdi_usb_purge_rx_buffer(&ftdi);
  if (ftdi_write_data(&ftdi,buf, 9) != 9)
    printf("Write failed\n");

#if 0
  while((last_read = ftdi_read_data(&ftdi, buf, 256))>0)
    printf("%d dummy bytes readn\n", last_read);
#endif

  /* Send 5 Clocks with TMS = 1 to reset the chain*/
  buf[0]= MPSSE_WRITE_TMS|MPSSE_LSB|MPSSE_BITMODE|MPSSE_WRITE_NEG;
  buf[1]= 5;
  buf[2]= 0x9f;
  if (ftdi_write_data(&ftdi,buf, 3) != 3)
    printf("Write1 failed\n");

  usleep(10000);
  /* Send 4 Clocks with TMS = 0 1 0 0 to reach SHIFTDR*/
  buf[0]= MPSSE_WRITE_TMS|MPSSE_LSB|MPSSE_BITMODE|MPSSE_WRITE_NEG;
  buf[1]= 4;
  buf[2]= 0x82;
  if (ftdi_write_data(&ftdi,buf, 3) != 3)
    printf("Write1 failed\n");

  /* In SHIFTDR, clock 32 times to get the ID (last device first)*/
  j = 0;
  do
    {
      buf[0] = MPSSE_DO_READ|MPSSE_DO_WRITE|MPSSE_LSB|MPSSE_WRITE_NEG;
      buf[1] = 3;
      buf[2] = 0;
      buf[3] = 0;
      buf[4] = 0;
      buf[5] = 0;
      buf[6] = 0;
      if (ftdi_write_data(&ftdi,buf, 7) != 7)
        printf("Write loop failed\n");

      to_read = 4;
      read = 0;
      while (read <to_read)
        {
          retries++;
          last_read = ftdi_read_data(&ftdi, buf+read, to_read -read);
          if (last_read > 0)
              read += last_read;
        }
      id = 
        (unsigned long) buf[3] <<24 |
        (unsigned long) buf[2] <<16 |
        (unsigned long) buf[1] << 8 |
        (unsigned long) buf[0];
      if (id)
        {
          printf("0x%08lx\n", id);
          j++;
        }
    } while( id !=0 && id!=0xffffffff && j<10);

  ftdi_usb_close(&ftdi);
  ftdi_deinit(&ftdi);
  return 0;
}

--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   

Current Thread
  • (Resent with code) : Strange observations with USBDEVFS_REAPURBNDELAY, Uwe Bonnes <=