Index: configure.ac
===================================================================
--- configure.ac	(revision 2035)
+++ configure.ac	(working copy)
@@ -649,6 +654,7 @@
 	ea253
 	ei012
 	ft2232
+	ft232r
 	gpio
 	ice100
 	igloo
Index: include/urjtag/cable.h
===================================================================
--- include/urjtag/cable.h	(revision 2035)
+++ include/urjtag/cable.h	(working copy)
@@ -118,7 +118,8 @@
         URJ_TAP_CABLE_GET_TDO,
         URJ_TAP_CABLE_TRANSFER,
         URJ_TAP_CABLE_SET_SIGNAL,
-        URJ_TAP_CABLE_GET_SIGNAL
+        URJ_TAP_CABLE_GET_SIGNAL,
+        URJ_TAP_CABLE_DUMP
     } action;
     union
     {
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(revision 2035)
+++ po/POTFILES.in	(working copy)
@@ -113,6 +113,7 @@
 src/tap/cable/ea253.c
 src/tap/cable/ei012.c
 src/tap/cable/ft2232.c
+src/tap/cable/ft232r.c
 src/tap/cable/generic.c
 src/tap/cable/generic_parport.c
 src/tap/cable/generic_usbconn.c
Index: src/tap/Makefile.am
===================================================================
--- src/tap/Makefile.am	(revision 2035)
+++ src/tap/Makefile.am	(working copy)
@@ -129,6 +129,11 @@
 	cable/ft2232.c
 endif
 
+if ENABLE_CABLE_FT2232
+libtap_la_SOURCES += \
+	cable/ft232r.c
+endif
+
 if ENABLE_CABLE_TS7800
 libtap_la_SOURCES += \
 	cable/ts7800.c
Index: src/tap/cable/ft232r.c
===================================================================
--- src/tap/cable/ft232r.c	(revision 0)
+++ src/tap/cable/ft232r.c	(working copy)
@@ -0,0 +1,742 @@
+/*
+ * $Id: ft2232.c 2030 2012-09-19 12:38:50Z jiez $
+ *
+ * Generic cable driver for FTDI's FT2232C chip in MPSSE mode.
+ * Copyright (C) 2007 A. Laeuger
+ *
+ * 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.
+ *
+ * Written by Arnim Laeuger, 2007-2008.
+ * Support for JTAGkey submitted by Laurent Gauch, 2008.
+ * Support for FT2232H written by Michael Hennerich, 2009; adapted
+ *      for urjtag codebase and submitted by Adam Megacz, 2010.
+ *      for usbScarab2 and KT-LINK added by Tomasz CEDRO, 2010,2012.
+ * Adopted for FT232R by Ake Rehnman 2012.
+ */
+
+#include <sysdep.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <urjtag/cable.h>
+#include <urjtag/chain.h>
+#include <urjtag/cmd.h>
+
+#include "generic.h"
+#include "generic_usbconn.h"
+
+#include <urjtag/usbconn.h>
+#include "usbconn/libftdx.h"
+
+#include "cmd_xfer.h"
+
+#define FT232R_MAX_TCK_FREQ 6000000
+
+/* bit and bitmask definitions for GPIO commands */
+#define BIT_TCK         0
+#define BIT_TDI         1
+#define BIT_TDO         2
+#define BIT_TMS         3
+#define BITMASK_TDO     (1 << BIT_TDO)
+#define BITMASK_TDI     (1 << BIT_TDI)
+#define BITMASK_TCK     (1 << BIT_TCK)
+#define BITMASK_TMS     (1 << BIT_TMS)
+
+typedef struct
+{
+    // bitrate
+    uint32_t frequency;
+
+    /* variables to save last TDO value
+       this acts as a cache to prevent multiple "Read Data Bits Low" transfer
+       over USB for ft232r_get_tdo */
+    unsigned int last_tdo_valid;
+    unsigned int last_tdo;
+    int signals;
+
+    // number of bytes to discard before reading
+    int xferred;
+
+    urj_tap_cable_cx_cmd_root_t cmd_root;
+} params_t;
+
+
+static void
+ft232r_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
+{
+    params_t *params = cable->params;
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
+
+    if (!new_frequency || new_frequency > FT232R_MAX_TCK_FREQ)
+        new_frequency = FT232R_MAX_TCK_FREQ;
+
+    /* update ft232r frequency if cable setting changed */
+    if (new_frequency != params->frequency)
+    {
+        urj_tap_cable_cx_cmd_queue (cmd_root, 0);
+        urj_tap_cable_cx_cmd_push (cmd_root, 0xAA);
+        urj_tap_cable_cx_cmd_push (cmd_root, new_frequency & 0xff);
+        urj_tap_cable_cx_cmd_push (cmd_root, (new_frequency >> 8) & 0xff);
+        urj_tap_cable_cx_cmd_push (cmd_root, (new_frequency >> 16) & 0xff);
+        urj_tap_cable_cx_cmd_push (cmd_root, (new_frequency >> 24) & 0xff);
+        urj_tap_cable_cx_xfer (cmd_root, NULL, cable,
+                               URJ_TAP_CABLE_COMPLETELY);
+
+        params->frequency = new_frequency;
+        cable->frequency = new_frequency;
+    }
+//    urj_warning (_("Unable to change frequency for FT232\n"));
+}
+
+static int
+ft232r_generic_init (urj_cable_t *cable)
+{
+    params_t *params = cable->params;
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
+
+    if (urj_tap_usbconn_open (cable->link.usb) != URJ_STATUS_OK)
+        return URJ_STATUS_FAIL;
+
+    /* Set Data Bits Low Byte
+       TCK = 0, TMS = 1, TDI = 0 */
+
+    //keep track of how many xferred bytes to
+    //be able to discard unwanted bytes
+    params->xferred = 0;
+
+    urj_tap_cable_cx_cmd_queue (cmd_root, 0);
+    urj_tap_cable_cx_cmd_push (cmd_root, BITMASK_TMS);
+    params->xferred += 1;
+
+    params->signals = 0;
+    params->signals &= ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK);
+    params->signals |= (URJ_POD_CS_TMS);
+
+    params->last_tdo_valid = 0;
+
+    return URJ_STATUS_OK;
+}
+
+static void
+ft232r_generic_done (urj_cable_t *cable)
+{
+    urj_tap_cable_generic_usbconn_done (cable);
+}
+
+//
+// clock out n bits TMS=tms and TDI=tdi
+// if cmd queue is full it is transferred
+//
+static void
+ft232r_clock_schedule (urj_cable_t *cable, int tms, int tdi, int n)
+{
+    params_t *params = cable->params;
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
+    uint8_t data;
+
+    data = 0;
+    if (tdi) data |= BITMASK_TDI;
+    if (tms) data |= BITMASK_TMS;
+
+    urj_tap_cable_cx_cmd_queue (cmd_root, 0);
+    while (n > 0)
+    {
+        if (urj_tap_cable_cx_cmd_space
+            (cmd_root, URJ_USBCONN_FTDX_MAXSEND_MPSSE) < 2)
+        {
+            /* no space left for Clock Data plus Send Immediate
+               transfer queued commands to device and read receive data
+               to internal buffer */
+            urj_tap_cable_cx_xfer (cmd_root, NULL, cable,
+                                   URJ_TAP_CABLE_COMPLETELY);
+            urj_tap_cable_cx_cmd_queue (cmd_root, 0);
+        }
+
+        urj_tap_cable_cx_cmd_push (cmd_root, data); //TCK low
+        urj_tap_cable_cx_cmd_push (cmd_root, data | BITMASK_TCK); //TCK high
+        n--;
+        params->xferred += 2;
+
+        params->signals &= ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK);
+        if (data & BITMASK_TMS)
+            params->signals |= URJ_POD_CS_TMS;
+        if (data & BITMASK_TDI)
+            params->signals |= URJ_POD_CS_TDI;
+        params->signals |= URJ_POD_CS_TCK;
+        params->last_tdo_valid = 0;
+    }
+}
+
+//
+// clock out n clocks with tms and tdi
+// then xfer
+//
+static void
+ft232r_clock (urj_cable_t *cable, int tms, int tdi, int n)
+{
+    params_t *params = cable->params;
+
+    ft232r_clock_schedule (cable, tms, tdi, n);
+
+    urj_tap_cable_cx_xfer (&params->cmd_root, NULL, cable,
+                           URJ_TAP_CABLE_COMPLETELY);
+    params->last_tdo_valid = 0;
+}
+
+
+static void
+ft232r_get_tdo_schedule (urj_cable_t *cable)
+{
+    params_t *params = cable->params;
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
+    uint8_t data;
+
+    /* Read Data Bits Low Byte */
+    urj_tap_cable_cx_cmd_queue (cmd_root, 2);
+
+    data = 0;
+    if (params->signals & URJ_POD_CS_TMS) data |= BITMASK_TMS;
+    if (params->signals & URJ_POD_CS_TDI) data |= BITMASK_TDI;
+    if (params->signals & URJ_POD_CS_TCK) data |= BITMASK_TCK;
+
+    urj_tap_cable_cx_cmd_push (cmd_root, data);
+    urj_tap_cable_cx_cmd_push (cmd_root, data);
+}
+
+static void
+xfer_dump(urj_cable_t *cable, int n)
+{
+    int i;
+    uint8_t b;
+
+    if (n==0) return;
+
+    urj_log(URJ_LOG_LEVEL_COMM,"ft232r:xfer_dump : dumping %d chars\n",n);
+
+    for (i=0;i<n;i++)
+    {
+        b = urj_tap_cable_cx_xfer_recv (cable);
+        urj_log(URJ_LOG_LEVEL_COMM,"ft232r:xfer_dump : %d %02x\n",i,b);
+    }
+}
+
+static uint8_t
+xfer_recv(urj_cable_t *cable)
+{
+    uint8_t b;
+
+    b = urj_tap_cable_cx_xfer_recv (cable);
+
+    urj_log(URJ_LOG_LEVEL_COMM,"ft232r:xfer_recv : return %02x\n",b);
+
+    return b;
+}
+
+static int
+ft232r_get_tdo_finish (urj_cable_t *cable)
+{
+    params_t *params = cable->params;
+    uint8_t b;
+    int value;
+
+    b = xfer_recv (cable);
+    b = xfer_recv (cable);
+
+    value = (b & BITMASK_TDO) ? 1 : 0;
+
+    params->last_tdo = value;
+    params->last_tdo_valid = 1;
+
+    return value;
+}
+
+
+static int
+ft232r_get_tdo (urj_cable_t *cable)
+{
+    params_t *params = cable->params;
+
+    ft232r_get_tdo_schedule (cable);
+
+    urj_tap_cable_cx_xfer (&params->cmd_root, NULL, cable,
+                           URJ_TAP_CABLE_COMPLETELY);
+
+    xfer_dump(cable,params->xferred);
+    params->xferred = 0;
+
+    return ft232r_get_tdo_finish (cable);
+}
+
+
+static void
+ft232r_set_signal_schedule (params_t *params, int mask, int val,
+                            int set_low, int set_high)
+{
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
+
+    mask &= (URJ_POD_CS_TCK | URJ_POD_CS_TDI | URJ_POD_CS_TMS);
+    if (mask != 0)
+    {
+        int sigs = (params->signals & ~mask) | (val & mask);
+        uint8_t data = 0;
+        if (sigs & URJ_POD_CS_TCK)
+            data |= BITMASK_TCK;
+        if (sigs & URJ_POD_CS_TDI)
+            data |= BITMASK_TDI;
+        if (sigs & URJ_POD_CS_TMS)
+            data |= BITMASK_TMS;
+        urj_tap_cable_cx_cmd_queue (cmd_root, 0);
+        urj_tap_cable_cx_cmd_push (cmd_root, data);
+        params->xferred += 1;
+        params->signals = sigs;
+    }
+}
+
+
+static int
+ft232r_set_signal (urj_cable_t *cable, int mask, int val)
+{
+    params_t *params = cable->params;
+
+    int prev_sigs = params->signals;
+
+    ft232r_set_signal_schedule (params, mask, val, 1, 1);
+
+    urj_tap_cable_cx_xfer (&params->cmd_root, NULL, cable,
+                           URJ_TAP_CABLE_COMPLETELY);
+    params->last_tdo_valid = 0;
+
+    return prev_sigs;
+}
+
+
+static void
+ft232r_transfer_schedule (urj_cable_t *cable, int len, const char *in,
+                          char *out)
+{
+    params_t *params = cable->params;
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &params->cmd_root;
+
+    int i;
+    uint8_t data;
+
+    if (out)
+    {
+        urj_tap_cable_cx_cmd_queue (cmd_root, len*2);
+    }
+    else
+    {
+        urj_tap_cable_cx_cmd_queue (cmd_root, 0);
+        params->xferred += (len*2);
+    }
+
+    for (i=0;i<len;i++)
+    {
+      if (in[i]) data=BITMASK_TDI; else data = 0;
+      urj_tap_cable_cx_cmd_push (cmd_root, data); //clock is low;
+      urj_tap_cable_cx_cmd_push (cmd_root, data | BITMASK_TCK); //clock is high;
+
+      params->signals &= ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK);
+      if (data & BITMASK_TMS)
+        params->signals |= URJ_POD_CS_TMS;
+      if (data & BITMASK_TDI)
+        params->signals |= URJ_POD_CS_TDI;
+    }
+
+    if (out)
+    {
+        /* Read Data Bits Low Byte to get current TDO,
+           Do this only if we'll read out data nonetheless */
+
+        urj_tap_cable_cx_cmd_queue (cmd_root, 2);
+
+        data = 0;
+        if (params->signals & URJ_POD_CS_TMS) data |= BITMASK_TMS;
+        if (params->signals & URJ_POD_CS_TDI) data |= BITMASK_TDI;
+        if (params->signals & URJ_POD_CS_TCK) data |= BITMASK_TCK;
+
+        urj_tap_cable_cx_cmd_push (cmd_root, data);
+        urj_tap_cable_cx_cmd_push (cmd_root, data);
+        params->last_tdo_valid = 1;
+    }
+    else
+    {
+        params->last_tdo_valid = 0;
+    }
+}
+
+
+static int
+ft232r_transfer_finish (urj_cable_t *cable, int len, char *out)
+{
+    params_t *params = cable->params;
+    int i;
+    uint8_t b;
+
+    if (out)
+    {
+        for (i=0;i<len;i++)
+        {
+          b = xfer_recv (cable);
+          b = xfer_recv (cable);
+
+          urj_log(URJ_LOG_LEVEL_COMM,"ft232r:read tdo %x\n",b);
+          if (b & BITMASK_TDO) b = 1; else b=0;
+          out[i] = b;
+        }
+
+        /* gather current TDO */
+
+        b = xfer_recv (cable);
+        b = xfer_recv (cable);
+
+        params->last_tdo =
+            (b & BITMASK_TDO) ? 1 : 0;
+
+        urj_log(URJ_LOG_LEVEL_COMM,"ft232r:last tdo %d\n",params->last_tdo);
+        params->last_tdo_valid = 1;
+    }
+    else
+        params->last_tdo_valid = 0;
+
+    return 0;
+}
+
+
+static int
+ft232r_transfer (urj_cable_t *cable, int len, const char *in, char *out)
+{
+    params_t *params = cable->params;
+
+    ft232r_transfer_schedule (cable, len, in, out);
+
+    urj_tap_cable_cx_xfer (&params->cmd_root, NULL, cable,
+                           URJ_TAP_CABLE_COMPLETELY);
+
+    if (out)
+    {
+      xfer_dump(cable,params->xferred);
+      params->xferred = 0;
+    }
+    return ft232r_transfer_finish (cable, len, out);
+}
+
+static void
+ft232r_flush (urj_cable_t *cable, urj_cable_flush_amount_t how_much)
+{
+    params_t *params = cable->params;
+
+    if (how_much == URJ_TAP_CABLE_OPTIONALLY)
+        return;
+
+    if (cable->todo.num_items == 0)
+        urj_tap_cable_cx_xfer (&params->cmd_root, NULL, cable, how_much);
+
+    while (cable->todo.num_items > 0)
+    {
+        int i, j, n;
+        int post_signals = params->signals;
+        int last_tdo_valid_schedule = params->last_tdo_valid;
+        int last_tdo_valid_finish = params->last_tdo_valid;
+
+
+        for (j = i = cable->todo.next_item, n = 0; n < cable->todo.num_items;
+             n++)
+        {
+            int length;
+            int tdi;
+            int tms;
+
+            switch (cable->todo.data[i].action)
+            {
+            case URJ_TAP_CABLE_CLOCK:
+                   length = cable->todo.data[i].arg.clock.n;
+                   tms = cable->todo.data[i].arg.clock.tms ? 1 : 0;
+                   tdi = cable->todo.data[i].arg.clock.tdi ? 1 << 7 : 0;
+                   ft232r_clock_schedule (cable, tms, tdi, length);
+                   last_tdo_valid_schedule = 0;
+                   break;
+
+            case URJ_TAP_CABLE_GET_TDO:
+                if (!last_tdo_valid_schedule)
+                {
+                    ft232r_get_tdo_schedule (cable);
+                    last_tdo_valid_schedule = 1;
+                    //insert a CABLE_DUMP action
+                    int m = urj_tap_cable_add_queue_item (cable, &cable->todo);
+
+                    //gahh why isn't this a linked list????
+                    int p = m;
+                    for (int z=m; z!=i;)
+                    {
+                        if (--z<0) z+=cable->todo.max_items;
+                        cable->todo.data[p--] = cable->todo.data[z];
+                        if (p<0) p+=cable->todo.max_items;
+                    }
+
+                    // fill in the new data at current pos
+                    cable->todo.data[i].action = URJ_TAP_CABLE_DUMP;
+                    cable->todo.data[i].arg.transfer.len = params->xferred;
+                    params->xferred = 0;
+
+                    i++; if (i==cable->todo.max_items) i=0;
+                    n++;
+                }
+                break;
+
+            case URJ_TAP_CABLE_SET_SIGNAL:
+                ft232r_set_signal_schedule (params,
+                                            cable->todo.data[i].arg.value.
+                                            mask,
+                                            cable->todo.data[i].arg.value.val,
+                                            1, 1);
+                last_tdo_valid_schedule = 0;
+                break;
+
+            case URJ_TAP_CABLE_TRANSFER:
+                ft232r_transfer_schedule (cable,
+                                          cable->todo.data[i].arg.transfer.
+                                          len,
+                                          cable->todo.data[i].arg.transfer.in,
+                                          cable->todo.data[i].arg.transfer.
+                                          out);
+                last_tdo_valid_schedule = params->last_tdo_valid;
+                if (cable->todo.data[i].arg.transfer.out)
+                {
+                    //insert a CABLE_DUMP action
+                    int m = urj_tap_cable_add_queue_item (cable, &cable->todo);
+
+                    //gahh why isn't this a linked list????
+                    int p = m;
+                    for (int z=m; z!=i;)
+                    {
+                      if (--z<0) z+=cable->todo.max_items;
+                      cable->todo.data[p--] = cable->todo.data[z];
+                      if (p<0) p+=cable->todo.max_items;
+                    }
+
+                    // fill in the new data at current pos
+                    cable->todo.data[i].action = URJ_TAP_CABLE_DUMP;
+                    cable->todo.data[i].arg.transfer.len = params->xferred;
+                    params->xferred = 0;
+
+                    i++; if (i==cable->todo.max_items) i=0;
+                    n++;
+                }
+                break;
+
+            default:
+                break;
+            }
+
+            i++;
+            if (i >= cable->todo.max_items)
+                i = 0;
+        }
+
+        urj_tap_cable_cx_xfer (&params->cmd_root, NULL, cable, how_much);
+
+        while (j != i)
+        {
+            switch (cable->todo.data[j].action)
+            {
+            case URJ_TAP_CABLE_CLOCK:
+                {
+                    post_signals &=
+                        ~(URJ_POD_CS_TCK | URJ_POD_CS_TDI | URJ_POD_CS_TMS);
+                    post_signals |=
+                        (cable->todo.data[j].arg.clock.
+                         tms ? URJ_POD_CS_TMS : 0);
+                    post_signals |=
+                        (cable->todo.data[j].arg.clock.
+                         tdi ? URJ_POD_CS_TDI : 0);
+                    params->last_tdo_valid = last_tdo_valid_finish = 0;
+
+                    break;
+                }
+            case URJ_TAP_CABLE_GET_TDO:
+                {
+                    int tdo;
+                    int m;
+
+                    if (last_tdo_valid_finish)
+                        tdo = params->last_tdo;
+                    else
+                        tdo = ft232r_get_tdo_finish (cable);
+                    last_tdo_valid_finish = params->last_tdo_valid;
+                    m = urj_tap_cable_add_queue_item (cable, &cable->done);
+                    cable->done.data[m].action = URJ_TAP_CABLE_GET_TDO;
+                    cable->done.data[m].arg.value.val = tdo;
+                    break;
+                }
+            case URJ_TAP_CABLE_SET_SIGNAL:
+                {
+                    int m =
+                        urj_tap_cable_add_queue_item (cable, &cable->done);
+                    cable->done.data[m].action = URJ_TAP_CABLE_SET_SIGNAL;
+                    cable->done.data[m].arg.value.mask =
+                        cable->todo.data[j].arg.value.mask;
+                    cable->done.data[m].arg.value.val = post_signals;
+                    int mask =
+                        cable->todo.data[j].arg.value.
+                        mask & ~(URJ_POD_CS_TCK | URJ_POD_CS_TDI |
+                                 URJ_POD_CS_TMS | URJ_POD_CS_TRST |
+                                 URJ_POD_CS_RESET);
+                    post_signals =
+                        (post_signals & ~mask) | (cable->todo.data[j].arg.
+                                                  value.val & mask);
+                }
+            case URJ_TAP_CABLE_GET_SIGNAL:
+                {
+                    int m =
+                        urj_tap_cable_add_queue_item (cable, &cable->done);
+                    cable->done.data[m].action = URJ_TAP_CABLE_GET_SIGNAL;
+                    cable->done.data[m].arg.value.sig =
+                        cable->todo.data[j].arg.value.sig;
+                    cable->done.data[m].arg.value.val =
+                        (post_signals & cable->todo.data[j].arg.value.
+                         sig) ? 1 : 0;
+                    break;
+                }
+            case URJ_TAP_CABLE_TRANSFER:
+                {
+                    int r = ft232r_transfer_finish (cable,
+                                                    cable->todo.data[j].arg.
+                                                    transfer.len,
+                                                    cable->todo.data[j].arg.
+                                                    transfer.out);
+                    last_tdo_valid_finish = params->last_tdo_valid;
+                    free (cable->todo.data[j].arg.transfer.in);
+                    if (cable->todo.data[j].arg.transfer.out)
+                    {
+                        int m = urj_tap_cable_add_queue_item (cable,
+                                                              &cable->done);
+                        if (m < 0)
+                        {
+                            // retain error state
+                            // urj_log (URJ_LOG_LEVEL_NORMAL, "out of memory!\n");
+                        }
+                        cable->done.data[m].action = URJ_TAP_CABLE_TRANSFER;
+                        cable->done.data[m].arg.xferred.len =
+                            cable->todo.data[j].arg.transfer.len;
+                        cable->done.data[m].arg.xferred.res = r;
+                        cable->done.data[m].arg.xferred.out =
+                            cable->todo.data[j].arg.transfer.out;
+                    }
+                }
+                break;
+            case URJ_TAP_CABLE_DUMP:
+                xfer_dump(cable, cable->todo.data[j].arg.transfer.len);
+                break;
+            default:
+                break;
+            }
+
+            j++;
+            if (j >= cable->todo.max_items)
+                j = 0;
+            cable->todo.num_items--;
+        }
+
+        cable->todo.next_item = i;
+    }
+
+    if (params->xferred > 0)
+    {
+      urj_log(URJ_LOG_LEVEL_COMM,"ft232r: *****  ft232r_flush there are still %d bytes to dump. I dump them now.",params->xferred);
+      xfer_dump(cable, params->xferred);
+      params->xferred = 0;
+    }
+}
+
+
+static int
+ft232r_connect (urj_cable_t *cable, const urj_param_t *params[])
+{
+    params_t *cable_params;
+
+    /* perform urj_tap_cable_generic_usbconn_connect */
+    if (urj_tap_cable_generic_usbconn_connect (cable, params) != URJ_STATUS_OK)
+        return URJ_STATUS_FAIL;
+
+    cable_params = malloc (sizeof (*cable_params));
+    if (!cable_params)
+    {
+        urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("malloc(%zd) fails"),
+                       sizeof (*cable_params));
+        /* NOTE:
+         * Call the underlying usbport driver (*free) routine directly
+         * not urj_tap_cable_generic_usbconn_free() since it also free's cable->params
+         * (which is not established) and cable (which the caller will do)
+         */
+        cable->link.usb->driver->free (cable->link.usb);
+        return URJ_STATUS_FAIL;
+    }
+
+    cable_params->frequency = 0;
+    cable_params->last_tdo_valid = 0;
+
+    urj_tap_cable_cx_cmd_init (&cable_params->cmd_root);
+
+    /* exchange generic cable parameters with our private parameter set */
+    free (cable->params);
+    cable->params = cable_params;
+
+    return URJ_STATUS_OK;
+}
+
+
+static void
+ft232r_cable_free (urj_cable_t *cable)
+{
+    params_t *params = cable->params;
+
+    urj_tap_cable_cx_cmd_deinit (&params->cmd_root);
+
+    urj_tap_cable_generic_usbconn_free (cable);
+}
+
+
+static void
+ft232r_usbcable_help (urj_log_level_t ll, const char *cablename)
+{
+    const char *ex_short = "[driver=DRIVER]";
+    const char *ex_desc = "DRIVER     usbconn driver, either ftdi-syncbitbang or ftd2xx-syncbitbang\n";
+    urj_tap_cable_generic_usbconn_help_ex (ll, cablename, ex_short, ex_desc);
+}
+
+
+const urj_cable_driver_t urj_tap_cable_ft232r_driver = {
+    "FT232R",
+    N_("Generic FTDI FT232R Cable"),
+    URJ_CABLE_DEVICE_USB,
+    { .usb = ft232r_connect, },
+    urj_tap_cable_generic_disconnect,
+    ft232r_cable_free,
+    ft232r_generic_init,
+    ft232r_generic_done,
+    ft232r_set_frequency,
+    ft232r_clock,
+    ft232r_get_tdo,
+    ft232r_transfer,
+    ft232r_set_signal,
+    urj_tap_cable_generic_get_signal,
+    ft232r_flush,
+    ft232r_usbcable_help
+};
+URJ_DECLARE_FTDX_CABLE(0x0000, 0x0000, "-syncbitbang", "FT232R", ft232r)

