FTDI's libftd2xx.1.2.2 broken for macbook air running 10.7.4 (workaround)

Alec Jacobson

December 21, 2012

weblog/

I recently got my device working on my iMac at work using the libftd2xx.1.2.2 available from the drivers page of FTDI. Unfortunately the code I wrote that worked with that version of the library on my iMac did not work on my macbook air (despite running the same mac os x 10.7). My problem was that FT_Open was returning -1, which as far as I can tell is not a valid FT_STATUS enum value. After a (not so) brief stint trying to get the libftdi open source library to work (I gave up because it was slow and crashed on ftdi_usb_close and ftdi_usb_reset), I tried to see if any of the old releases of libftd2xx would work for me. I tried all I could find and report the following:
Name                    Source   Problem
libftd2xx.1.1.0.dylib,  macports,          random "bus error 10" after ~30secs (otherwise pretty good)
libftd2xx.0.1.7.dylib,  D2xx drivers page, "Error FT_ListDevices(18)" and reading garbage occasionally
libftd2xx.1.0.4.dylib,  D2xx hidden page,  reading occasional garbage
libftd2xx.1.1.0.dylib,  D2xx hidden page,  "bus error 10" after ~30secs (otherwise pretty good)
libftd2xx.1.1.12.dylib, D2xx Drivers page, FT_Open(-1)
libftd2xx.1.2.2.dylib,  D2xx Drivers page, FT_Open(-1)
As you can see, one of the sources is "D2xx hidden page". I found this accidentally. The version 1.1.0 seemed like the best bet. But like clockwork the device would send a Bus error: 10 and crash after 30 seconds. I flipped a bunch of switches and toggled a bunch of comments and I think I found the issue. I was reading in a tight loop using something like:
ftStatus = FT_Read(ftHandle, buffer, BUF_SIZE, &dwRxSize);
But what works is to do something like:
ftStatus = FT_GetStatus(ftHandle, &dwAmountInRxQueue, &dwAmountInTxQueue, &dwEventStatus);
if(dwAmountInRxQueue)                                      
{                                                          
  ftStatus = FT_Read(ftHandle, buffer, (dwAmountInRxQueue<BUF_SIZE?dwAmountInRxQueue:BUF_SIZE), &dwRxSize);
} 
I understand why the second is better, but I don't understand why the first should crash. In any case, my device has been running with no problems for going on 8 minutes. So I'm happy again.