Please take another look.

I have adressed:
- file header documentation
- separate documentation (NEWS, driver commands, examples, etc)
- "static"
~/src/openocd/src$ !nm
nm -g --defined-only jtag/drivers/usb_blaster.o
00000000 D _usb_blaster_interface
- formatting (line length, headers)

Also moved some of the usb_blaster_write/read stuff around a bit to
make it look more like parport and easier to write things like
usb_blaster_blink.

I'm not sure what to do about usb_blaster_speed. Even if I were to use
sleeps, after passing through the USB stacks, FIFOs, etc, the timing
would be grossly inaccurate. It might still be worth implementing it
that way so people can run their interfaces very slowly (kHz range)
for deep-sleep debugging.

On Sun, Dec 20, 2009 at 3:13 PM, David Brownell <[email protected]> wrote:
> On Sunday 20 December 2009, Øyvind Harboe wrote:
>> > Agreed.  It even fixes a bug:  broken USB-Blaster support!  :)
>>
>> Uh? Did we have any USB byte blaster support before this patch?
>
> No, and that's the bug.  ;)
>
>
diff --git a/NEWS b/NEWS
index e122912..d45e01a 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ and other issues not mentioned here.
 
 JTAG Layer:
        Support KT-Link JTAG adapter.
+       Support USB-JTAG, Altera USB-Blaster and compatibles.
 
 Boundary Scan:
 Target Layer:
diff --git a/configure.in b/configure.in
index 12270eb..2b13a79 100644
--- a/configure.in
+++ b/configure.in
@@ -392,6 +392,14 @@ AC_ARG_ENABLE(ft2232_ftd2xx,
   AS_HELP_STRING([--enable-ft2232_ftd2xx], [Enable building support for FT2232 
based devices using the FTD2XX driver from ftdichip.com]),
   [build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no])
 
+AC_ARG_ENABLE(usb_blaster_libftdi,
+  AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for 
the Altera USB-Blaster using the libftdi driver, opensource alternate of 
FTD2XX]), 
+  [build_usb_blaster_libftdi=$enableval], [build_usb_blaster_libftdi=no])
+
+AC_ARG_ENABLE(usb_blaster_ftd2xx,
+  AS_HELP_STRING([--enable-usb_blaster_ftd2xx], [Enable building support for 
the Altera USB-Blaster using the FTD2XX driver from ftdichip.com]), 
+  [build_usb_blaster_ftd2xx=$enableval], [build_usb_blaster_ftd2xx=no])
+
 AC_ARG_ENABLE(amtjtagaccel,
   AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec 
JTAG-Accelerator driver]),
   [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
@@ -651,6 +659,20 @@ else
   AC_DEFINE(BUILD_FT2232_FTD2XX, 0, [0 if you don't want ftd2xx ft2232.])
 fi
 
+if test $build_usb_blaster_libftdi = yes; then
+  build_bitbang=yes
+  AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 1, [1 if you want libftdi usb_blaster.])
+else
+  AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 0, [0 if you don't want libftdi 
usb_blaster.])
+fi
+
+if test $build_usb_blaster_ftd2xx = yes; then
+  build_bitbang=yes
+  AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 1, [1 if you want ftd2xx usb_blaster.])
+else
+  AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 0, [0 if you don't want ftd2xx 
usb_blaster.])
+fi
+
 if test $build_amtjtagaccel = yes; then
   AC_DEFINE(BUILD_AMTJTAGACCEL, 1, [1 if you want the Amontec JTAG-Accelerator 
driver.])
 else
@@ -727,7 +749,7 @@ then
   AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.])
 fi
 
-if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes ; then
+if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o 
$build_usb_blaster_ftd2xx = yes ; then
   AC_MSG_CHECKING([for ftd2xx.lib exists (win32)])
 
   # if we are given a zipdir...
