This patch enables dynamic loading of ftd2xx.dll in ft2232.c on Win32
platform.
It's made to work only on Win32 and for ftd2xx.dll in ft2232.c - it
doesn't affect linux, libftdi or any other modules that could use that.
That's the first from a series that I am planing (win32 only):
1. (this one) enable dynamic loading of ftd2xx.dll in ft2232.c
2. enable dynamic loading of libusb0.dll in ft2232.c
3. make it possible to have support for both libftdi and ftd2xx at the
same time in ft2232.c
n. enable dynamic loading for some other modules - jlink, rlink, presto
n+1. make it possible to have support for both libftdi and ftd2xx at the
same time in presto.c
I can do the same for linux, but as I have no means for testing I'd
rather pass that to someone else. With help in testing I can try to do
that myself.
What would be the opinion of maintainers? Should I continue?
Anyone with FT2232 based dongle and Windows - please test. When
compiling enable ft2232 with ftd2xx.dll only, as there are other
interfaces that use dynamic libraries not yet "converted" to dynamic
loading. I can also provide you with a compiled executable, as current
trunk doesn't build on Windows - in such case contact me and I'll post
such executable somewhere.
The main difference is that patched copy would run WITHOUT ftd2xx.dll,
so you may test in the following way:
1. locate all ftd2xx.dll occurencies that can be reached through system
PATH (usually in /bin/ with openocd, Windows/system32, but sometimes may
be more) and rename them to anything else - for example ftd2xx.dl_
2. trying to run some earlier version would result in failure, as
windows would not be able to load library. even "openocd -v" will fail
3. Modified version shoud run and in case of using ft2232 based config
files should report an Error (on command line!) that the library cannot
be loaded. "openocd -v" shoud work without problems.
4. Rename at least one ftd2xx.dll to original name and try again -
modified version should work as expected.
4\/3!!
Index: src/jtag/ft2232.c
===================================================================
--- src/jtag/ft2232.c (revision 2405)
+++ src/jtag/ft2232.c (working copy)
@@ -63,6 +63,38 @@
#include <ftdi.h>
#endif
+/* Dynamic loading of libraries at runtime - only for Win32 and ftd2xx.dll
currently */
+
+#if defined(_WIN32) && BUILD_FT2232_FTD2XX == 1
+#define FTD2XX_DYNAMIC 1
+#else
+#define FTD2XX_DYNAMIC 0
+#endif
+
+#if FTD2XX_DYNAMIC == 1
+
+// typedefs for all used functions from ftd2xx.dll library
+typedef FT_STATUS (WINAPI *FT_Write_t)(FT_HANDLE ftHandle, LPVOID lpBuffer,
DWORD dwBytesToWrite, LPDWORD lpBytesWritten);
+typedef FT_STATUS (WINAPI *FT_Read_t)(FT_HANDLE ftHandle, LPVOID lpBuffer,
DWORD dwBytesToRead, LPDWORD lpBytesReturned);
+typedef FT_STATUS (WINAPI *FT_OpenEx_t)(PVOID pArg1, DWORD Flags, FT_HANDLE
*pHandle);
+typedef FT_STATUS (WINAPI *FT_ListDevices_t)(PVOID pArg1, PVOID pArg2, DWORD
Flags);
+typedef FT_STATUS (WINAPI *FT_SetLatencyTimer_t)(FT_HANDLE ftHandle, UCHAR
ucLatency);
+typedef FT_STATUS (WINAPI *FT_GetLatencyTimer_t)(FT_HANDLE ftHandle, PUCHAR
pucLatency);
+typedef FT_STATUS (WINAPI *FT_SetTimeouts_t)(FT_HANDLE ftHandle, ULONG
ReadTimeout, ULONG WriteTimeout);
+typedef FT_STATUS (WINAPI *FT_SetBitMode_t)(FT_HANDLE ftHandle, UCHAR ucMask,
UCHAR ucEnable);
+typedef FT_STATUS (WINAPI *FT_GetDeviceInfo_t)(FT_HANDLE ftHandle, FT_DEVICE
*lpftDevice, LPDWORD lpdwID, PCHAR SerialNumber, PCHAR Description, LPVOID
Dummy);
+typedef FT_STATUS (WINAPI *FT_Purge_t)(FT_HANDLE ftHandle, ULONG Mask);
+typedef FT_STATUS (WINAPI *FT_Close_t)(FT_HANDLE ftHandle);
+
+// library handle
+static HINSTANCE dynamic_library;
+
+// global pointers for read and write functions
+static FT_Write_t FT_Write_ptr;
+static FT_Read_t FT_Read_ptr;
+
+#endif
+
/* max TCK for the high speed devices 30000 kHz */
#define FTDI_2232H_4232H_MAX_TCK 30000
@@ -343,7 +375,12 @@
#if BUILD_FT2232_FTD2XX == 1
FT_STATUS status;
DWORD dw_bytes_written;
+
+#if FTD2XX_DYNAMIC == 1
+ if ((status = (*FT_Write_ptr)(ftdih, buf, size, &dw_bytes_written)) !=
FT_OK)
+#else
if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
+#endif
{
*bytes_written = dw_bytes_written;
LOG_ERROR("FT_Write returned: %lu", status);
@@ -381,8 +418,13 @@
while ((*bytes_read < size) && timeout--)
{
+#if FTD2XX_DYNAMIC == 1
+ if ((status = (*FT_Read_ptr)(ftdih, buf + *bytes_read, size -
+ *bytes_read, &dw_bytes_read))
!= FT_OK)
+#else
if ((status = FT_Read(ftdih, buf + *bytes_read, size -
*bytes_read, &dw_bytes_read)) !=
FT_OK)
+#endif
{
*bytes_read = 0;
LOG_ERROR("FT_Read returned: %lu", status);
@@ -1803,6 +1845,78 @@
LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout
(%4.4x:%4.4x)", ft2232_layout, vid, pid);
+#if FTD2XX_DYNAMIC == 1
+
+ FT_OpenEx_t FT_OpenEx_ptr;
+ FT_ListDevices_t FT_ListDevices_ptr;
+ FT_SetLatencyTimer_t FT_SetLatencyTimer_ptr;
+ FT_GetLatencyTimer_t FT_GetLatencyTimer_ptr;
+ FT_SetTimeouts_t FT_SetTimeouts_ptr;
+ FT_SetBitMode_t FT_SetBitMode_ptr;
+ FT_GetDeviceInfo_t FT_GetDeviceInfo_ptr;
+
+ dynamic_library = LoadLibrary("ftd2xx.dll");
+
+ if(dynamic_library == NULL)
+ {
+ LOG_ERROR("Can't open ftd2xx.dll");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ else
+ {
+ BOOL fail = FALSE;
+
+ if((FT_Write_ptr = (FT_Write_t)GetProcAddress(dynamic_library,
"FT_Write")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_Write() function");
+ fail = TRUE;
+ }
+ if((FT_Read_ptr = (FT_Read_t)GetProcAddress(dynamic_library,
"FT_Read")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_Read() function");
+ fail = TRUE;
+ }
+ if((FT_OpenEx_ptr =
(FT_OpenEx_t)GetProcAddress(dynamic_library, "FT_OpenEx")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_OpenEx() function");
+ fail = TRUE;
+ }
+ if((FT_ListDevices_ptr =
(FT_ListDevices_t)GetProcAddress(dynamic_library, "FT_ListDevices")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_ListDevices() function");
+ fail = TRUE;
+ }
+ if((FT_SetLatencyTimer_ptr =
(FT_SetLatencyTimer_t)GetProcAddress(dynamic_library, "FT_SetLatencyTimer")) ==
NULL)
+ {
+ LOG_ERROR("Can't get FT_SetLatencyTimer() function");
+ fail = TRUE;
+ }
+ if((FT_GetLatencyTimer_ptr =
(FT_GetLatencyTimer_t)GetProcAddress(dynamic_library, "FT_GetLatencyTimer")) ==
NULL)
+ {
+ LOG_ERROR("Can't get FT_GetLatencyTimer() function");
+ fail = TRUE;
+ }
+ if((FT_SetTimeouts_ptr =
(FT_SetTimeouts_t)GetProcAddress(dynamic_library, "FT_SetTimeouts")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_SetTimeouts() function");
+ fail = TRUE;
+ }
+ if((FT_SetBitMode_ptr =
(FT_SetBitMode_t)GetProcAddress(dynamic_library, "FT_SetBitMode")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_SetBitMode() function");
+ fail = TRUE;
+ }
+ if((FT_GetDeviceInfo_ptr =
(FT_GetDeviceInfo_t)GetProcAddress(dynamic_library, "FT_GetDeviceInfo")) ==
NULL)
+ {
+ LOG_ERROR("Can't get FT_GetDeviceInfo() function");
+ fail = TRUE;
+ }
+
+ if(fail != FALSE)
+ return ERROR_JTAG_INIT_FAILED;
+ }
+#endif
+
#if IS_WIN32 == 0
/* Add non-standard Vid/Pid to the linux driver */
if ((status = FT_SetVIDPID(vid, pid)) != FT_OK)
@@ -1835,7 +1949,11 @@
return ERROR_JTAG_INIT_FAILED;
}
+#if FTD2XX_DYNAMIC == 1
+ status = (*FT_OpenEx_ptr)(openex_string, openex_flags, &ftdih);
+#else
status = FT_OpenEx(openex_string, openex_flags, &ftdih);
+#endif
if (status != FT_OK) {
// under Win32, the FTD2XX driver appends an "A" to the end
// of the description, if we tried by the desc, then
@@ -1843,7 +1961,11 @@
if (openex_string == ft2232_device_desc) {
// Try the alternate method.
openex_string = ft2232_device_desc_A;
+#if FTD2XX_DYNAMIC == 1
+ status = (*FT_OpenEx_ptr)(openex_string, openex_flags,
&ftdih);
+#else
status = FT_OpenEx(openex_string, openex_flags, &ftdih);
+#endif
if (status == FT_OK) {
// yea, the "alternate" method worked!
} else {
@@ -1867,7 +1989,11 @@
return ERROR_JTAG_INIT_FAILED;
}
LOG_ERROR("unable to open ftdi device: %lu", status);
+#if FTD2XX_DYNAMIC == 1
+ status = (*FT_ListDevices_ptr)(&num_devices, NULL,
FT_LIST_NUMBER_ONLY);
+#else
status = FT_ListDevices(&num_devices, NULL,
FT_LIST_NUMBER_ONLY);
+#endif
if (status == FT_OK)
{
char** desc_array = malloc(sizeof(char*) * (num_devices
+ 1));
@@ -1878,7 +2004,11 @@
desc_array[num_devices] = NULL;
+#if FTD2XX_DYNAMIC == 1
+ status = (*FT_ListDevices_ptr)(desc_array,
&num_devices, FT_LIST_ALL | openex_flags);
+#else
status = FT_ListDevices(desc_array, &num_devices,
FT_LIST_ALL | openex_flags);
+#endif
if (status == FT_OK)
{
@@ -1899,13 +2029,21 @@
return ERROR_JTAG_INIT_FAILED;
}
+#if FTD2XX_DYNAMIC == 1
+ if ((status = (*FT_SetLatencyTimer_ptr)(ftdih, ft2232_latency)) !=
FT_OK)
+#else
if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK)
+#endif
{
LOG_ERROR("unable to set latency timer: %lu", status);
return ERROR_JTAG_INIT_FAILED;
}
+#if FTD2XX_DYNAMIC == 1
+ if ((status = (*FT_GetLatencyTimer_ptr)(ftdih, &latency_timer)) !=
FT_OK)
+#else
if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK)
+#endif
{
LOG_ERROR("unable to get latency timer: %lu", status);
return ERROR_JTAG_INIT_FAILED;
@@ -1915,19 +2053,31 @@
LOG_DEBUG("current latency timer: %i", latency_timer);
}
+#if FTD2XX_DYNAMIC == 1
+ if ((status = (*FT_SetTimeouts_ptr)(ftdih, 5000, 5000)) != FT_OK)
+#else
if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK)
+#endif
{
LOG_ERROR("unable to set timeouts: %lu", status);
return ERROR_JTAG_INIT_FAILED;
}
+#if FTD2XX_DYNAMIC == 1
+ if ((status = (*FT_SetBitMode_ptr)(ftdih, 0x0b, 2)) != FT_OK)
+#else
if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK)
+#endif
{
LOG_ERROR("unable to enable bit i/o mode: %lu", status);
return ERROR_JTAG_INIT_FAILED;
}
+#if FTD2XX_DYNAMIC == 1
+ if ((status = (*FT_GetDeviceInfo_ptr)(ftdih, &ftdi_device, &deviceID,
SerialNumber, Description, NULL)) != FT_OK)
+#else
if ((status = FT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID,
SerialNumber, Description, NULL)) != FT_OK)
+#endif
{
LOG_ERROR("unable to get FT_GetDeviceInfo: %lu", status);
return ERROR_JTAG_INIT_FAILED;
@@ -1956,7 +2106,19 @@
{
FT_STATUS status;
+#if FTD2XX_DYNAMIC == 1
+ FT_Purge_t FT_Purge_ptr;
+
+ if((FT_Purge_ptr = (FT_Purge_t)GetProcAddress(dynamic_library,
"FT_Purge")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_Purge() function");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if ((status = (*FT_Purge_ptr)(ftdih, FT_PURGE_RX | FT_PURGE_TX)) !=
FT_OK)
+#else
if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
+#endif
{
LOG_ERROR("error purging ftd2xx device: %lu", status);
return ERROR_JTAG_INIT_FAILED;
@@ -2760,7 +2922,27 @@
#if BUILD_FT2232_FTD2XX == 1
FT_STATUS status;
+#if FTD2XX_DYNAMIC == 1
+ FT_Close_t FT_Close_ptr;
+ int retval=ERROR_OK;
+
+ if((FT_Close_ptr = (FT_Close_t)GetProcAddress(dynamic_library,
"FT_Close")) == NULL)
+ {
+ LOG_ERROR("Can't get FT_Close() function");
+ retval = ERROR_FAIL;
+ }
+ else
+ status = (*FT_Close_ptr)(ftdih);
+
+ if(FreeLibrary(dynamic_library) == FALSE)
+ {
+ LOG_ERROR("Can't close library");
+ retval = ERROR_FAIL;
+ }
+#else
status = FT_Close(ftdih);
+#endif
+
#elif BUILD_FT2232_LIBFTDI == 1
ftdi_usb_close(&ftdic);
@@ -2770,7 +2952,11 @@
free(ft2232_buffer);
ft2232_buffer = NULL;
+#if FTD2XX_DYNAMIC == 1
+ return retval;
+#else
return ERROR_OK;
+#endif
}
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development