FTDI library platform differences between Mac and Windows when using JNA

330 views Asked by At

I am currently working on a Java application that uses JNA to access some FTDI libraries, both D2XX and LibFT4222. I have used JNAerator to create the JNA used. This is all working correctly on Windows platforms. However when trying to run the software on Mac I come into a problem with LibFT4222.

FT_OpenEx In D2XX appears to work correctly, resulting in no error code, I can also check its returned description to see it listed as “FT4222 A”. I am also able to perform other functions without returning an unexpected error code (such as closing it twice, the first time resulting in no error code, the second resulting in one as expected). However when trying any operation using LibFT4222 on the Handle created by D2XX such as FT4222_I2CMaster_Init, FT4222_GetVersion or FT4222_GetClock it produces error code 1000 FT4222_DEVICE_NOT_SUPPORTED.

I have tried playing around with the generated JNA code such as changing the FT HANDLE type from PointerByReference to IntByReference, and can get it working on Windows correctly as before but still nothing seems to get it working on Mac.

The same logic works correctly using modified versions of the Sample C files that FTDI provides (using the same LibFT4222.dylib), so I know it will work correctly on the Mac. And as mentioned, all of the above works with no issues on Windows.

Would anyone be able to provide any insight on the differences between Mac OSX and Windows that might cause this behaviour?

Edited to include code, Example Java code (In this case the description will be "FT4222 A", and OpenEx appears to work correctly) This works on Windows but on Mac FT4222_I2CMaster_Init returns 1000:

Memory memory = new Memory(16);
memory.setString(0, "FT4222 A");
PointerByReference handle = new PointerByReference();
Ftd2xxLibrary.FT_OpenEx(new PVOID(memory), 
Ftd2xxLibrary.FT_OPEN_BY_DESCRIPTION, handle);
FT4222Library.FT_HANDLE ftHandle = new FT4222Library.FT_HANDLE(handle.getValue());
logger.warn("init" + FT4222Library.FT4222_I2CMaster_Init(ftHandle, (int) 100));

Where FT_OpenEx is (automatically generated by JNAerator) : /**

 * Original signature : <code>FT_STATUS FT_OpenEx(PVOID, DWORD, FT_HANDLE*)</code><br>
 * <i>native declaration : line 336</i>
 */
public static native NativeLong FT_OpenEx(Ftd2xxLibrary.PVOID pArg1, int Flags, PointerByReference pHandle);

Where FT4222_I2CMaster_Initis (automatically generated by JNAerator) :

    /**
 * FT4222 I2C Functions<br>
     * Original signature : <code>FT4222_STATUS FT4222_I2CMaster_Init(FT_HANDLE, uint32)</code><br>
     * <i>native declaration : line 338</i>
     */
    public static native int FT4222_I2CMaster_Init(FT4222Library.FT_HANDLE ftHandle, int kbps);

Where FT_HANDLE is (automatically generated by JNAerator) :

public static class FT_HANDLE extends PointerType {
        public FT_HANDLE(Pointer address) {
            super(address);
        }
        public FT_HANDLE() {
            super();
        }
    };

C Code working correctly on Mac (returning 0):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ftd2xx.h"
#include "libft4222.h"

static void init()
{
    FT_HANDLE            ftHandle = (FT_HANDLE)NULL;
    FT_OpenEx("FT4222 A", FT_OPEN_BY_DESCRIPTION, &ftHandle);
    printf("Init %d",FT4222_I2CMaster_Init(ftHandle,100));
}
1

There are 1 answers

3
Daniel Widdis On

Different results on different platforms are often a case of type mapping, but there's not an obvious difference here. I will point out a few inconsistencies that I see in the code, in the hopes that you can further troubleshoot using this information.

The library return type of FT_OpenEx() is FT_STATUS, and the return type of FT4222_I2CMaster_Init() is FT4222_STATUS, which is further documented as an extension of FT_STATUS... and in fact they use the same enum integer value basis but it's not clear how they are further defined. Logically one would expect the same data types for both, however in your mapping the FT_STATUS is mapped to NativeLong and the FT4222_STATUS is mapped to int.

In the header file, FT_STATUS is typedef'd to ULONG based on the Windows API. This is 4 bytes on Windows, but might be 8 bytes on macOS, suggesting the NativeLong mapping is probably correct. But ULONG is not a standard type on macOS so I'm not sure what it should be... perhaps instrumenting the C code to get the size of that type would be useful. Also, given the native (Direct Mapping) declaration, I suspect the primitive int return type may be problematic.

Possibly related, the FT4222_STATUS codes are simply enum type in C, so the width is not guaranteed by standard. It wouldn't surprise me if the return type for FT4222_STATUS was short on macOS.

I'm not sure why the return type would make a difference (short of stack corruption) but it's one thing to start looking at.