Property changes on: src/tap/cable/ft232r.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
Index: src/tap/cable/generic_usbconn_list.h
===================================================================
--- src/tap/cable/generic_usbconn_list.h	(revision 2035)
+++ src/tap/cable/generic_usbconn_list.h	(working copy)
@@ -45,6 +45,7 @@
 #endif
 #ifdef ENABLE_CABLE_FT2232
 _URJ_USB_FTDX(ft2232)
+_URJ_USB_FTDX(ft232r)
 _URJ_USB_FTDX(armusbocd)
 _URJ_USB_FTDX(armusbocd_h)
 _URJ_USB_FTDX(armusbocdtiny)
Index: src/tap/cable_list.h
===================================================================
--- src/tap/cable_list.h	(revision 2035)
+++ src/tap/cable_list.h	(working copy)
@@ -47,6 +47,7 @@
 #endif
 #ifdef ENABLE_CABLE_FT2232
 _URJ_CABLE(ft2232)
+_URJ_CABLE(ft232r)
 _URJ_CABLE(ft2232_armusbocd)
 _URJ_CABLE(ft2232_armusbtiny_h)
 _URJ_CABLE(ft2232_flyswatter)
Index: src/tap/usbconn/libftd2xx.c
===================================================================
--- src/tap/usbconn/libftd2xx.c	(revision 2035)
+++ src/tap/usbconn/libftd2xx.c	(working copy)
@@ -293,6 +293,30 @@
     }
 }
 
