How to use the FTDI D2XX library on OSX?

6.1k views Asked by At

I'm trying to talk to a an usb device connected to an EasySync USB2-H-5004-M USB to RS485 converter at baud rate 3750000 but on OSX.

I've some c++ code working on Windows and have just managed to get it to compile on OSX (using the D2XX dylib instead of the dll) but I have an issue with communication somewhere and I'm not sure where to start and how to resolve this.

I'm using openFrameworks/c++ and the method to list devices looks like this:

int FTDI::enumerateDevices(){
    DWORD numDevs;
    FT_STATUS ftStatus = FT_CreateDeviceInfoList(&numDevs);
    numPortsFound = 0;

    if (ftStatus == FT_OK) {
        ofLog(OF_LOG_NOTICE, "Number of FTDI devices is %d",numDevs);
        devicesList = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*numDevs);
        ftStatus = FT_GetDeviceInfoList(devicesList, &numDevs);
        if (ftStatus == FT_OK) {
            printf("\n");
            for (int i = 0; i < numDevs; i++) {
                ofLog(OF_LOG_VERBOSE, "Dev %d:",i);
                ofLog(OF_LOG_VERBOSE, " Flags=0x%x",devicesList[i].Flags);
                ofLog(OF_LOG_VERBOSE, " Type=0x%x",devicesList[i].Type);
                ofLog(OF_LOG_VERBOSE, " ID=0x%x",devicesList[i].ID);
                ofLog(OF_LOG_VERBOSE, " LocId=0x%x",devicesList[i].LocId);
                ofLog(OF_LOG_VERBOSE, " SerialNumber=%s",devicesList[i].SerialNumber);
                ofLog(OF_LOG_VERBOSE, " Description=%s",devicesList[i].Description);
                ofLog(OF_LOG_VERBOSE, " ftHandle=0x%x\n",devicesList[i].ftHandle);
            }
            numPortsFound = numDevs;
        } else {
            ofLog(OF_LOG_ERROR, "FTD2XX::FT_GetDeviceInfoList() failed");
        }
    } else {
        ofLog(OF_LOG_ERROR, "FTD2XX::FT_CreateDeviceInfoList() failed");
    }

    return numPortsFound;

}

The problem is on OSX I get this output:

[notice ] Number of FTDI devices is 4

[verbose] Dev 0:
[verbose]  Flags=0x1
[verbose]  Type=0x3
[verbose]  ID=0x0
[verbose]  LocId=0x0
[verbose]  SerialNumber=
[verbose]  Description=
[verbose]  ftHandle=0x0

[verbose] Dev 1:
[verbose]  Flags=0x1
[verbose]  Type=0x3
[verbose]  ID=0x0
[verbose]  LocId=0x0
[verbose]  SerialNumber=
[verbose]  Description=
[verbose]  ftHandle=0x0

[verbose] Dev 2:
[verbose]  Flags=0x1
[verbose]  Type=0x3
[verbose]  ID=0x0
[verbose]  LocId=0x0
[verbose]  SerialNumber=
[verbose]  Description=
[verbose]  ftHandle=0x0

[verbose] Dev 3:
[verbose]  Flags=0x1
[verbose]  Type=0x3
[verbose]  ID=0x0
[verbose]  LocId=0x0
[verbose]  SerialNumber=
[verbose]  Description=
[verbose]  ftHandle=0x0

[ error ] failed to register FTDI device with serial FTWVZVEBA in internal register
[ error ] error opening port with serial: FTWVZVEBA

which doesn't look right. For example on Windows, on port A/channel 1/device index 0 I see this:

[verbose] Dev 0:
[verbose]  Flags=0x2
[verbose]  Type=0x7
[verbose]  ID=0x4036011
[verbose]  LocId=0x02111
[verbose]  SerialNumber=FTWVZVEBA
[verbose]  Description=USB2-H-5004-M A
[verbose]  ftHandle=0x0

Having a quick look in /dev things look ok:

ls /dev/tty.*
/dev/tty.Bluetooth-Incoming-Port    /dev/tty.usbserial-FTWVZVEBB
/dev/tty.Bluetooth-Modem        /dev/tty.usbserial-FTWVZVEBC
/dev/tty.usbmodemfa131          /dev/tty.usbserial-FTWVZVEBD

and through System Information I get:

USB2-H-5004-M:

  Product ID:   0x6011
  Vendor ID:    0x0403  (Future Technology Devices International Limited)
  Version:   8.00
  Serial Number:    FTWVZVEB
  Speed:    Up to 480 Mb/sec
  Manufacturer: FTDI
  Location ID:  0xfd120000 / 4
  Current Available (mA):   500
  Current Required (mA):    200

I have installed the D2XX driver as instructed on the FTDI OSX Installation Guide (pdf link) but I'm not sure what I'm missing/doing wrong.

How can I correctly communicate to the device using the FTDI D2XX library ?

2

There are 2 answers

1
Brad Larson On BEST ANSWER

To flesh out my comment, since it seems to have answered the core question here: Mac OS 10.9 (Mavericks) now ships with a kernel extension that acts like FTDI's VCP drivers did. It creates a virtual comm port for FTDI USB-to-serial devices it detects, and means that you no longer have to install the VCP driver if you needed it before.

This has an unfortunate side-effect, though, in that it breaks any application using FTDI's D2XX library. This exhibits itself as a failure for the D2XX functions to connect to the FTDI device, even though they can see it. As a work-around, you can manually unload the kext:

sudo kextunload -b com.apple.driver.AppleUSBFTDI

but it will reload itself on next boot.

As a more permanent solution, I've been having my applications detect if this kext is loaded (by trying to connect via the D2XX functions and seeing if they fail), and using the more traditional open(), etc. calls for connecting to the serial port as a fallback.

I'm not sure if the VCP-style kext they use allows for as much flexibility in terms of baud rates as the D2XX one does, though.

1
Tim MB On

As mentioned in Brad Larson's answer, you need to unload the Apple FTDI kext for the D2XX library to work, on later versions of MacOS. However, FTDI have a script that automatically does this for you, called D2XX Helper, linked to in the Comments box under the Mac OS X row on the D2XX drivers page.