

#this is highly experimental patch that adds support for buspirate

# use only with openocd-0.3.0-rc0

# to compile:

# tar xvf openocd-0.3.0-rc0.tar.bz2
# cd openocd-0.3.0-rc0
# patch -p1 < ../openocd-0.3.0-rc0-buspirate.diff
# aclocal
# automake
# autoconfig
# mkdir build
# cd build
# ../configure --enable-buspirate
# make
# make install (as root)

# create config that contains these lines (without #) :

# interface buspirate
# buspirate_port /dev/ttyUSB0
# buspirate_speed fast

# enjoy ;)

diff -Naur openocd-0.3.0-rc0/config.h.in openocd-0.3.0-rc0-BP/config.h.in
--- openocd-0.3.0-rc0/config.h.in	2009-10-29 05:23:51.000000000 +0100
+++ openocd-0.3.0-rc0-BP/config.h.in	2010-01-18 17:37:20.000000000 +0100
@@ -69,6 +69,9 @@
 /* 0 if you don't want the usbprog JTAG driver. */
 #undef BUILD_USBPROG
 
+/* 0 if you don't want the usbprog JTAG driver. */
+#undef BUILD_BUSPIRATE
+
 /* 0 if you don't want the Versaloon-Link JTAG driver. */
 #undef BUILD_VSLLINK
 
diff -Naur openocd-0.3.0-rc0/configure.in openocd-0.3.0-rc0-BP/configure.in
--- openocd-0.3.0-rc0/configure.in	2009-10-29 05:23:17.000000000 +0100
+++ openocd-0.3.0-rc0-BP/configure.in	2010-01-18 17:37:04.000000000 +0100
@@ -376,6 +376,10 @@
   AS_HELP_STRING([--enable-usbprog], [Enable building support for the usbprog JTAG Programmer]),
   [build_usbprog=$enableval], [build_usbprog=no])
 