+static int
+usbconn_ftd2xx_syncbitbang_write (urj_usbconn_t *conn, uint8_t *buf, int len, int recv)
+{
+    ftd2xx_param_t *p = conn->params;
+    uint32_t freq;
+    FT_STATUS status;
+
+    if (!p->fc)
+        return -1;
+   
+    //check if frequency change is requested
+    if ((len > 4) && buf[0]==0xAA)
+    {
+    	freq = (buf[1] | buf[2]<<8 | buf[3]<<16 | buf[4]<<24);
+    	if ((status=FT_SetBaudRate (p->fc, freq/5)) != FT_OK)
+    		   urj_error_set (URJ_ERROR_FTD, _("Can't set baudrate: %s"),
+                 ftd2xx_status_string(status));
+      buf = buf + 5;
+      len = len - 5;
+    }
+    
+   	return usbconn_ftd2xx_write(conn, buf, len, recv);
+}
+
 /* ---------------------------------------------------------------------- */
 
 static urj_usbconn_t *
@@ -371,7 +395,21 @@
     return conn;
 }
 
+/* ---------------------------------------------------------------------- */
 
+static urj_usbconn_t *
+usbconn_ftd2xx_syncbitbang_connect (urj_usbconn_cable_t *template,
+                        const urj_param_t *params[])
+{
+    urj_usbconn_t *conn = usbconn_ftd2xx_connect (template, params);
+
+    if (conn)
+        conn->driver = &urj_tap_usbconn_ftd2xx_syncbitbang_driver;
+
+    return conn;
+}
+
+
 /* ---------------------------------------------------------------------- */
 
 static int
