Adds initial support for Buspirate as Jtag interface

---
 configure.in                 |   11 +
 doc/openocd.texi             |    3 +
 src/jtag/drivers/Makefile.am |    3 +
 src/jtag/drivers/buspirate.c |  981 ++++++++++++++++++++++++++++++++++++++++++
 src/jtag/interfaces.c        |    6 +
 tcl/interface/buspirate.cfg  |   16 +
 6 files changed, 1020 insertions(+), 0 deletions(-)
 create mode 100644 src/jtag/drivers/buspirate.c
 create mode 100644 tcl/interface/buspirate.cfg

diff --git a/configure.in b/configure.in
index 3b0a06d..d93b21a 100644
--- a/configure.in
+++ b/configure.in
@@ -474,6 +474,10 @@ AC_ARG_ENABLE(arm-jtag-ew,
  AS_HELP_STRING([--enable-arm-jtag-ew], [Enable building support for
the Olimex ARM-JTAG-EW Programmer]),
  [build_armjtagew=$enableval], [build_armjtagew=no])

+AC_ARG_ENABLE(buspirate,
+  AS_HELP_STRING([--enable-buspirate], [Enable building support for
the Buspirate]),
+  [build_buspirate=$enableval], [build_buspirate=no])
+
 AC_ARG_ENABLE(minidriver_dummy,
  AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]),
  [build_minidriver_dummy=$enableval], [build_minidriver_dummy=no])