@@ -1001,6 +1023,8 @@ AM_CONDITIONAL(AT91RM9200, test $build_at91rm9200 = yes)
 AM_CONDITIONAL(BITBANG, test $build_bitbang = yes)
 AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes)
 AM_CONDITIONAL(FT2232_DRIVER, test $build_ft2232_ftd2xx = yes -o 
$build_ft2232_libftdi = yes)
+AM_CONDITIONAL(USB_BLASTER_LIBFTDI, test $build_usb_blaster_libftdi = yes)
+AM_CONDITIONAL(USB_BLASTER_DRIVER, test $build_usb_blaster_ftd2xx = yes -o 
$build_usb_blaster_libftdi = yes)
 AM_CONDITIONAL(AMTJTAGACCEL, test $build_amtjtagaccel = yes)
 AM_CONDITIONAL(GW16012, test $build_gw16012 = yes)
 AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 4244a1e..91c1536 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -310,6 +310,23 @@ chips are starting to become available in JTAG adapters.
 @* Link @url{http://www.hitex.com/index.php?id=cortino}
 @end itemize
 
+...@section USB-JTAG / Altera USB-Blaster compatibles
+
+These devices also show up as FTDI devices, but are not protocol-compatible 
with
+the FT2232 devices. They are, however, protocol-compatible among themselves.
+USB-JTAG devices typically consist of a FT245 followed by a CPLD that
+understands a particular protocol, or emulate this protocol using some other
+hardware.
+
+They may appear under different USB VID/PID depending on the particular 
product.
+The driver can be configured to search for any VID/PID pair (see the section
+on driver commands).
+
+...@item @b{USB-JTAG} Kolja Waschk's USB Blaster-compatible adapter
+...@* Link: @url{http://www.ixo.de/info/usb_jtag/}
+...@item @b{Altera USB-Blaster}
+...@* Link: @url{http://www.altera.com/literature/ug/ug_usb_blstr.pdf}
+
 @section USB JLINK based
 There are several OEM versions of the Segger @b{JLINK} adapter. It is
 an example of a micro controller based JTAG adapter, it uses an
@@ -1988,6 +2005,32 @@ ft2232_vid_pid 0x0403 0xbdc8
 @end example
 @end deffn
 
+...@deffn {Interface Driver} {usb_blaster}
+USB JTAG/USB-Blaster compatibles over one of the userspace libraries.
+These interfaces have several commands, used to configure the driver
+before initializing the JTAG scan chain:
+
+...@deffn {Config Command} {usb_blaster_device_desc} description
+Provides the USB device description (the @emph{iProduct string})
+of the FTDI FT245 device. If not
+specified, the FTDI default value is used. This setting is only valid
+if compiled with FTD2XX support.
+...@end deffn
+
+...@deffn {Config Command} {usb_blaster_vid_pid} [vid pid]
+The vendor ID and product ID of the FTDI FT245 device. If not specified, the 
FTDI
+default values are used.
+Currently, only one [var{vid}, @var{pid}] pair may be given, e.g. for
+Altera USB-Blaster (default):
+...@example
+ft2232_vid_pid 0x09FB 0x6001
+...@end example
+The following VID/PID is for Kolja Waschk's USB JTAG:
+...@example
+ft2232_vid_pid 0x16C0 0x06AD
+...@end example
+...@end deffn
+
 @deffn {Interface Driver} {gw16012}
 Gateworks GW16012 JTAG programmer.
 This has one driver-specific command:
diff --git a/src/Makefile.am b/src/Makefile.am
index f60feac..a566b4d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,12 +60,16 @@ endif
 if FT2232_LIBFTDI
 FTDI2232LIB = -lftdi -lusb
 else
+if USB_BLASTER_LIBFTDI
+FTDI2232LIB = -lftdi -lusb
+else
 if PRESTO_LIBFTDI
 FTDI2232LIB = -lftdi -lusb
 else
 FTDI2232LIB =
 endif
 endif
+endif
 
 if USBPROG
 LIBUSB = -lusb
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index 8ee5ac5..d6113c6 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -28,6 +28,9 @@ endif
 if FT2232_DRIVER
 DRIVERFILES += ft2232.c
 endif
+if USB_BLASTER_DRIVER
+DRIVERFILES += usb_blaster.c
+endif
 if AMTJTAGACCEL
 DRIVERFILES += amt_jtagaccel.c
 endif
diff --git a/src/jtag/drivers/usb_blaster.c b/src/jtag/drivers/usb_blaster.c
new file mode 100644
index 0000000..15c23c6
--- /dev/null
+++ b/src/jtag/drivers/usb_blaster.c
@@ -0,0 +1,540 @@
+/***************************************************************************
+ *   Driver for USB-JTAG, Altera USB-Blaster and compatibles               *
+ *   Original code from Kolja Waschk's USB-JTAG project                    *
+ *     (http://www.ixo.de/info/usb_jtag/).                                 *
+ *   Some updates by Anthony Liu (2006).                                   *
+ *   Minor updates and cleanup by Catalin Patulea (2009).                  *
+ *                                                                         *
+ *   Copyright (C) 2009 Catalin Patulea                                    *
+ *   [email protected]                                                    *
+ *                                                                         *
+ *   Copyright (C) 2006 Kolja Waschk                                       *
+ *   [email protected]                                                        *
+ *                                                                         *
+ *   Based on ft2232.c and bitbang.c,                                      *
+ *   Copyright (C) 2004,2006 by Dominic Rath                               *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+/*
+ * The following information is originally from Kolja Waschk's USB-JTAG, where
+ * it was presumably obtained by reverse engineering an Altera USB-Blaster.
+ * (see http://www.ixo.de/info/usb_jtag/ for USB-Blaster block diagram and
+ *  usb_jtag-20080705-1200.zip#usb_jtag/host/openocd for protocol)
+ *
+ * The same information is also on the UrJTAG mediawiki, with some additional
+ * notes on bits marked as "unknown" by usb_jtag.
+ * (http://sourceforge.net/apps/mediawiki/urjtag/index.php?
+ *    title=Cable_Altera_USB-Blaster)
+ *
+ * USB-JTAG, Altera USB-Blaster and compatibles are typically implemented as
+ * an FTDIChip FT245 followed by a CPLD which handles a two-mode protocol:
+ *
+ *            _________
+ *           |         |
+ *           | AT93C46 |
+ *           |_________|
+ *            __|__________    _________
+ *           |             |  |         |
+ *      USB__| FTDI 245BM  |__| EPM7064 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK)
+ *           |_____________|  |_________|
+ *            __|__________    _|___________
+ *           |             |  |             |
+ *           | 6 MHz XTAL  |  | 24 MHz Osc. |
+ *           |_____________|  |_____________|
+ *
+ * Protocol details are given in the code below.
+ *
+ * It is also possible to emulate this configuration using a single-chip USB
+ * controller like the Cypress FX2 (again, see usb_jtag for details).
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if IS_CYGWIN == 1
+#include "windows.h"
+#undef LOG_ERROR
+#endif
+
+/* project specific includes */
+#include <jtag/interface.h>
+#include <jtag/commands.h>
+#include <helper/time_support.h>
+
+/* system includes */
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "bitbang.h"
+
+#if (BUILD_USB_BLASTER_FTD2XX == 1 && BUILD_USB_BLASTER_LIBFTDI == 1)
+#error "BUILD_USB_BLASTER_FTD2XX && BUILD_USB_BLASTER_LIBFTDI "
+          "are mutually exclusive"
+#elif (BUILD_USB_BLASTER_FTD2XX != 1 && BUILD_USB_BLASTER_LIBFTDI != 1)
+#error "BUILD_USB_BLASTER_FTD2XX || BUILD_USB_BLASTER_LIBFTDI must be chosen"
+#endif
+
+/* USB_BLASTER access library includes */
+#if BUILD_USB_BLASTER_FTD2XX == 1
+#include <ftd2xx.h>
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+#include <ftdi.h>
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+
+static char *usb_blaster_device_desc = NULL;
+static uint16_t usb_blaster_vid = 0x09fb; // Altera
+static uint16_t usb_blaster_pid = 0x6001; // USB-Blaster
+
+// last output byte in simple bit banging mode
+static uint8_t out_value = 0;
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+static FT_HANDLE ftdih = NULL;
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+static struct ftdi_context ftdic;
+#endif
+
+static int usb_blaster_buf_write(
+       uint8_t *buf, int size, uint32_t *bytes_written)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       FT_STATUS status;
+       DWORD dw_bytes_written;
+
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+       if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
+       {
+               *bytes_written = dw_bytes_written;
+               LOG_ERROR("FT_Write returned: %lu", status);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       else
+       {
+               *bytes_written = dw_bytes_written;
+               return ERROR_OK;
+       }
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       int retval;
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+       if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0)
+       {
+               *bytes_written = 0;
+               LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       else
+       {
+               *bytes_written = retval;
+               return ERROR_OK;
+       }
+#endif
+}
+
+static int usb_blaster_buf_read(uint8_t* buf, int size, uint32_t* bytes_read)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       DWORD dw_bytes_read;
+       FT_STATUS status;
+       if ((status = FT_Read(ftdih, buf, size, &dw_bytes_read)) != FT_OK)
+       {
+               *bytes_read = dw_bytes_read;
+               LOG_ERROR("FT_Read returned: %lu", status);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read);
+#endif
+       *bytes_read = dw_bytes_read;
+       return ERROR_OK;
+
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       int retval;
+       int timeout = 100;
+       *bytes_read = 0;
+
+       while ((*bytes_read < size) && timeout--)
+       {
+               retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - 
*bytes_read);
+               if (retval < 0)
+               {
+                       *bytes_read = 0;
+                       LOG_ERROR("ftdi_read_data: %s", 
ftdi_get_error_string(&ftdic));
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               *bytes_read += retval;
+       }
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read);
+#endif
+       return ERROR_OK;
+#endif
+}
+
+/* The following code doesn't fully utilize the possibilities of the
+ * USB-Blaster. It writes one byte per JTAG pin state change at a time; it
+ * doesn't even try to buffer data up to the maximum packet size of 64 bytes.
+ *
+ * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 
data
+ * bits (bidirectional) in a single USB packet. A header byte has to be sent as
+ * the first byte in a packet with the following meaning:
+ *
+ *   Bit 7 (0x80): Must be set to indicate byte-shift mode.
+ *   Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
+ *   Bit 5..0:     Define the number N of following bytes
+ *
+ * All N following bytes will then be clocked out serially on TDI. If Bit 6 was
+ * set, it will afterwards return N bytes with TDO data read while clocking out
+ * the TDI data. LSB of the first byte after the header byte will appear first
+ * on TDI.
+ */
+
+/* Simple bit banging mode:
+ *
+ *   Bit 7 (0x80): Must be zero (see byte-shift mode above)
+ *   Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
+ *                 in return.
+ *   Bit 5 (0x20): Output Enable/LED.
+ *   Bit 4 (0x10): TDI Output.
+ *   Bit 3 (0x08): nCS Output (not used in JTAG mode).
+ *   Bit 2 (0x04): nCE Output (not used in JTAG mode).
+ *   Bit 1 (0x02): TMS Output.
+ *   Bit 0 (0x01): TCK Output.
+ *
+ * For transmitting a single data bit, you need to write two bytes. Up to 64
+ * bytes can be combined in a single USB packet (but this is not done in the
+ * code below). It isn't possible to read a data without transmitting data.
+ */
+
+#define TCK                    (1 << 0)
+#define TMS                    (1 << 1)
+#define TDI                    (1 << 4)
+#define LED                    (1 << 5)
+#define READ           (1 << 6)
+#define SHMODE         (1 << 7)
+#define OTHERS         ((1 << 2) | (1 << 3) | (1 << 5))
+
+#define READ_TDO       (1 << 0)
+
+static void usb_blaster_write_data(void)
+{
+       uint32_t bytes_written;
+       usb_blaster_buf_write(&out_value, 1, &bytes_written);
+}
+
+static int usb_blaster_read_data(void)
+{
+       int status;
+       uint8_t buf[1];
+       uint32_t bytes_read;
+       
+       out_value |= READ;
+       usb_blaster_write_data();
+       out_value &= ~READ;
+       
+       status = usb_blaster_buf_read(buf, 1, &bytes_read);
+       if (status < 0) {
+               return 0;
+       }
+       
+       return !!(buf[0] & READ_TDO);
+}
+
+static void usb_blaster_write(int tck, int tms, int tdi)
+{
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("---- usb_blaster_write(%d,%d,%d)\n", tck,tms,tdi);
+#endif
+       out_value &= ~(TCK | TMS | TDI);
+       if (tck) out_value |= TCK;
+       if (tms) out_value |= TMS;
+       if (tdi) out_value |= TDI;
+       
+       usb_blaster_write_data();
+}
+
+static int usb_blaster_speed(int speed)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       LOG_DEBUG("TODO: usb_blaster_speed() isn't implemented for libftd2xx!");
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       LOG_DEBUG("TODO: usb_blaster_speed() isn't optimally implemented!");
+       /* TODO: libftdi's ftdi_set_baudrate chokes on high rates, use lowlevel
+        * usb function instead! And additionally allow user to throttle. */
+       if(ftdi_set_baudrate(&ftdic, 3000000/4)<0)
+       {
+               LOG_ERROR("Can't set baud rate to max: %s",
+                       ftdi_get_error_string(&ftdic));
+               return ERROR_JTAG_DEVICE_ERROR;
+       };
+#endif
+
+       return ERROR_OK;
+}
+
+static void usb_blaster_reset(int trst, int srst)
+{
+       LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!", trst, 
srst);
+}
+
+static struct bitbang_interface usb_blaster_bitbang = {
+       .read = usb_blaster_read_data,
+       .write = usb_blaster_write,
+       .reset = usb_blaster_reset,
+};
+
+static int usb_blaster_init(void)
+{
+       uint8_t latency_timer;
+       uint8_t buf[1];
+       int retval;
+       uint32_t bytes_written;
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       FT_STATUS status;
+#endif
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       LOG_DEBUG("'usb_blaster' interface using FTD2XX");
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       LOG_DEBUG("'usb_blaster' interface using libftdi");
+#endif
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       /* Open by device description */
+       if (usb_blaster_device_desc == NULL)
+       {
+               LOG_WARNING("no usb_blaster device description specified, "
+                                       "using default 'USB-Blaster'");
+               usb_blaster_device_desc = "USB-Blaster";
+       }
+
+#if IS_WIN32 == 0
+       /* Add non-standard Vid/Pid to the linux driver */
+       if ((status = FT_SetVIDPID(usb_blaster_vid, usb_blaster_pid)) != FT_OK)
+       {
+               LOG_WARNING("couldn't add %4.4x:%4.4x",
+                       usb_blaster_vid, usb_blaster_pid);
+       }
+#endif
+
+       status = FT_OpenEx(usb_blaster_device_desc, FT_OPEN_BY_DESCRIPTION, 
&ftdih);
+       if (status != FT_OK)
+       {
+               DWORD num_devices;
+
+               LOG_ERROR("unable to open ftdi device: %lu", status);
+               status = FT_ListDevices(&num_devices, NULL, 
FT_LIST_NUMBER_ONLY);
+               if (status == FT_OK)
+               {
+                       char **desc_array = malloc(sizeof(char*) * (num_devices 
+ 1));
+                       int i;
+
+                       for (i = 0; i < num_devices; i++)
+                               desc_array[i] = malloc(64);
+                       desc_array[num_devices] = NULL;
+
+                       status = FT_ListDevices(desc_array, &num_devices,
+                               FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
+
+                       if (status == FT_OK)
+                       {
+                               LOG_ERROR("ListDevices: %d\n", num_devices);
+                               for (i = 0; i < num_devices; i++)
+                                       LOG_ERROR("%i: %s", i, desc_array[i]);
+                       }
+
+                       for (i = 0; i < num_devices; i++)
+                               free(desc_array[i]);
+                       free(desc_array);
+               }
+               else
+               {
+                       printf("ListDevices: NONE\n");
+               }
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if ((status = FT_SetLatencyTimer(ftdih, 2)) != FT_OK)
+       {
+               LOG_ERROR("unable to set latency timer: %i", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK)
+       {
+               LOG_ERROR("unable to get latency timer: %i", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       else
+       {
+               LOG_DEBUG("current latency timer: %i", latency_timer);
+       }
+
+       if ((status = FT_SetBitMode(ftdih, 0x00, 0)) != FT_OK)
+       {
+               LOG_ERROR("unable to disable bit i/o mode: %i", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       if (ftdi_init(&ftdic) < 0)
+               return ERROR_JTAG_INIT_FAILED;
+
+       /* context, vendor id, product id */
+       if (ftdi_usb_open(&ftdic, usb_blaster_vid, usb_blaster_pid) < 0)
+       {
+               LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_usb_reset(&ftdic) < 0)
+       {
+               LOG_ERROR("unable to reset ftdi device");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_set_latency_timer(&ftdic, 2) < 0)
+       {
+               LOG_ERROR("unable to set latency timer");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)
+       {
+               LOG_ERROR("unable to get latency timer");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       else
+       {
+               LOG_DEBUG("current latency timer: %i", latency_timer);
+       }
+
+       ftdi_disable_bitbang(&ftdic);
+#endif
+
+       bitbang_interface = &usb_blaster_bitbang;
+
+       usb_blaster_speed(jtag_get_speed());
+
+#if 0
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
+       {
+               LOG_ERROR("error purging ftd2xx device: %i", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       if (ftdi_usb_purge_buffers(&ftdic) < 0)
+       {
+               LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+#endif
+#endif
+
+       return ERROR_OK;
+}
+
+static int usb_blaster_quit(void)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       FT_STATUS status;
+
+       status = FT_Close(ftdih);
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       ftdi_usb_close(&ftdic);
+       ftdi_deinit(&ftdic);
+#endif
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_device_desc_command)
+{
+       if (CMD_ARGC == 1)
+       {
+               usb_blaster_device_desc = strdup(CMD_ARGV[0]);
+       }
+       else
+       {
+               LOG_ERROR("expected exactly one argument to "
+                                 "usb_blaster_device_desc <description>");
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_vid_pid_command)
+{
+       if (CMD_ARGC > 2)
+       {
+               LOG_WARNING("ignoring extra IDs in ft2232_vid_pid "
+                                       "(maximum is 1 pair)");
+               CMD_ARGC = 2;
+       }
+       if (CMD_ARGC == 2)
+       {
+               COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], usb_blaster_vid);
+               COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], usb_blaster_pid);
+       }
+       else
+       {
+               LOG_WARNING("incomplete usb_blaster_vid_pid configuration 
directive");
+       }
+
+       return ERROR_OK;
+}
+
+static const struct command_registration usb_blaster_command_handlers[] = {
+       {
+               .name = "usb_blaster_device_desc",
+               .handler = usb_blaster_handle_device_desc_command,
+               .mode = COMMAND_CONFIG,
+               .help = "set the USB device description of the Altera 
USB-Blaster device",
+               .usage = "<description>",
+       },
+       {
+               .name = "usb_blaster_vid_pid",
+               .handler = usb_blaster_handle_vid_pid_command,
+               .mode = COMMAND_CONFIG,
+               .help = "the vendor ID and product ID of the Altera USB-Blaster 
device",
+               .usage = "<vid> <pid>",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct jtag_interface usb_blaster_interface =
+{
+       .name = "usb_blaster",
+       .commands = usb_blaster_command_handlers,
+
+       .execute_queue = bitbang_execute_queue,
+
+//     .support_pathmove = 1,
+
+       .speed = usb_blaster_speed,
+       .init = usb_blaster_init,
+       .quit = usb_blaster_quit,
+};
diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
index 643e111..4226b3f 100644
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -58,6 +58,12 @@ extern struct jtag_interface ft2232_interface;
 #if BUILD_FT2232_LIBFTDI == 1
 extern struct jtag_interface ft2232_interface;
 #endif
+#if BUILD_USB_BLASTER_FTD2XX == 1
+extern struct jtag_interface usb_blaster_interface;
+#endif
+#if BUILD_USB_BLASTER_LIBFTDI == 1
+extern struct jtag_interface usb_blaster_interface;
+#endif
 #if BUILD_AMTJTAGACCEL == 1
 extern struct jtag_interface amt_jtagaccel_interface;
 #endif
@@ -115,6 +121,12 @@ struct jtag_interface *jtag_interfaces[] = {
 #if BUILD_FT2232_LIBFTDI == 1
                &ft2232_interface,
 #endif
+#if BUILD_USB_BLASTER_FTD2XX == 1
+               &usb_blaster_interface,
+#endif
+#if BUILD_USB_BLASTER_LIBFTDI == 1
+               &usb_blaster_interface,
+#endif
 #if BUILD_AMTJTAGACCEL == 1
                &amt_jtagaccel_interface,
 #endif
diff --git a/tcl/interface/altera-usb-blaster.cfg 
b/tcl/interface/altera-usb-blaster.cfg
new file mode 100755
index 0000000..bb78339
--- /dev/null
+++ b/tcl/interface/altera-usb-blaster.cfg
@@ -0,0 +1,11 @@
+#
+# Altera USB-Blaster
+#
+# http://www.altera.com/literature/ug/ug_usb_blstr.pdf
+#
+
+interface usb_blaster
+# These are already the defaults.
+# usb_blaster_vid_pid 0x09FB 0x6001
+# usb_blaster_device_desc "USB-Blaster"
+jtag_khz 3000
diff --git a/tcl/interface/usb-jtag.cfg b/tcl/interface/usb-jtag.cfg
new file mode 100755
index 0000000..499e647
--- /dev/null
+++ b/tcl/interface/usb-jtag.cfg
@@ -0,0 +1,11 @@
+#
+# Kolja Waschk's USB-JTAG
+#
+# http://www.ixo.de/info/usb_jtag/
+#
+
+interface usb_blaster
+usb_blaster_vid_pid 0x16C0 0x06AD
+usb_blaster_device_desc "USB-JTAG-IF"
+jtag_khz 3000
+
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to