@@ -559,6 +597,84 @@
 /* ---------------------------------------------------------------------- */
 
 static int
+usbconn_ftd2xx_syncbitbang_open (urj_usbconn_t *conn)
+{
+    ftd2xx_param_t *p = conn->params;
+    FT_HANDLE fc;
+    FT_STATUS status;
+
+    if (usbconn_ftd2xx_common_open (conn, URJ_LOG_LEVEL_NORMAL)
+        != URJ_STATUS_OK)
+        return URJ_STATUS_FAIL;
+
+    fc = p->fc;
+
+    /* This sequence might seem weird and containing superfluous stuff.
+       However, it's built after the description of JTAG_InitDevice
+       Ref. FTCJTAGPG10.pdf
+       Intermittent problems will occur when certain steps are skipped. */
+    if ((status = FT_ResetDevice (fc)) != FT_OK)
+        urj_error_set (URJ_ERROR_FTD, _("Can't reset device: %s"),
+                       ftd2xx_status_string(status));
+    if (status == FT_OK)
+        if ((status = FT_Purge (fc, FT_PURGE_RX)) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("s(): Can't purge RX buffer: %s"),
+                           ftd2xx_status_string(status));
+
+    if (status == FT_OK)
+        if ((status =
+             FT_SetUSBParameters (fc, URJ_USBCONN_FTDX_MAXSEND_MPSSE,
+                                  URJ_USBCONN_FTDX_MAXSEND_MPSSE)) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("Can't set USB parameters: %s"),
+                           ftd2xx_status_string(status));
+
+    if (status == FT_OK)
+        if ((status = FT_SetChars (fc, 0, 0, 0, 0)) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("Can't set special characters: %s"),
+                           ftd2xx_status_string(status));
+
+    /* set a reasonable latency timer value
+       if this value is too low then the chip will send intermediate result data
+       in short packets (suboptimal performance) */
+    if (status == FT_OK)
+        if ((status = FT_SetLatencyTimer (fc, 1)) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("Can't set target latency timer: %s"),
+                           ftd2xx_status_string(status));
+                           
+    if (status == FT_OK)
+        if ((status = FT_SetBaudRate (fc, 3E6)) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("Can't set baudrate: %s"),
+                           ftd2xx_status_string(status));
+                           
+                                                      
+    if (status == FT_OK)
+        if ((status =
+             FT_SetBitMode (fc, 0x0b, 0x05 /* BITMODE_sync_bitbang */ )) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("Can't set sync bitbang mode: %s"),
+                           ftd2xx_status_string(status));
+
+    if (status == FT_OK)
+        if ((status = FT_ResetDevice (fc)) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("Can't reset device: %s"),
+                           ftd2xx_status_string(status));
+    if (status == FT_OK)
+        if ((status = FT_Purge (fc, FT_PURGE_RX)) != FT_OK)
+            urj_error_set (URJ_ERROR_FTD, _("Can't purge RX buffer: %s"),
+                           ftd2xx_status_string(status));
+
+    if (status != FT_OK)
+    {
+        FT_Close (fc);
+        /* mark ftdi layer as not initialized */
+        p->fc = NULL;
+    }
+		
+    return status != FT_OK ? URJ_STATUS_FAIL : URJ_STATUS_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int
 usbconn_ftd2xx_close (urj_usbconn_t *conn)
 {
     ftd2xx_param_t *p = conn->params;
@@ -612,6 +728,15 @@
     usbconn_ftd2xx_write
 };
 
+const urj_usbconn_driver_t urj_tap_usbconn_ftd2xx_syncbitbang_driver = {
+    "ftd2xx-syncbitbang",
+    usbconn_ftd2xx_syncbitbang_connect,
+    usbconn_ftd2xx_free,
+    usbconn_ftd2xx_syncbitbang_open,
+    usbconn_ftd2xx_close,
+    usbconn_ftd2xx_read,
+    usbconn_ftd2xx_syncbitbang_write
+};
 
 /*
  Local Variables:
Index: src/tap/usbconn/libftdi.c
===================================================================
--- src/tap/usbconn/libftdi.c	(revision 2035)
+++ src/tap/usbconn/libftdi.c	(working copy)
@@ -268,6 +268,30 @@
     }
 }
 
+static int
+usbconn_ftdi_syncbitbang_write (urj_usbconn_t *conn, uint8_t *buf, int len, int recv)
+{
+    ftdi_param_t *p = conn->params;
+    uint32_t freq;
+    int status;
+
+    if (!p->fc)
+        return -1;
+   
+    //check if frequency change is requested
+    if ((len > 4) && buf[0]==0xAA)
+    {
+    	freq = (buf[1] | buf[2]<<8 | buf[3]<<16 | buf[4]<<24);
+    	if ((status=ftdi_set_baudrate(p->fc, freq)) < 0)
+            urj_error_set (URJ_ERROR_FTD, _("ftdi_set_baudrate() failed: %s"),
+                           ftdi_get_error_string (p->fc));
+      buf = buf + 5;
+      len = len - 5;
+    }
+    
+   	return usbconn_ftdi_write(conn, buf, len, recv);
+}
+
 /* ---------------------------------------------------------------------- */
 
 static urj_usbconn_t *
@@ -351,7 +375,18 @@
     return conn;
 }
 
