The FTDI’s gift

The FTDI’s gift is very interesting.

Keeping the “See Figure 1.” motto in their minds, they have changed data types when switching over from library versions 0.4.x to The gift affects on 64-bit libraries only. There is no problem for 32-bit ones.

ftd2xx library was born in Windows and contains WinAPI-like UART support functions FT_W32_ххх(). That’s why WinAPI standard types DWORD, BYTE and so on are used in the library. For Linux version of the library they have added WinTypes.h header file with typedefs for these types. In general, it seems to be a logical step, but…

There is a part of WinTypes.h from libftd2xx v.0.4.16:

typedef unsigned long    DWORD;
typedef unsigned long    ULONG;
typedef long             LONG;

These definitions are just borrowed from windef.h header file of Windows-based C-compilers.

There is the same part of WinTypes.h from libftd2xx v.1.0.0:

typedef unsigned int    DWORD;
typedef unsigned int    ULONG;
typedef int             LONG;

In Windows, including 64-bit, there is no difference between these definitions in practice. Window-64 uses so-called LLP64 data model (only long long and pointer-types are 64-bit wide). In this case sizeof(long) == sizeof(int), both types are 32-bit wide. The same is true for 32-bit Linux. Old avreal version will work properly with new library for the listed OS.

But 64-bit Linux uses LP64 data model so type “long” is 64-bit too.

So, for 0.4.x and 64-біт Linux types DWORD, ULONG, LONG are 64-bit, twice as they are in 32-bit Linux. Since both library and program have been compiled with the same header file, the program still works.

For libftd2xx 1.0.0 the types are 32-bit in all 32- and 64-bit operating systems. Again, a program will work if compiled with the same header as the library was compiled with.

But avreal will not work if compiled with header from libray v0.4.x but library v1.0.0 is installed. Consider this function call:

    DWORD chip_type, chip_id, status;
    char serno[16];
    char description[64];

    status = FT_GetDeviceInfo(handle, &chip_type, &chip_id, serno, description, 0);

In old program variables chip_type, chip_id are 64-bit. New library will write 32-bit data into lower half of these variables. If I was more accurate (paranoic?) and initialise the variables with 0’s, the program would not even notice that the library consider the variables as 32-bit (thanks to x86 is little-endian processor). But the benefit of that would be small, because the library has the following type of data:

typedef struct _ft_device_list_info_node {
    ULONG Flags;
    ULONG Type;
    DWORD LocId;
    char SerialNumber[16];
    char Description[64];
    FT_HANDLE ftHandle;

The structure occupies 120 bytes for old library version and 104 bytes for new one. Device list building function FT_GetDeviceInfoList() receives pointer to array of that structures… It is clear that it will not work anyway.

Everything is getting worse if avreal is compiled with header from library v1.0.0 but library v0.4.16 is installed. The library will write more data than there is a place for. Adjacent variables will be spoiled or even “segmentation fault” will be reached.

That’s why I’m not going to rebuild avreal as yet. For 64-bit Linux take the libftd2xx 0.4.16 on download page.

I will think about what should I do with this FTDI’s gift.

3 Responses to “The FTDI’s gift”

  1. goblin says:

    и для чего существуют uint8_t .. uint64_t ?

  2. Dekar says:

    А использовать открытую libftdi?

    • ReAl says:

      Так про неё smartly уже сказал по соседству.
      Можно, и в том направлении я буду двигаться малой скоростью.
      Но и с libfd2xx особых проблем нет — когда стало ясно, в чём дело.
      В любом случае это будет не «перейти», а «поддерживать и», так как совсем отказываться от libftd2xx я не собираюсь.

Leave a Reply

[flagcounter image]