@@ -741,6 +745,12 @@ else
  AC_DEFINE(BUILD_ARMJTAGEW, 0, [0 if you don't want the ARM-JTAG-EW
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
+
 #-- Deal with MingW/Cygwin FTD2XX issues

 if test $is_win32 = yes; then
@@ -1035,6 +1045,7 @@ AM_CONDITIONAL(JLINK, test $build_jlink = yes)
 AM_CONDITIONAL(VSLLINK, test $build_vsllink = yes)
 AM_CONDITIONAL(RLINK, test $build_rlink = yes)
 AM_CONDITIONAL(ARMJTAGEW, test $build_armjtagew = yes)
+AM_CONDITIONAL(BUSPIRATE, test $build_buspirate = yes)
 AM_CONDITIONAL(USB, test $build_usb = yes)
 AM_CONDITIONAL(IS_CYGWIN, test $is_cygwin = yes)
 AM_CONDITIONAL(IS_MINGW, test $is_mingw = yes)
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 61e39b2..bcf06e7 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -386,6 +386,9 @@ Raisonance has an adapter called @b{RLink}.  It
exists in a stripped-down form o

 @item @b{ARM-JTAG-EW}
 @* Link: @url{http://www.olimex.com/dev/arm-jtag-ew.html}
+
+...@item @b{Buspirate}
+...@* Link: @url{http://dangerousprototypes.com}
 @end itemize

 @section IBM PC Parallel Printer Port Based
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index d6113c6..0588126 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -64,6 +64,9 @@ endif
 if ARMJTAGEW
 DRIVERFILES += arm-jtag-ew.c
 endif
+if BUSPIRATE
+DRIVERFILES += buspirate.c
+endif

 noinst_HEADERS = \
       bitbang.h \
diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c
new file mode 100644
index 0000000..9b7d67e
--- /dev/null
+++ b/src/jtag/drivers/buspirate.c
@@ -0,0 +1,981 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Michal Demin                                    *
+ *   based on usbprog.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 <jtag/interface.h>
+#include <jtag/commands.h>
+
+#include <termios.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#undef DEBUG_SERIAL
+//#define 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_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(int num_states, tap_state_t *path);
+static void buspirate_runtest(int num_cycles);
+static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t
*buffer, int scan_size, struct scan_command *command);
+
+
+#define CMD_UNKOWN        0x00
+#define CMD_PORT_MODE     0x01
+#define CMD_FEATURE       0x02
+#define CMD_READ_ADCS     0x03
+//#define CMD_TAP_SHIFT     0x04 // old protocol
+#define CMD_TAP_SHIFT     0x05
+#define CMD_ENTER_OOCD    0x06
+#define CMD_UART_SPEED    0x07
+#define CMD_JTAG_SPEED    0x08
+
+enum {
+       MODE_HIZ=0,
+       MODE_JTAG=1, // push-pull outputs
+       MODE_JTAG_OD=2, // open-drain outputs
+};
+
+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_pinmode = MODE_JTAG_OD;
+static int buspirate_baudrate = SERIAL_NORMAL;
+static int buspirate_vreg = 0;
+static int buspirate_pullup = 0;
+static char* buspirate_port = NULL;
+
+
+/* TAP interface */
+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,
struct scan_command *command);
+static void buspirate_tap_make_space(int scan, int bits);
+
+static void buspirate_reset(int trst, int srst);
+
+/* low level interface */
+static void buspirate_jtag_reset(int);
+static void buspirate_jtag_enable(int);
+static unsigned char buspirate_jtag_command(int, char *, int);
+static void buspirate_jtag_set_speed(int, char);
+static void buspirate_jtag_set_mode(int, char);
+static void buspirate_jtag_set_feature(int, char, char);
+static void buspirate_jtag_get_adcs(int);
+
+/* 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_execute_queue(void)
+{
+       struct jtag_command *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->num_states,
cmd->cmd.pathmove->path);
+                               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);
+
+       buspirate_jtag_enable(buspirate_fd);
+
+       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, buspirate_pinmode);
+       buspirate_jtag_set_feature(buspirate_fd, FEATURE_VREG,
(buspirate_vreg==1)?ACTION_ENABLE:ACTION_DISABLE);
+       buspirate_jtag_set_feature(buspirate_fd, FEATURE_PULLUP,
(buspirate_pullup==1)?ACTION_ENABLE:ACTION_DISABLE);
+       buspirate_reset(0, 0);
+
+       return ERROR_OK;
+}
+
+static int buspirate_quit(void)
+{
+       LOG_INFO("Shuting down buspirate ");
+       buspirate_jtag_set_mode(buspirate_fd, MODE_HIZ);
+
+       buspirate_jtag_set_speed(buspirate_fd, SERIAL_NORMAL);
+       buspirate_jtag_reset(buspirate_fd);
+       if (buspirate_port) {
+               free(buspirate_port);
+               buspirate_port = NULL;
+       }
+       return ERROR_OK;
+}
+
+/* openocd command interface */
+COMMAND_HANDLER(buspirate_handle_adc_command) {
+       if (CMD_ARGC != 0)
+       {
+               LOG_ERROR("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;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_vreg_command) {
+       if (CMD_ARGC != 1)
+       {
+               LOG_ERROR("usage: buspirate_vreg <1|0>");
+               return ERROR_OK;
+       }
+
+       if (atoi(CMD_ARGV[0]) == 1) {
+               buspirate_vreg = 1;
+       } else {
+               buspirate_vreg = 0;
+       }
+
+       return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_pullup_command) {
+       if (CMD_ARGC != 1)
+       {
+               LOG_ERROR("usage: buspirate_pullup <1|0>");
+               return ERROR_OK;
+       }
+
+       if (atoi(CMD_ARGV[0]) == 1) {
+               buspirate_pullup = 1;
+       } else {
+               buspirate_pullup = 0;
+       }
+
+       return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_led_command) {
+       if (CMD_ARGC != 1)
+       {
+               LOG_ERROR("usage: buspirate_led <1|0>");
+               return ERROR_OK;
+       }
+
+       if (atoi(CMD_ARGV[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;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_mode_command) {
+       if (CMD_ARGC != 1)
+       {
+               LOG_ERROR("usage: buspirate_mode <normal|open-drain>");
+               return ERROR_OK;
+       }
+
+       if (CMD_ARGV[0][0] == 'n') {
+               buspirate_pinmode = MODE_JTAG;
+       } else if (CMD_ARGV[0][0] == 'o') {
+               buspirate_pinmode = MODE_JTAG_OD;
+       } else {
+               LOG_ERROR("usage: buspirate_mode <normal|open-drain>");
+       }
+
+       return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_speed_command) {
+       if (CMD_ARGC != 1)
+       {
+               LOG_ERROR("usage: buspirate_speed <normal|fast>");
+               return ERROR_OK;
+       }
+
+       if (CMD_ARGV[0][0] == 'n') {
+               buspirate_baudrate = SERIAL_NORMAL;
+       } else if (CMD_ARGV[0][0] == 'f') {
+               buspirate_baudrate = SERIAL_FAST;
+       } else {
+               LOG_ERROR("usage: buspirate_speed <normal|fast>");
+       }
+
+       return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_port_command) {
+       if (CMD_ARGC != 1)
+       {
+               LOG_ERROR("usage: buspirate_port /dev/ttyUSB0");
+               return ERROR_OK;
+       }
+
+       if (buspirate_port == 0) {
+               buspirate_port = strdup(CMD_ARGV[0]);
+       }
+
+       return ERROR_OK;
+
+}
+
+static const struct command_registration buspirate_command_handlers[] = {
+       {
+               .name = "buspirate_adc",
+               .handler = &buspirate_handle_adc_command,
+               .mode = COMMAND_EXEC,
+               .help = "reads voltages on adc pins",
+       },
+       {
+               .name = "buspirate_vreg",
+               .handler = &buspirate_handle_vreg_command,
+               .mode = COMMAND_CONFIG,
+               .help = "changes the state of voltage regulators",
+       },
+       {
+               .name = "buspirate_pullup",
+               .handler = &buspirate_handle_pullup_command,
+               .mode = COMMAND_CONFIG,
+               .help = "changes the state of pullup",
+       },
+       {
+               .name = "buspirate_led",
+               .handler = &buspirate_handle_led_command,
+               .mode = COMMAND_EXEC,
+               .help = "changes the state of led",
+       },
+       {
+               .name = "buspirate_speed",
+               .handler = &buspirate_handle_speed_command,
+               .mode = COMMAND_CONFIG,
+               .help = "speed of the interface",
+       },
+       {
+               .name = "buspirate_mode",
+               .handler = &buspirate_handle_mode_command,
+               .mode = COMMAND_CONFIG,
+               .help = "pin mode of the interface",
+       },
+       {
+               .name = "buspirate_port",
+               .handler = &buspirate_handle_port_command,
+               .mode = COMMAND_CONFIG,
+               .help = "name of the serial port to open",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct jtag_interface buspirate_interface =
+{
+       .name = "buspirate",
+       .execute_queue = buspirate_execute_queue,
+       .speed = buspirate_speed,
+       .khz = buspirate_khz,
+       .commands = buspirate_command_handlers,
+       .init = buspirate_init,
+       .quit = buspirate_quit
+};
+
+/*************** 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(int num_states, tap_state_t *path)
+{
+       int i;
+
+       for (i = 0; i< num_states; i++)
+       {
+               if (tap_state_transition(tap_get_state(), false) == path[i])
+               {
+                       /* LOG_INFO("1"); */
+                       buspirate_tap_append(0, 0);
+               }
+               else if (tap_state_transition(tap_get_state(), true) == 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(path[i]));
+                       exit(-1);
+               }
+
+               tap_set_state(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, struct scan_command *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 */
+       struct scan_command *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_SHIFT; // 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
+
+       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;
+               struct scan_command *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,
struct scan_command *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_enable(int fd)
+{
+       int ret;
+       char tmp[21] = { [0 ... 20] = 0x00 };
+       int done = 0;
+       int cmd_sent = 0;
+
+       buspirate_serial_write(fd, tmp, 20);
+       usleep(10000);
+
+       // reads 1 to x "BBIO1" and one "OCD1"
+       while (!done)
+       {
+               ret = buspirate_serial_read(fd, tmp, 4);
+#ifdef DEBUG_SERIAL
+fprintf(stderr,"bytes read %i:\n", ret);
+buspirate_print_buffer(tmp, ret);
+#endif
+               if (ret != 4)
+               {
+                       LOG_ERROR("Buspirate did not respond :((
restart everything");
+                       exit(-1);
+               }
+               if (strncmp(tmp, "BBIO", 4)==0)
+               {
+                       ret = buspirate_serial_read(fd, tmp, 1);
+#ifdef DEBUG_SERIAL
+fprintf(stderr,"bytes read %i:\n", ret);
+buspirate_print_buffer(tmp, ret);
+#endif
+                       if (ret != 1) {
+                               LOG_ERROR("Buspirate did not respond
well :( restart everything");
+                               exit(-1);
+                       }
+                       if (tmp[0] != '1')
+                       {
+                               LOG_ERROR("Unsupported binary protocol ");
+                               exit(-1);
+                       }
+                       if (cmd_sent == 0)
+                       {
+                               cmd_sent = 1;
+                               tmp[0] = CMD_ENTER_OOCD;
+                               ret = buspirate_serial_write(fd, tmp, 1);
+#ifdef DEBUG_SERIAL
+fprintf(stderr,"bytes written %i:\n", ret);
+#endif
+                       }
+               }
+               else if (strncmp(tmp, "OCD1", 4) == 0)
+               {
+                       done = 1;
+               }
+               else
+               {
+                       LOG_ERROR("Buspirate did not respond :(((
restart everything");
+                       exit(-1);
+               }
+       }
+
+}
+
+static void buspirate_jtag_reset(int fd) {
+       int ret;
+       char tmp[5];
+
+       tmp[0] = 0x00; // exit OCD1 mode
+       buspirate_serial_write(fd, tmp, 1);
+       usleep(10000);
+       ret = buspirate_serial_read(fd, tmp, 5);
+       if (strncmp(tmp, "BBIO1", 5)==0)
+       {
+               tmp[0] = 0x0F; //  reset BP
+               buspirate_serial_write(fd, tmp, 1);
+       }
+       else
+       {
+               LOG_ERROR("Bad reply :( Please restart manually");
+       }
+
+}
+
+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("Buspirate switched to %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)
+{
+       uint8_t tmp[10];
+       uint16_t a,b,c,d;
+       tmp[0] = CMD_READ_ADCS;
+       buspirate_jtag_command(fd, (char*)tmp, 1);
+       a = tmp[2] << 8 | tmp[3];
+       b = tmp[4] << 8 | tmp[5];
+       c = tmp[6] << 8 | tmp[7];
+       d = tmp[8] << 8 | tmp[9];
+
+       LOG_INFO("ADC: ADC_Pin = %.02f VPullup = %.02f V33 = %.02f V50 = %.02f",
+               ((float)a)/155.1515, ((float)b)/155.1515, ((float)c)/155.1515,
((float)d)/155.1515);
+}
+
+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 = 10; // 2+2*4
+                               break;
+                       case CMD_TAP_SHIFT:
+                               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;
+}
+
+/* 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;
+       tcflush(buspirate_fd, TCIFLUSH);
+       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 --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
index f6d8219..8d13a08 100644
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -91,6 +91,9 @@ extern struct jtag_interface rlink_interface;
 #if BUILD_ARMJTAGEW == 1
 extern struct jtag_interface armjtagew_interface;
 #endif
+#if BUILD_BUSPIRATE == 1
+extern struct jtag_interface buspirate_interface;
+#endif
 #endif // standard drivers

 /**
@@ -151,6 +154,9 @@ struct jtag_interface *jtag_interfaces[] = {
 #if BUILD_ARMJTAGEW == 1
               &armjtagew_interface,
 #endif
+#if BUILD_BUSPIRATE == 1
+               &buspirate_interface,
+#endif
 #endif // standard drivers
               NULL,
       };
diff --git a/tcl/interface/buspirate.cfg b/tcl/interface/buspirate.cfg
new file mode 100644
index 0000000..6573c3d
--- /dev/null
+++ b/tcl/interface/buspirate.cfg
@@ -0,0 +1,16 @@
+#
+# Buspirate with OpenOCD support
+#
+# http://dangerousprototypes.com/category/bus-pirate/
+#
+
+interface buspirate
+buspirate_port /dev/ttyUSB0 # adjust to your needs
+buspirate_speed normal # or fast
+#buspirate_vreg 0 # or 1
+#buspirate_mode normal # or open-drain
+#buspirate_pullup 0 # or 1
+
+# this depends on the cable, you are safe with this option
+reset_config srst_only
+
--
1.6.6.1
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to