+static urj_usbconn_t *
+usbconn_ftdi_syncbitbang_connect (urj_usbconn_cable_t *template,
+                            const urj_param_t *params[])
+{
+    urj_usbconn_t *conn = usbconn_ftdi_connect (template, params);
 
+    if (conn)
+        conn->driver = &urj_tap_usbconn_ftdi_syncbitbang_driver;
+
+    return conn;
+}
+
 /* ---------------------------------------------------------------------- */
 
 static int
@@ -619,6 +654,80 @@
 /* ---------------------------------------------------------------------- */
 
 static int
+usbconn_ftdi_syncbitbang_open (urj_usbconn_t *conn)
+{
+    ftdi_param_t *p = conn->params;
+    struct ftdi_context *fc = p->fc;
+    int r;
+
+    if (usbconn_ftdi_common_open (conn, URJ_LOG_LEVEL_NORMAL) != URJ_STATUS_OK)
+        return URJ_STATUS_FAIL;
+
+    /* This sequence might seem weird and containing superfluous stuff.
+       However, it's built after the description of JTAG_InitDevice
+       Ref. FTCJTAGPG10.pdf
+       Intermittent problems will occur when certain steps are skipped. */
+    r = seq_reset (fc);
+    if (r >= 0)
+        r = seq_purge (fc, 1, 0);
+
+    if (r >= 0)
+        if ((r =
+             ftdi_write_data_set_chunksize (fc,
+                                            URJ_USBCONN_FTDX_MAXSEND_MPSSE)) <
+            0)
+            urj_log (URJ_LOG_LEVEL_NORMAL, "%s", ftdi_get_error_string (fc));
+    if (r >= 0)
+        if ((r =
+             ftdi_read_data_set_chunksize (fc,
+                                           URJ_USBCONN_FTDX_MAXSEND_MPSSE)) <
+            0)
+            urj_log (URJ_LOG_LEVEL_NORMAL, "%s", ftdi_get_error_string (fc));
+
+#ifdef LIBFTDI_UNIMPLEMENTED
+    if (r >= 0)
+        if ((r = ftdi_set_event_char (fc, 0, 0)) < 0)
+            urj_log (URJ_LOG_LEVEL_NORMAL, "%s", ftdi_get_error_string (fc));
+    if (r >= 0)
+        if ((r = ftdi_set_error_char (fc, 0, 0)) < 0)
+            urj_log (URJ_LOG_LEVEL_NORMAL, "%s", ftdi_get_error_string (fc));
+#endif
+
+    /* set a reasonable latency timer value
+       if this value is too low then the chip will send intermediate result data
+       in short packets (suboptimal performance) */
+    if (r >= 0)
+        if ((r = ftdi_set_latency_timer (fc, 1)) < 0)
+            urj_error_set (URJ_ERROR_FTD,
+                           _("ftdi_set_latency_timer() failed: %s"),
+                           ftdi_get_error_string (fc));
+
+    if (r >= 0)
+        if ((r = ftdi_set_bitmode (fc, 0xfb, 0x05)) < 0)
+            urj_error_set (URJ_ERROR_FTD, _("ftdi_set_bitmode() failed: %s"),
+                           ftdi_get_error_string (fc));
+
+    if (r >= 0)
+        if ((r = ftdi_usb_reset (fc)) < 0)
+            urj_error_set (URJ_ERROR_FTD, _("ftdi_usb_reset() failed: %s"),
+                           ftdi_get_error_string (fc));
+    if (r >= 0)
+        r = seq_purge (fc, 1, 0);
+
+    if (r < 0)
+    {
+        ftdi_usb_close (fc);
+        ftdi_deinit (fc);
+        /* mark ftdi layer as not initialized */
+        p->fc = NULL;
+    }
+
+    return r < 0 ? URJ_STATUS_FAIL : URJ_STATUS_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int
 usbconn_ftdi_close (urj_usbconn_t *conn)
 {
     ftdi_param_t *p = conn->params;
@@ -675,6 +784,15 @@
     usbconn_ftdi_write
 };
 
+const urj_usbconn_driver_t urj_tap_usbconn_ftdi_syncbitbang_driver = {
+    "ftdi-syncbitbang",
+    usbconn_ftdi_syncbitbang_connect,
+    usbconn_ftdi_free,
+    usbconn_ftdi_syncbitbang_open,
+    usbconn_ftdi_close,
+    usbconn_ftdi_read,
+    usbconn_ftdi_syncbitbang_write
+};
 
 /*
  Local Variables:
Index: src/tap/usbconn_list.h
===================================================================
--- src/tap/usbconn_list.h	(revision 2035)
+++ src/tap/usbconn_list.h	(working copy)
@@ -30,10 +30,12 @@
 #ifdef ENABLE_LOWLEVEL_FTD2XX
 _URJ_LIST(ftd2xx)
 _URJ_LIST(ftd2xx_mpsse)
+_URJ_LIST(ftd2xx_syncbitbang)
 #endif
 #ifdef ENABLE_LOWLEVEL_FTDI
 _URJ_LIST(ftdi)
 _URJ_LIST(ftdi_mpsse)
+_URJ_LIST(ftdi_syncbitbang)
 #endif
 #ifdef HAVE_LIBUSB
 _URJ_LIST(libusb)