+AC_ARG_ENABLE(buspirate,
+  AS_HELP_STRING([--enable-buspirate], [Enable building support for the buspirate JTAG Programmer]),
+  [build_buspirate=$enableval], [build_buspirate=no])
+
 AC_ARG_ENABLE(oocd_trace,
   AS_HELP_STRING([--enable-oocd_trace],
   [Enable building support for some prototype OpenOCD+trace ETM capture hardware]),
@@ -632,6 +636,12 @@
   AC_DEFINE(BUILD_USBPROG, 0, [0 if you don't want the usbprog JTAG driver.])
 fi
 
+if test $build_buspirate = yes; then
+  AC_DEFINE(BUILD_BUSPIRATE, 1, [1 if you want the buspirate JTAG driver.])
+else
+  AC_DEFINE(BUILD_BUSPIRATE, 0, [0 if you don't want the buspirate JTAG driver.])
+fi
+
 if test $build_oocd_trace = yes; then
   AC_DEFINE(BUILD_OOCD_TRACE, 1, [1 if you want the OpenOCD+trace ETM capture driver.])
 else
@@ -947,6 +957,7 @@
 AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)
 AM_CONDITIONAL(PRESTO_DRIVER, test $build_presto_ftd2xx = yes -o $build_presto_libftdi = yes)
 AM_CONDITIONAL(USBPROG, test $build_usbprog = yes)
+AM_CONDITIONAL(BUSPIRATE, test $build_buspirate = yes)
 AM_CONDITIONAL(OOCD_TRACE, test $build_oocd_trace = yes)
 AM_CONDITIONAL(JLINK, test $build_jlink = yes)
 AM_CONDITIONAL(VSLLINK, test $build_vsllink = yes)
diff -Naur openocd-0.3.0-rc0/src/jtag/Makefile.am openocd-0.3.0-rc0-BP/src/jtag/Makefile.am
--- openocd-0.3.0-rc0/src/jtag/Makefile.am	2009-10-21 13:45:59.000000000 +0200
+++ openocd-0.3.0-rc0-BP/src/jtag/Makefile.am	2010-01-18 17:41:03.000000000 +0100
@@ -68,6 +68,9 @@
 if ARMJTAGEW
 DRIVERFILES += arm-jtag-ew.c
 endif
+if BUSPIRATE
+DRIVERFILES += buspirate.c
+endif
 
 endif
 # endif // MINIDRIVER
diff -Naur openocd-0.3.0-rc0/src/jtag/buspirate.c openocd-0.3.0-rc0-BP/src/jtag/buspirate.c
--- openocd-0.3.0-rc0/src/jtag/buspirate.c	1970-01-01 01:00:00.000000000 +0100
+++ openocd-0.3.0-rc0-BP/src/jtag/buspirate.c	2010-01-29 21:46:55.000000000 +0100
@@ -0,0 +1,826 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Michal Demin                                    *
+ *   heavily based on Benedikt Sauter's usnprog.c and arm-jtag-ew.c        *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "interface.h"
+#include "commands.h"
+
+#include <termios.h>
+#include <fcntl.h>
+
+/* Pins at buspirate */
+#define TDO_BIT			0
+#define TDI_BIT			3
+#define TCK_BIT			2
+#define TMS_BIT			1
+
+
+#undef DEBUG_SERIAL
+static int buspirate_execute_queue(void);
+static int buspirate_speed(int speed);
+static int buspirate_khz(int khz, int *jtag_speed);
+static int buspirate_register_commands(struct command_context_s *cmd_ctx);
+static int buspirate_init(void);
+static int buspirate_quit(void);
+
+static void buspirate_end_state(tap_state_t state);
+static void buspirate_state_move(void);
+static void buspirate_path_move(pathmove_command_t *cmd);
+static void buspirate_runtest(int num_cycles);
+static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, scan_command_t *command);
+
+jtag_interface_t buspirate_interface =
+{
+	.name = "buspirate",
+	.execute_queue = buspirate_execute_queue,
+	.speed = buspirate_speed,
+	.khz = buspirate_khz,
+	.register_commands = buspirate_register_commands,
+	.init = buspirate_init,
+	.quit = buspirate_quit
+};
+
+#define CMD_UNKOWN        0x00
+#define CMD_PORT_MODE     0x01
+#define CMD_FEATURE       0x02
+#define CMD_READ_ADCS     0x03
+#define CMD_TAP_SHIFT     0x04
+#define CMD_TAP_SHIFT2    0x05
+#define CMD_JTAG_SPEED    0x06
+#define CMD_UART_SPEED    0x07
+
+enum {
+	MODE_HIZ=0,
+	MODE_JTAG=1
+};
+
+enum {
+	FEATURE_LED=0x01,
+	FEATURE_VREG=0x02,
+	FEATURE_TRST=0x04,
+	FEATURE_SRST=0x08,
+	FEATURE_PULLUP=0x10
+};
+
+enum {
+	ACTION_DISABLE=0,
+	ACTION_ENABLE=1
+};
+
+enum {
+	SERIAL_NORMAL=0,
+	SERIAL_FAST=1
+};
+
+
+static int buspirate_fd = -1;
+static int buspirate_baudrate = SERIAL_NORMAL;
+static char* buspirate_port = NULL;
+
+
+
+static void buspirate_tap_init(void);
+static int buspirate_tap_execute(void);
+static void buspirate_tap_append(int tms, int tdi);
+static void buspirate_tap_append_scan(int length, uint8_t *buffer, scan_command_t *command);
+static void buspirate_tap_make_space(int scan, int bits);
+
+static void buspirate_reset(int trst, int srst);
+
+/* low level interface */
+static unsigned char buspirate_jtag_command(int buspirate_fd, char *cmd, int cmdlen);
+static void buspirate_jtag_set_speed(int buspirate_fd, char speed);
+static void buspirate_jtag_set_mode(int buspirate_fd, char mode);
+static void buspirate_jtag_set_feature(int buspirate_fd, char feat, char action);
+static void buspirate_jtag_get_adcs(int buspirate_fd);
+
+/* command interface */
+static int buspirate_handle_adc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int buspirate_handle_vreg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int buspirate_handle_led_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int buspirate_handle_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int buspirate_handle_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* low level HW communication interface */
+static int buspirate_serial_setspeed(int fd, speed_t speed);
+static int buspirate_serial_write(int fd, char *buf, int size);
+static int buspirate_serial_read(int fd, char *buf, int size);
+static void buspirate_print_buffer(char* buf, int size);
+
+static int buspirate_speed(int speed)
+{
+	// TODO
+	LOG_INFO("Want to set speed to %dkHz, but not implemented :(", speed);
+	return ERROR_OK;
+}
+
+static int buspirate_khz(int khz, int *jtag_speed) {
+	*jtag_speed = khz;
+	return ERROR_OK;
+}
+
+static int buspirate_register_commands(struct command_context_s *cmd_ctx)
+{
+	register_command(cmd_ctx, NULL, "buspirate_adc", buspirate_handle_adc_command,
+		COMMAND_EXEC, "reads voltages on the buspirate");
+	register_command(cmd_ctx, NULL, "buspirate_vreg", buspirate_handle_vreg_command,
+		COMMAND_EXEC, "changes the state of voltage regulators");
+	register_command(cmd_ctx, NULL, "buspirate_led", buspirate_handle_led_command,
+		COMMAND_EXEC, "changes the state of the led");
+	register_command(cmd_ctx, NULL, "buspirate_speed", buspirate_handle_speed_command,
+		COMMAND_CONFIG, "speed of the interface");
+	register_command(cmd_ctx, NULL, "buspirate_port", buspirate_handle_port_command,
+		COMMAND_CONFIG, "name of the serial port to open");
+	return ERROR_OK;
+}
+
+static int buspirate_execute_queue(void)
+{
+	jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
+	int scan_size;
+	enum scan_type type;
+	uint8_t *buffer;
+
+	while (cmd)
+	{
+		switch (cmd->type)
+		{
+			case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state));
+#endif
+				buspirate_end_state(cmd->cmd.runtest->end_state);
+				buspirate_runtest(cmd->cmd.runtest->num_cycles);
+				break;
+			case JTAG_STATEMOVE:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state));
+#endif
+				buspirate_end_state(cmd->cmd.statemove->end_state);
+				buspirate_state_move();
+				break;
+			case JTAG_PATHMOVE:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states,
+					tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
+#endif
+				buspirate_path_move(cmd->cmd.pathmove);
+				break;
+			case JTAG_SCAN:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("scan end in %s", tap_state_name(cmd->cmd.scan->end_state));
+#endif
+
+				buspirate_end_state(cmd->cmd.scan->end_state);
+
+				scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+				type = jtag_scan_type(cmd->cmd.scan);
+				buspirate_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
+
+				break;
+			case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+				// flush buffers, so we can reset
+				buspirate_tap_execute();
+
+				if (cmd->cmd.reset->trst == 1)
+				{
+					tap_set_state(TAP_RESET);
+				}
+				buspirate_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+				break;
+			case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
+#endif
+				buspirate_tap_execute();
+				jtag_sleep(cmd->cmd.sleep->us);
+					break;
+			default:
+				LOG_ERROR("BUG: unknown JTAG command type encountered");
+				exit(-1);
+		}
+
+		cmd = cmd->next;
+	}
+
+	return buspirate_tap_execute();
+}
+
+static int buspirate_init(void)
+{
+buspirate_print_buffer(" ", 0);
+	if (buspirate_port == NULL) {
+		buspirate_port = "/dev/ttyUSB0";
+	}
+
+
+	buspirate_fd = open(buspirate_port, O_RDWR | O_NOCTTY);
+	if (buspirate_fd == -1)
+	{
+		LOG_ERROR("Could not open serial port.");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	buspirate_serial_setspeed(buspirate_fd, B115200);
+
+	if (buspirate_baudrate != SERIAL_NORMAL) {
+		buspirate_jtag_set_speed(buspirate_fd, SERIAL_FAST);
+	}
+
+	LOG_INFO("Buspirate Interface ready!");
+
+	buspirate_tap_init();
+	buspirate_jtag_set_mode(buspirate_fd, MODE_JTAG);
+	buspirate_reset(0, 0);
+
+	return ERROR_OK;
+}
+
+static int buspirate_quit(void)
+{
+	if (buspirate_port) {
+		free(buspirate_port);
+		buspirate_port = NULL;
+	}
+	return ERROR_OK;
+}
+
+/*************** jtag execute commands **********************/
+static void buspirate_end_state(tap_state_t state)
+{
+	if (tap_is_state_stable(state))
+		tap_set_end_state(state);
+	else
+	{
+		LOG_ERROR("BUG: %i is not a valid end state", state);
+		exit(-1);
+	}
+}
+
+static void buspirate_state_move(void)
+{
+	int i = 0, tms = 0;
+	uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
+	int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
+
+	for (i = 0; i < tms_count; i++)
+	{
+		tms = (tms_scan >> i) & 1;
+		buspirate_tap_append(tms, 0);
+	}
+
+	tap_set_state(tap_get_end_state());
+}
+
+static void buspirate_path_move(pathmove_command_t *cmd)
+{
+	int num_states = cmd->num_states;
+	int i;
+
+	for (i = 0; i< num_states; i++)
+	{
+		if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
+		{
+			/* LOG_INFO("1"); */
+			buspirate_tap_append(0, 0);
+		}
+		else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
+		{
+			/* LOG_INFO("2"); */
+			buspirate_tap_append(1, 0);
+		}
+		else
+		{
+			LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[i]));
+			exit(-1);
+		}
+
+		tap_set_state(cmd->path[i]);
+	}
+
+	tap_set_end_state(tap_get_state());
+}
+
+static void buspirate_runtest(int num_cycles)
+{
+	int i;
+	
+	tap_state_t saved_end_state = tap_get_end_state();
+
+	/* only do a state_move when we're not already in IDLE */
+	if (tap_get_state() != TAP_IDLE)
+	{
+		buspirate_end_state(TAP_IDLE);
+		buspirate_state_move();
+	}
+
+	for (i = 0; i < num_cycles; i++)
+	{
+		buspirate_tap_append(0, 0);
+	}
+
+#ifdef _DEBUG_JTAG_IO_
+	LOG_DEBUG("runtest: cur_state %s end_state %s", tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()));
+#endif
+
+	/* finish in end_state */
+	buspirate_end_state(saved_end_state);
+	if (tap_get_state() != tap_get_end_state())
+	{
+		buspirate_state_move();
+	}
+}
+
+static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, scan_command_t *command)
+{
+	tap_state_t saved_end_state;
+	
+	buspirate_tap_make_space(1, scan_size+8); // is 8 correct ? (2 moves = 16)
+	
+	saved_end_state = tap_get_end_state();
+
+	buspirate_end_state(ir_scan?TAP_IRSHIFT:TAP_DRSHIFT);
+	buspirate_state_move();
+
+
+	/* The adapter does the transition to PAUSE internally */
+	if (ir_scan)
+		tap_set_state(TAP_IRPAUSE);
+	else
+		tap_set_state(TAP_DRPAUSE);
+
+	buspirate_tap_append_scan(scan_size, buffer, command);
+
+	/* move to PAUSE */
+	buspirate_tap_append(0, 0);
+
+	/* restore the saved state */	
+	buspirate_end_state(saved_end_state);
+	tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
+
+	if (tap_get_state() != tap_get_end_state())
+		buspirate_state_move();
+}
+
+
+/************************* TAP related stuff **********/
+
+#define BUSPIRATE_BUFFER_SIZE 1024
+#define BUSPIRATE_MAX_PENDING_SCANS 32
+
+static char tms_chain[BUSPIRATE_BUFFER_SIZE]; // send
+static char tdi_chain[BUSPIRATE_BUFFER_SIZE]; // send
+//static char tdo_chain[BUSPIRATE_BUFFER_SIZE]; // recv
+static int tap_chain_index;
+
+typedef struct // this was stolen from arm-jtag-ew
+{
+	int first;	/* First bit position in tdo_buffer to read */
+	int length; /* Number of bits to read */
+	scan_command_t *command; /* Corresponding scan command */
+	uint8_t *buffer;
+} pending_scan_result_t;
+
+static pending_scan_result_t tap_pending_scans[BUSPIRATE_MAX_PENDING_SCANS];
+static int tap_pending_scans_num;
+
+static void buspirate_tap_init(void) {
+	tap_chain_index = 0;
+	tap_pending_scans_num = 0;
+}
+
+static int buspirate_tap_execute(void)
+{
+	char tmp[4096];
+	uint8_t *in_buf;
+	int i;
+	int fill_index = 0;
+	int ret;
+  int bytes_to_send;
+
+	if (tap_chain_index <= 0)
+		return ERROR_OK;
+	LOG_DEBUG("executing tap num bits = %i scans = %i", tap_chain_index, tap_pending_scans_num);
+
+	bytes_to_send = (tap_chain_index+7) / 8;
+
+	tmp[0] = CMD_TAP_SHIFT2; // this command expects number of bits
+	tmp[1] = (char)(tap_chain_index >> 8);	/* high */
+	tmp[2] = (char)(tap_chain_index);			  /* low */
+
+	fill_index = 3;
+	for (i=0; i<bytes_to_send; i++) {
+		tmp[fill_index] = tdi_chain[i];
+		fill_index++;
+		tmp[fill_index] = tms_chain[i];
+		fill_index++;
+	}
+
+	ret = buspirate_serial_write(buspirate_fd, tmp, 3 + bytes_to_send*2);
+	if (ret != bytes_to_send*2+3)
+	{
+		LOG_ERROR("error writing :(");
+		return ERROR_JTAG_DEVICE_ERROR;
+	}
+#ifdef DEBUG_SERIAL
+fprintf(stderr,"bytes writen %i:\n", ret);
+buspirate_print_buffer(tmp, bytes_to_send*2+3);
+#endif
+
+//	usleep(1);
+
+	ret = buspirate_serial_read(buspirate_fd, tmp, bytes_to_send + 3);
+#ifdef DEBUG_SERIAL
+fprintf(stderr,"bytes read %i should have read %i:\n", ret, bytes_to_send + 3);
+buspirate_print_buffer(tmp, bytes_to_send+3);
+#endif
+	in_buf = (uint8_t*)(&tmp[3]);
+	/* parse the scans */
+	for (i = 0; i < tap_pending_scans_num; i++) {
+		uint8_t *buffer = tap_pending_scans[i].buffer;
+		int length = tap_pending_scans[i].length;
+		int first = tap_pending_scans[i].first;
+		scan_command_t *command = tap_pending_scans[i].command;
+//LOG_INFO("Parsing scan result [%i] len = %i first = %i bytes:", i, length, first); 
+
+		/* copy bits from buffer */ 
+		buf_set_buf(in_buf, first, buffer, 0, length);
+//buspirate_print_buffer((char*)buffer, (length+7)/8);
+
+		/* return buffer to higher level */
+		if (jtag_read_buffer(buffer, command) != ERROR_OK)
+		{
+			buspirate_tap_init();
+			return ERROR_JTAG_QUEUE_FAILED;
+		}
+
+		if (buffer) {
+			free(buffer);
+		}
+	}
+	tap_pending_scans_num = 0;
+	tap_chain_index = 0;
+	return ERROR_OK;
+}
+
+static void buspirate_tap_make_space(int scans, int bits) 
+{
+	int have_scans = BUSPIRATE_MAX_PENDING_SCANS - tap_pending_scans_num;
+	int have_bits = BUSPIRATE_BUFFER_SIZE * 8 - tap_chain_index;
+
+	if ((have_scans < scans) || (have_bits < bits))
+	{
+		buspirate_tap_execute();
+	}
+}
+
+static void buspirate_tap_append(int tms, int tdi)
+{
+	int index = tap_chain_index / 8;
+
+	if (index < BUSPIRATE_BUFFER_SIZE)
+	{
+		int bit_index = tap_chain_index % 8;
+		uint8_t bit = 1 << bit_index;
+
+		if (tms)
+			tms_chain[index] |= bit;
+		else
+			tms_chain[index] &= ~bit;
+
+		if (tdi)
+			tdi_chain[index] |= bit;
+		else
+			tdi_chain[index] &= ~bit;
+
+		tap_chain_index++;
+	}
+	else
+	{
+		LOG_ERROR("tap_chain overflow, Bad things will happen");
+	}
+	
+}
+
+static void buspirate_tap_append_scan(int length, uint8_t *buffer, scan_command_t *command)
+{
+	int i;
+	tap_pending_scans[tap_pending_scans_num].length = length;
+	tap_pending_scans[tap_pending_scans_num].buffer = buffer;
+	tap_pending_scans[tap_pending_scans_num].command = command;
+	tap_pending_scans[tap_pending_scans_num].first = tap_chain_index;
+//fprintf(stderr,"adding scan\n");
+	for (i = 0; i<length; i++) {
+		int tms = (i < length-1 ? 0 : 1);
+		int tdi = (buffer[i/8] >> (i%8)) & 1;
+		buspirate_tap_append(tms, tdi);
+	}
+	tap_pending_scans_num++;
+}
+
+/*************** jtag wrapper functions *********************/
+
+/* (1) assert or (0) deassert reset lines */
+static void buspirate_reset(int trst, int srst)
+{
+	LOG_DEBUG("trst: %i, srst: %i", trst, srst);
+
+	if (trst)
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_TRST, ACTION_DISABLE);
+	else
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_TRST, ACTION_ENABLE);
+
+	if (srst)
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_SRST, ACTION_DISABLE);
+	else
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_SRST, ACTION_ENABLE);
+}
+
+/*************** jtag lowlevel functions ********************/
+
+static void buspirate_jtag_set_speed(int fd, char speed)
+{
+	int ret;
+	char tmp[2];
+	char ack[2];
+	speed_t baudrate = B115200;
+
+	ack[0] = 0xAA;
+	ack[1] = 0x55;
+
+	tmp[0] = CMD_UART_SPEED;
+	tmp[1] = speed;
+	buspirate_jtag_command(fd, tmp, 2);
+
+	// here the adapter changes speed, we need follow
+	if (speed == SERIAL_FAST) {
+		baudrate = B1000000;
+	}
+	buspirate_serial_setspeed(fd, baudrate);
+
+	buspirate_serial_write(fd, ack, 2);
+	ret = buspirate_serial_read(fd, tmp, 2);
+	if (ret != 2) {
+		LOG_ERROR("Buspirate did not respond :(( restart everything");
+		exit(-1);
+	}
+	if ((tmp[0] != CMD_UART_SPEED) || (tmp[1] != speed)) {
+		LOG_ERROR("Buspirate didn't reply as expected :(( restart everything");
+		exit(-1);
+	}
+	LOG_INFO("Running in %s mode", (speed==SERIAL_NORMAL)?"normal":"FAST");
+}
+
+
+static void buspirate_jtag_set_mode(int fd, char mode)
+{
+	char tmp[2];
+	tmp[0] = CMD_PORT_MODE;
+	tmp[1] = mode;
+	buspirate_jtag_command(fd, tmp, 2);
+}
+
+static void buspirate_jtag_set_feature(int fd, char feat, char action)
+{
+	char tmp[3];
+	tmp[0] = CMD_FEATURE;
+	tmp[1] = feat;   // what
+	tmp[2] = action; // action
+	buspirate_jtag_command(fd, tmp, 3);
+}
+
+static void buspirate_jtag_get_adcs(int fd)
+{
+	char tmp[10];
+	tmp[0] = CMD_READ_ADCS;
+	buspirate_jtag_command(fd, tmp, 1);
+	LOG_INFO("ADC: Ch1 = %d Ch2 = %d Ch3 = %d", tmp[1], tmp[2], tmp[3]);
+}
+
+static unsigned char buspirate_jtag_command(int buspirate_fd, char *cmd, int cmdlen)
+{
+	int res;
+	int len = 0;
+	
+	res = buspirate_serial_write(buspirate_fd, cmd, cmdlen);
+#ifdef DEBUG_SERIAL
+//LOG_INFO("jtag_message  %i",(int)cmd[0]);
+LOG_INFO("write cmd = %i bytes %i", cmd[0], res); 
+buspirate_print_buffer(cmd, cmdlen);
+#endif
+	if ((cmd[0] == CMD_UART_SPEED) || (cmd[0] == CMD_PORT_MODE) || (cmd[0] == CMD_FEATURE) || (cmd[0] == CMD_JTAG_SPEED))
+		return 1;
+
+	if (res == cmdlen)
+	{
+	//	LOG_INFO("waiting jtag_message response %i",(int)msg[0]);
+		switch (cmd[0]) {
+			case CMD_READ_ADCS:
+				len = 4; // 3+1
+				break;
+			case CMD_TAP_SHIFT:
+			case CMD_TAP_SHIFT2:
+				len = cmdlen;
+				break;
+			default:
+				LOG_INFO("Wrong !");
+		}
+		res =  buspirate_serial_read(buspirate_fd, cmd, len);
+#ifdef DEBUG_SERIAL
+LOG_INFO("read bytes  %i should have read  %i", res, len); 
+buspirate_print_buffer(cmd, len);
+#endif
+		if (res > 0)
+			return (unsigned char)cmd[1];
+		else
+			return -1;
+	}
+	else
+		return -1;
+	return 0;
+}
+
+/* openocd command interface */
+static int buspirate_handle_adc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) {
+	if (argc != 0)
+	{
+		command_print(cmd_ctx, "usage: buspirate_adc");
+		return ERROR_OK;
+	}
+
+	if (buspirate_fd == -1) {
+		return ERROR_OK;
+	}
+
+	// send the command
+	buspirate_jtag_get_adcs(buspirate_fd);
+
+	return ERROR_OK;
+	
+}
+
+static int buspirate_handle_vreg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) {
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: buspirate_vreg <1|0>");
+		return ERROR_OK;
+	}
+
+	if (atoi(args[0]) == 1) {
+		// enable vreg
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_VREG, ACTION_ENABLE);
+	} else {
+		// disable vreg
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_VREG, ACTION_DISABLE);
+	}
+
+	return ERROR_OK;
+	
+}
+
+static int buspirate_handle_led_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) {
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: buspirate_led <1|0>");
+		return ERROR_OK;
+	}
+
+	if (atoi(args[0]) == 1) {
+		// enable led
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED, ACTION_ENABLE);
+	} else {
+		// disable led
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED, ACTION_DISABLE);
+	}
+
+	return ERROR_OK;
+	
+}
+
+static int buspirate_handle_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) {
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: buspirate_speed <normal|fast>");
+		return ERROR_OK;
+	}
+
+	if (args[0][0] == 'n') {
+		buspirate_baudrate = SERIAL_NORMAL;
+	} else if (args[0][0] == 'f') {
+		buspirate_baudrate = SERIAL_FAST;
+	} else {
+		command_print(cmd_ctx, "usage: buspirate_speed <normal|fast>");
+	}
+
+	return ERROR_OK;
+	
+}
+
+static int buspirate_handle_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) {
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: buspirate_port /dev/ttyUSB0");
+		return ERROR_OK;
+	}
+
+	if (buspirate_port == 0) {
+		buspirate_port = strdup(args[0]);
+	}
+
+	return ERROR_OK;
+	
+}
+
+/* low level serial port */
+static int buspirate_serial_setspeed(int fd, speed_t speed) {
+	struct termios t_opt;
+
+	/* set the serial port parameters */
+	fcntl(buspirate_fd, F_SETFL, 0);
+	tcgetattr(buspirate_fd, &t_opt);
+	cfsetispeed(&t_opt, speed);
+	cfsetospeed(&t_opt, speed);
+	t_opt.c_cflag |= (CLOCAL | CREAD);
+	t_opt.c_cflag &= ~PARENB;
+	t_opt.c_cflag &= ~CSTOPB;
+	t_opt.c_cflag &= ~CSIZE;
+	t_opt.c_cflag |= CS8;
+	t_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+	t_opt.c_iflag &= ~(IXON | IXOFF | IXANY);
+	t_opt.c_oflag &= ~OPOST;
+	t_opt.c_cc[VMIN] = 0;
+	t_opt.c_cc[VTIME] = 10;
+	tcsetattr(buspirate_fd, TCSANOW, &t_opt);
+
+	return 0;
+}
+
+static int buspirate_serial_write(int fd, char *buf, int size) {
+	int ret = 0;
+
+	ret = write(fd, buf, size);
+
+	if (ret != size) {
+		LOG_ERROR("Error sending data");
+	}
+	
+	return ret;
+}
+
+static int buspirate_serial_read(int fd, char *buf, int size) {
+	int len = 0;
+	int ret = 0;
+	int timeout = 0;
+
+	while (len < size)
+	{
+		ret = read(fd, buf+len, size-len); 
+		if (ret == -1)
+			return -1;
+		
+		if (ret == 0) {
+			timeout ++;
+		
+			if (timeout >= 10) 
+				return len;
+
+			continue;
+		}
+		
+		len += ret;
+	}
+
+	return len;
+}
+
+static void buspirate_print_buffer(char* buf, int size) {
+	int i;
+
+	for (i = 0 ; i < size; i++) {
+		fprintf(stderr, "%02X ", ((unsigned char)buf[i]) & 0xff);
+	}
+	fprintf(stderr, "\n");
+}
diff -Naur openocd-0.3.0-rc0/src/jtag/interfaces.c openocd-0.3.0-rc0-BP/src/jtag/interfaces.c
--- openocd-0.3.0-rc0/src/jtag/interfaces.c	2009-10-21 13:45:59.000000000 +0200
+++ openocd-0.3.0-rc0-BP/src/jtag/interfaces.c	2010-01-18 17:41:44.000000000 +0100
@@ -88,6 +88,9 @@
 #if BUILD_ARMJTAGEW == 1
 extern jtag_interface_t armjtagew_interface;
 #endif
+#if BUILD_BUSPIRATE == 1
+extern jtag_interface_t buspirate_interface;
+#endif
 #endif // standard drivers
 
 /**
@@ -145,6 +148,9 @@
 #if BUILD_ARMJTAGEW == 1
 		&armjtagew_interface,
 #endif
+#if BUILD_BUSPIRATE == 1
+		&buspirate_interface,
+#endif
 #endif // standard drivers
 		NULL,
 	};
