OpenCores
URL https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [trunk/] [Software/] [adv_jtag_bridge/] [cable_ft2232.c] - Diff between revs 21 and 55

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 21 Rev 55
/* cable_ft2232.c - FT2232 based cable driver for the Advanced JTAG Bridge
/* cable_ft2232.c - FT2232 based cable driver for the Advanced JTAG Bridge
   Copyright (C) 2008 Arnim Laeuger, arniml@opencores.org
   Copyright (C) 2008 Arnim Laeuger, arniml@opencores.org
   Copyright (C) 2009 José Ignacio Villar, jose@dte.us.es
   Copyright (C) 2009 José Ignacio Villar, jose@dte.us.es
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
 
 
#include <time.h>
#include <time.h>
#include <sys/time.h>
#include <sys/time.h>
#include <fcntl.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdint.h>
#include <unistd.h>
#include <unistd.h>
#include <ftdi.h>
#include <ftdi.h>
 
 
#include "cable_ft2232.h"
#include "cable_ft2232.h"
#include "cable_common.h"
 
#include "errcodes.h"
#include "errcodes.h"
int debug = 0;
int debug = 0;
 
 
 
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
 
 
 
jtag_cable_t ft2232_cable_driver = {
 
    .name = "ft2232",
 
    .inout_func = NULL,
 
    .out_func = NULL,
 
    .init_func = cable_ftdi_init,
 
    .opt_func = cable_ftdi_opt,
 
    .bit_out_func = cable_ftdi_write_bit,
 
    .bit_inout_func = cable_ftdi_read_write_bit,
 
    .stream_out_func = cable_ftdi_write_stream,
 
    .stream_inout_func = cable_ftdi_read_stream,
 
    .flush_func = cable_ftdi_flush,
 
    .opts = "",
 
    .help = "no options\n",
 
};
 
 
 
usbconn_t * usbconn_ftdi_connect();
 
int my_ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size);
 
char *my_ftdi_get_error_string (struct ftdi_context *ftdi);
 
int my_ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size);
 
int my_ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, const char* description, const char* serial);
 
void my_ftdi_deinit(struct ftdi_context *ftdi);
 
int my_ftdi_usb_purge_buffers(struct ftdi_context *ftdi);
 
int my_ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi);
 
int my_ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi);
 
int my_ftdi_usb_reset(struct ftdi_context *ftdi);
 
int my_ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency);
 
int my_ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate);
 
int my_ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize);
 
int my_ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize);
 
int my_ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch, unsigned char enable);
 
int my_ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable);
 
int my_ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode);
 
int my_ftdi_usb_close(struct ftdi_context *ftdi);
 
 
static int usbconn_ftdi_common_open( usbconn_t *conn);
static int usbconn_ftdi_common_open( usbconn_t *conn);
static void usbconn_ftdi_free( usbconn_t *conn );
static void usbconn_ftdi_free( usbconn_t *conn );
static int seq_purge(struct ftdi_context *ftdic, int purge_rx, int purge_tx);
static int seq_purge(struct ftdi_context *ftdic, int purge_rx, int purge_tx);
static int seq_reset(struct ftdi_context *ftdic);
static int seq_reset(struct ftdi_context *ftdic);
static int usbconn_ftdi_flush( ftdi_param_t *params );
static int usbconn_ftdi_flush( ftdi_param_t *params );
static int usbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len );
static int usbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len );
static int usbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv );
static int usbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv );
static int usbconn_ftdi_mpsse_open( usbconn_t *conn );
static int usbconn_ftdi_mpsse_open( usbconn_t *conn );
static int usbconn_ftdi_close(usbconn_t *conn);
static int usbconn_ftdi_close(usbconn_t *conn);
 
 
usbconn_driver_t usbconn_ft2232_mpsse_driver = {
usbconn_driver_t usbconn_ft2232_mpsse_driver = {
        "ftdi-mpsse",
        "ftdi-mpsse",
        usbconn_ftdi_connect,
        usbconn_ftdi_connect,
        usbconn_ftdi_free,
        usbconn_ftdi_free,
        usbconn_ftdi_mpsse_open,
        usbconn_ftdi_mpsse_open,
        usbconn_ftdi_close,
        usbconn_ftdi_close,
        usbconn_ftdi_read,
        usbconn_ftdi_read,
        usbconn_ftdi_write
        usbconn_ftdi_write
};
};
 
 
usbconn_cable_t usbconn_ft2232_mpsse_CableID2= {
usbconn_cable_t usbconn_ft2232_mpsse_CableID2= {
  "CableID2",         /* cable name */
  "CableID2",         /* cable name */
  "CableID2",         /* string pattern, not used */
  "CableID2",         /* string pattern, not used */
  "ftdi-mpsse",       /* default usbconn driver */
  "ftdi-mpsse",       /* default usbconn driver */
  0x0403,             /* VID */
  0x0403,             /* VID */
  0x6010              /* PID */
  0x6010              /* PID */
};
};
 
 
static usbconn_t *ft2232_device;
static usbconn_t *ft2232_device;
 
 
 
 
 
 
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
/// libftdi wrappers for debugging purposes.
/// libftdi wrappers for debugging purposes.
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
 
 
void print_buffer(unsigned char *buf, int size) {
void print_buffer(unsigned char *buf, int size) {
        int i=0;
        int i=0;
        for(i=0; i<size; i++)
        for(i=0; i<size; i++)
                printf("[MYDBG]\tBUFFER[%d] = %02x\n", i, buf[i]);
                printf("[MYDBG]\tBUFFER[%d] = %02x\n", i, buf[i]);
 
 
}
}
 
 
int my_ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
int my_ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
        debug("[MYDBG] ftdi_write_data(ftdi, buf=BUFFER[%d], size=%d);\n", size, size);
        debug("[MYDBG] ftdi_write_data(ftdi, buf=BUFFER[%d], size=%d);\n", size, size);
        if(debug > 1) print_buffer(buf, size);
        if(debug > 1) print_buffer(buf, size);
        return ftdi_write_data(ftdi, buf, size);
        return ftdi_write_data(ftdi, buf, size);
}
}
 
 
char *my_ftdi_get_error_string (struct ftdi_context *ftdi) {
char *my_ftdi_get_error_string (struct ftdi_context *ftdi) {
        debug("[MYDBG] ftdi_get_error_string(ftdi);\n");
        debug("[MYDBG] ftdi_get_error_string(ftdi);\n");
        return ftdi_get_error_string (ftdi);
        return ftdi_get_error_string (ftdi);
}
}
 
 
int my_ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
int my_ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
        int ret = 0;
        int ret = 0;
        debug("[MYDBG] ftdi_read_data(ftdi, buf=BUFFER[%d], size=%d);\n", size, size);
        debug("[MYDBG] ftdi_read_data(ftdi, buf=BUFFER[%d], size=%d);\n", size, size);
        ret = ftdi_read_data(ftdi, buf, size);
        ret = ftdi_read_data(ftdi, buf, size);
        if(debug) print_buffer(buf, size);
        if(debug) print_buffer(buf, size);
        return ret;
        return ret;
}
}
 
 
int my_ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, const char* description, const char* serial) {
int my_ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, const char* description, const char* serial) {
        debug("[MYDBG] ftdi_usb_open_desc(ftdi, vendor=%d, product=%d, description=DESCRIPTION, serial=SERIAL);\n", vendor, product);
        debug("[MYDBG] ftdi_usb_open_desc(ftdi, vendor=%d, product=%d, description=DESCRIPTION, serial=SERIAL);\n", vendor, product);
        return ftdi_usb_open_desc(ftdi, vendor, product, description, serial);
        return ftdi_usb_open_desc(ftdi, vendor, product, description, serial);
}
}
 
 
void my_ftdi_deinit(struct ftdi_context *ftdi) {
void my_ftdi_deinit(struct ftdi_context *ftdi) {
        debug("[MYDBG] ftdi_deinit(ftdi);\n");
        debug("[MYDBG] ftdi_deinit(ftdi);\n");
        ftdi_deinit(ftdi);
        ftdi_deinit(ftdi);
}
}
 
 
int my_ftdi_usb_purge_buffers(struct ftdi_context *ftdi) {
int my_ftdi_usb_purge_buffers(struct ftdi_context *ftdi) {
        debug("[MYDBG] ftdi_usb_purge_buffers(ftdi);\n");
        debug("[MYDBG] ftdi_usb_purge_buffers(ftdi);\n");
        return ftdi_usb_purge_buffers(ftdi);
        return ftdi_usb_purge_buffers(ftdi);
}
}
 
 
int my_ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi) {
int my_ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi) {
        debug("[MYDBG] ftdi_usb_purge_rx_buffer(ftdi);\n");
        debug("[MYDBG] ftdi_usb_purge_rx_buffer(ftdi);\n");
        return ftdi_usb_purge_rx_buffer(ftdi);
        return ftdi_usb_purge_rx_buffer(ftdi);
}
}
 
 
int my_ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi) {
int my_ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi) {
        debug("[MYDBG] ftdi_usb_purge_tx_buffer(ftdi);\n");
        debug("[MYDBG] ftdi_usb_purge_tx_buffer(ftdi);\n");
        return ftdi_usb_purge_tx_buffer(ftdi);
        return ftdi_usb_purge_tx_buffer(ftdi);
}
}
 
 
int my_ftdi_usb_reset(struct ftdi_context *ftdi) {
int my_ftdi_usb_reset(struct ftdi_context *ftdi) {
        debug("[MYDBG] ftdi_usb_reset(ftdi);\n");
        debug("[MYDBG] ftdi_usb_reset(ftdi);\n");
        return ftdi_usb_reset(ftdi);
        return ftdi_usb_reset(ftdi);
}
}
 
 
int my_ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) {
int my_ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) {
        debug("[MYDBG] ftdi_set_latency_timer(ftdi, latency=0x%02x);\n", latency);
        debug("[MYDBG] ftdi_set_latency_timer(ftdi, latency=0x%02x);\n", latency);
        return ftdi_set_latency_timer(ftdi, latency);
        return ftdi_set_latency_timer(ftdi, latency);
}
}
 
 
int my_ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate) {
int my_ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate) {
        debug("[MYDBG] ftdi_set_baudrate(ftdi, baudrate=%d);\n", baudrate);
        debug("[MYDBG] ftdi_set_baudrate(ftdi, baudrate=%d);\n", baudrate);
        return ftdi_set_baudrate(ftdi, baudrate);
        return ftdi_set_baudrate(ftdi, baudrate);
}
}
 
 
int my_ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) {
int my_ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) {
        debug("[MYDBG] ftdi_read_data_set_chunksize(ftdi, chunksize=%u);\n", chunksize);
        debug("[MYDBG] ftdi_read_data_set_chunksize(ftdi, chunksize=%u);\n", chunksize);
        return ftdi_read_data_set_chunksize(ftdi, chunksize);
        return ftdi_read_data_set_chunksize(ftdi, chunksize);
}
}
 
 
int my_ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) {
int my_ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) {
        debug("[MYDBG] ftdi_write_data_set_chunksize(ftdi, chunksize=%u);\n", chunksize);
        debug("[MYDBG] ftdi_write_data_set_chunksize(ftdi, chunksize=%u);\n", chunksize);
        return ftdi_write_data_set_chunksize(ftdi, chunksize);
        return ftdi_write_data_set_chunksize(ftdi, chunksize);
}
}
 
 
int my_ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch, unsigned char enable) {
int my_ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch, unsigned char enable) {
        debug("[MYDBG] ftdi_set_event_char(ftdi, eventch=0x%02x, enable=0x%02x);\n", eventch, enable);
        debug("[MYDBG] ftdi_set_event_char(ftdi, eventch=0x%02x, enable=0x%02x);\n", eventch, enable);
        return ftdi_set_event_char(ftdi, eventch, enable);
        return ftdi_set_event_char(ftdi, eventch, enable);
}
}
 
 
int my_ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable) {
int my_ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable) {
        debug("[MYDBG] ftdi_set_error_char(ftdi, errorch=0x%02x, enable=0x%02x);\n", errorch, enable);
        debug("[MYDBG] ftdi_set_error_char(ftdi, errorch=0x%02x, enable=0x%02x);\n", errorch, enable);
        return ftdi_set_error_char(ftdi, errorch, enable);
        return ftdi_set_error_char(ftdi, errorch, enable);
}
}
 
 
int my_ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode) {
int my_ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode) {
        debug("[MYDBG] ftdi_set_bitmode(ftdi, bitmask=0x%02x, mode=0x%02x);\n", bitmask, mode);
        debug("[MYDBG] ftdi_set_bitmode(ftdi, bitmask=0x%02x, mode=0x%02x);\n", bitmask, mode);
        return ftdi_set_bitmode(ftdi, bitmask, mode);
        return ftdi_set_bitmode(ftdi, bitmask, mode);
}
}
 
 
int my_ftdi_usb_close(struct ftdi_context *ftdi) {
int my_ftdi_usb_close(struct ftdi_context *ftdi) {
        debug("[MYDBG] ftdi_usb_close(ftdi);\n");
        debug("[MYDBG] ftdi_usb_close(ftdi);\n");
        return ftdi_usb_close(ftdi);
        return ftdi_usb_close(ftdi);
}
}
 
 
 
 
 
 
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
/// USBconn FTDI MPSSE subsystem
/// USBconn FTDI MPSSE subsystem
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
 
 
 
 
static int usbconn_ftdi_common_open(usbconn_t *conn) {
static int usbconn_ftdi_common_open(usbconn_t *conn) {
        ftdi_param_t *params = conn->params;
        ftdi_param_t *params = conn->params;
        struct ftdi_context * ftdic = params->ftdic;
        struct ftdi_context * ftdic = params->ftdic;
        int error;
        int error;
 
 
        printf("Initializing USB device\n");
        printf("Initializing USB device\n");
 
 
        if ((error = my_ftdi_usb_open_desc(ftdic, conn->cable->vid, conn->cable->pid, NULL, NULL))) {
        if ((error = my_ftdi_usb_open_desc(ftdic, conn->cable->vid, conn->cable->pid, NULL, NULL))) {
                if      (error == -1) printf("usb_find_busses() failed\n");
                if      (error == -1) printf("usb_find_busses() failed\n");
                else if (error == -2) printf("usb_find_devices() failed\n");
                else if (error == -2) printf("usb_find_devices() failed\n");
                else if (error == -3) printf("usb device not found\n");
                else if (error == -3) printf("usb device not found\n");
                else if (error == -4) printf("unable to open device\n");
                else if (error == -4) printf("unable to open device\n");
                else if (error == -5) printf("unable to claim device\n");
                else if (error == -5) printf("unable to claim device\n");
                else if (error == -6) printf("reset failed\n");
                else if (error == -6) printf("reset failed\n");
                else if (error == -7) printf("set baudrate failed\n");
                else if (error == -7) printf("set baudrate failed\n");
                else if (error == -8) printf("get product description failed\n");
                else if (error == -8) printf("get product description failed\n");
                else if (error == -9) printf("get serial number failed\n");
                else if (error == -9) printf("get serial number failed\n");
                else if (error == -10) printf("unable to close device\n");
                else if (error == -10) printf("unable to close device\n");
 
 
                my_ftdi_deinit(ftdic);
                my_ftdi_deinit(ftdic);
                ftdic = NULL;
                ftdic = NULL;
 
 
                printf("Can't open FTDI usb device\n");
                printf("Can't open FTDI usb device\n");
                return(-1);
                return(-1);
        }
        }
 
 
        return 0;
        return 0;
}
}
 
 
static int seq_purge(struct ftdi_context *ftdic, int purge_rx, int purge_tx) {
static int seq_purge(struct ftdi_context *ftdic, int purge_rx, int purge_tx) {
        int r = 0;
        int r = 0;
        unsigned char buf;
        unsigned char buf;
 
 
        if ((r = my_ftdi_usb_purge_buffers( ftdic )) < 0)
        if ((r = my_ftdi_usb_purge_buffers( ftdic )) < 0)
                printf("my_ftdi_usb_purge_buffers() failed\n");
                printf("my_ftdi_usb_purge_buffers() failed\n");
        if (r >= 0) if ((r = my_ftdi_read_data( ftdic, &buf, 1 )) < 0)
        if (r >= 0) if ((r = my_ftdi_read_data( ftdic, &buf, 1 )) < 0)
                printf("my_ftdi_read_data() failed\n");
                printf("my_ftdi_read_data() failed\n");
 
 
        return r < 0 ? -1 : 0;
        return r < 0 ? -1 : 0;
}
}
 
 
static int seq_reset(struct ftdi_context *ftdic) {
static int seq_reset(struct ftdi_context *ftdic) {
 
 
        if (my_ftdi_usb_reset( ftdic ) < 0) {
        if (my_ftdi_usb_reset( ftdic ) < 0) {
                printf("my_ftdi_usb_reset() failed\n");
                printf("my_ftdi_usb_reset() failed\n");
                return -1;
                return -1;
        }
        }
 
 
        if(seq_purge(ftdic, 1, 1) < 0)
        if(seq_purge(ftdic, 1, 1) < 0)
                return -1;
                return -1;
 
 
        return 0;
        return 0;
}
}
 
 
static int usbconn_ftdi_flush( ftdi_param_t *params )
static int usbconn_ftdi_flush( ftdi_param_t *params )
        {
        {
        int xferred;
        int xferred;
        int recvd = 0;
        int recvd = 0;
 
 
        if (!params->ftdic)
        if (!params->ftdic)
                return -1;
                return -1;
 
 
        if (params->send_buffered == 0)
        if (params->send_buffered == 0)
                return 0;
                return 0;
 
 
        if ((xferred = my_ftdi_write_data( params->ftdic, params->send_buf, params->send_buffered )) < 0)
        if ((xferred = my_ftdi_write_data( params->ftdic, params->send_buf, params->send_buffered )) < 0)
                printf("my_ftdi_write_data() failed\n");
                printf("my_ftdi_write_data() failed\n");
 
 
        if (xferred < params->send_buffered) {
        if (xferred < params->send_buffered) {
                printf("Written fewer bytes than requested.\n");
                printf("Written fewer bytes than requested.\n");
                return -1;
                return -1;
        }
        }
 
 
        params->send_buffered = 0;
        params->send_buffered = 0;
 
 
        /* now read all scheduled receive bytes */
        /* now read all scheduled receive bytes */
        if (params->to_recv) {
        if (params->to_recv) {
                if (params->recv_write_idx + params->to_recv > params->recv_buf_len) {
                if (params->recv_write_idx + params->to_recv > params->recv_buf_len) {
                        /* extend receive buffer */
                        /* extend receive buffer */
                        params->recv_buf_len = params->recv_write_idx + params->to_recv;
                        params->recv_buf_len = params->recv_write_idx + params->to_recv;
                        if (params->recv_buf)
                        if (params->recv_buf)
                                params->recv_buf = (uint8_t *)realloc( params->recv_buf, params->recv_buf_len );
                                params->recv_buf = (uint8_t *)realloc( params->recv_buf, params->recv_buf_len );
                }
                }
 
 
                if (!params->recv_buf) {
                if (!params->recv_buf) {
                        printf("Receive buffer does not exist.\n");
                        printf("Receive buffer does not exist.\n");
                        return -1;
                        return -1;
                }
                }
 
 
                while (recvd == 0)
                while (recvd == 0)
                        if ((recvd = my_ftdi_read_data( params->ftdic, &(params->recv_buf[params->recv_write_idx]), params->to_recv )) < 0)
                        if ((recvd = my_ftdi_read_data( params->ftdic, &(params->recv_buf[params->recv_write_idx]), params->to_recv )) < 0)
                                printf("Error from my_ftdi_read_data()\n");
                                printf("Error from my_ftdi_read_data()\n");
 
 
                if (recvd < params->to_recv)
                if (recvd < params->to_recv)
                        printf("Received less bytes than requested.\n");
                        printf("Received less bytes than requested.\n");
 
 
                params->to_recv -= recvd;
                params->to_recv -= recvd;
                params->recv_write_idx += recvd;
                params->recv_write_idx += recvd;
        }
        }
 
 
        debug("[MYDBG] FLUSHING xferred=%u\n", xferred);
        debug("[MYDBG] FLUSHING xferred=%u\n", xferred);
        return xferred < 0 ? -1 : xferred;
        return xferred < 0 ? -1 : xferred;
}
}
 
 
static int usbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len ) {
static int usbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len ) {
        ftdi_param_t *params = conn->params;
        ftdi_param_t *params = conn->params;
        int cpy_len;
        int cpy_len;
        int recvd = 0;
        int recvd = 0;
 
 
        if (!params->ftdic)
        if (!params->ftdic)
                return -1;
                return -1;
 
 
        /* flush send buffer to get all scheduled receive bytes */
        /* flush send buffer to get all scheduled receive bytes */
        if (usbconn_ftdi_flush( params ) < 0)
        if (usbconn_ftdi_flush( params ) < 0)
                return -1;
                return -1;
 
 
        if (len == 0)
        if (len == 0)
                return 0;
                return 0;
 
 
        /* check for number of remaining bytes in receive buffer */
        /* check for number of remaining bytes in receive buffer */
        cpy_len = params->recv_write_idx - params->recv_read_idx;
        cpy_len = params->recv_write_idx - params->recv_read_idx;
        if (cpy_len > len)
        if (cpy_len > len)
                cpy_len = len;
                cpy_len = len;
        len -= cpy_len;
        len -= cpy_len;
 
 
        if (cpy_len > 0) {
        if (cpy_len > 0) {
                /* get data from the receive buffer */
                /* get data from the receive buffer */
                memcpy( buf, &(params->recv_buf[params->recv_read_idx]), cpy_len );
                memcpy( buf, &(params->recv_buf[params->recv_read_idx]), cpy_len );
                params->recv_read_idx += cpy_len;
                params->recv_read_idx += cpy_len;
                if (params->recv_read_idx == params->recv_write_idx)
                if (params->recv_read_idx == params->recv_write_idx)
                        params->recv_read_idx = params->recv_write_idx = 0;
                        params->recv_read_idx = params->recv_write_idx = 0;
        }
        }
 
 
        if (len > 0) {
        if (len > 0) {
                /* need to get more data directly from the device */
                /* need to get more data directly from the device */
                while (recvd == 0)
                while (recvd == 0)
                        if ((recvd = my_ftdi_read_data( params->ftdic, &(buf[cpy_len]), len )) < 0)
                        if ((recvd = my_ftdi_read_data( params->ftdic, &(buf[cpy_len]), len )) < 0)
                                printf("Error from my_ftdi_read_data()\n");
                                printf("Error from my_ftdi_read_data()\n");
        }
        }
        debug("[MYDBG] READ cpy_len=%u ; len=%u\n", cpy_len, len);
        debug("[MYDBG] READ cpy_len=%u ; len=%u\n", cpy_len, len);
        return recvd < 0 ? -1 : cpy_len + len;
        return recvd < 0 ? -1 : cpy_len + len;
}
}
 
 
static int usbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv ) {
static int usbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv ) {
 
 
        ftdi_param_t *params = conn->params;
        ftdi_param_t *params = conn->params;
        int xferred = 0;
        int xferred = 0;
 
 
        if (!params->ftdic)
        if (!params->ftdic)
                return -1;
                return -1;
 
 
        /* this write function will try to buffer write data
        /* this write function will try to buffer write data
           buffering will be ceased and a flush triggered in two cases. */
           buffering will be ceased and a flush triggered in two cases. */
 
 
        /* Case A: max number of scheduled receive bytes will be exceeded
        /* Case A: max number of scheduled receive bytes will be exceeded
           with this write
           with this write
           Case B: max number of scheduled send bytes has been reached */
           Case B: max number of scheduled send bytes has been reached */
        if ((params->to_recv + recv > FTDI_MAXRECV) || ((params->send_buffered > FTDX_MAXSEND) && (params->to_recv == 0)))
        if ((params->to_recv + recv > FTDI_MAXRECV) || ((params->send_buffered > FTDX_MAXSEND) && (params->to_recv == 0)))
                xferred = usbconn_ftdi_flush(params);
                xferred = usbconn_ftdi_flush(params);
 
 
        if (xferred < 0)
        if (xferred < 0)
                return -1;
                return -1;
 
 
        /* now buffer this write */
        /* now buffer this write */
        if (params->send_buffered + len > params->send_buf_len) {
        if (params->send_buffered + len > params->send_buf_len) {
                params->send_buf_len = params->send_buffered + len;
                params->send_buf_len = params->send_buffered + len;
                if (params->send_buf)
                if (params->send_buf)
                        params->send_buf = (uint8_t *)realloc( params->send_buf, params->send_buf_len);
                        params->send_buf = (uint8_t *)realloc( params->send_buf, params->send_buf_len);
        }
        }
 
 
        if (params->send_buf) {
        if (params->send_buf) {
                memcpy( &(params->send_buf[params->send_buffered]), buf, len );
                memcpy( &(params->send_buf[params->send_buffered]), buf, len );
                params->send_buffered += len;
                params->send_buffered += len;
                if (recv > 0)
                if (recv > 0)
                        params->to_recv += recv;
                        params->to_recv += recv;
 
 
                if (recv < 0) {
                if (recv < 0) {
                        /* immediate write requested, so flush the buffered data */
                        /* immediate write requested, so flush the buffered data */
                        xferred = usbconn_ftdi_flush( params );
                        xferred = usbconn_ftdi_flush( params );
                }
                }
 
 
                debug("[MYDBG] WRITE inmediate=%s ; xferred=%u ; len=%u\n", ((recv < 0) ? "TRUE" : "FALSE"), xferred, len);
                debug("[MYDBG] WRITE inmediate=%s ; xferred=%u ; len=%u\n", ((recv < 0) ? "TRUE" : "FALSE"), xferred, len);
                return xferred < 0 ? -1 : len;
                return xferred < 0 ? -1 : len;
        }
        }
        else {
        else {
                printf("Send buffer does not exist.\n");
                printf("Send buffer does not exist.\n");
                return -1;
                return -1;
        }
        }
}
}
 
 
static int usbconn_ftdi_mpsse_open( usbconn_t *conn ) {
static int usbconn_ftdi_mpsse_open( usbconn_t *conn ) {
        ftdi_param_t *params = conn->params;
        ftdi_param_t *params = conn->params;
        struct ftdi_context *ftdic = params->ftdic;
        struct ftdi_context *ftdic = params->ftdic;
 
 
        int r = 0;
        int r = 0;
 
 
        if (usbconn_ftdi_common_open(conn) < 0) {
        if (usbconn_ftdi_common_open(conn) < 0) {
                printf("Connection failed\n");
                printf("Connection failed\n");
                return -1;
                return -1;
        }
        }
 
 
        /* This sequence might seem weird and containing superfluous stuff.
        /* This sequence might seem weird and containing superfluous stuff.
           However, it's built after the description of JTAG_InitDevice
           However, it's built after the description of JTAG_InitDevice
           Ref. FTCJTAGPG10.pdf
           Ref. FTCJTAGPG10.pdf
           Intermittent problems will occur when certain steps are skipped. */
           Intermittent problems will occur when certain steps are skipped. */
 
 
        r = seq_reset( ftdic );
        r = seq_reset( ftdic );
        if (r >= 0)
        if (r >= 0)
                r = seq_purge( ftdic, 1, 0 );
                r = seq_purge( ftdic, 1, 0 );
 
 
        if (r >= 0)
        if (r >= 0)
                if ((r = my_ftdi_write_data_set_chunksize( ftdic, FTDX_MAXSEND_MPSSE )) < 0)
                if ((r = my_ftdi_write_data_set_chunksize( ftdic, FTDX_MAXSEND_MPSSE )) < 0)
                        puts( my_ftdi_get_error_string( ftdic ) );
                        puts( my_ftdi_get_error_string( ftdic ) );
 
 
        if (r >= 0)
        if (r >= 0)
                if ((r = my_ftdi_read_data_set_chunksize( ftdic, FTDX_MAXSEND_MPSSE )) < 0)
                if ((r = my_ftdi_read_data_set_chunksize( ftdic, FTDX_MAXSEND_MPSSE )) < 0)
                        puts( my_ftdi_get_error_string( ftdic ) );
                        puts( my_ftdi_get_error_string( ftdic ) );
 
 
        /* set a reasonable latency timer value
        /* set a reasonable latency timer value
           if this value is too low then the chip will send intermediate result data
           if this value is too low then the chip will send intermediate result data
           in short packets (suboptimal performance) */
           in short packets (suboptimal performance) */
        if (r >= 0)
        if (r >= 0)
                if ((r = my_ftdi_set_latency_timer( ftdic, 16 )) < 0)
                if ((r = my_ftdi_set_latency_timer( ftdic, 16 )) < 0)
                        printf("my_ftdi_set_latency_timer() failed\n");
                        printf("my_ftdi_set_latency_timer() failed\n");
 
 
        if (r >= 0)
        if (r >= 0)
                if ((r = my_ftdi_set_bitmode( ftdic, 0x0b, BITMODE_MPSSE )) < 0)
                if ((r = my_ftdi_set_bitmode( ftdic, 0x0b, BITMODE_MPSSE )) < 0)
                        printf("my_ftdi_set_bitmode() failed\n");
                        printf("my_ftdi_set_bitmode() failed\n");
 
 
        if (r >= 0)
        if (r >= 0)
                if ((r = my_ftdi_usb_reset( ftdic )) < 0)
                if ((r = my_ftdi_usb_reset( ftdic )) < 0)
                        printf("my_ftdi_usb_reset() failed\n");
                        printf("my_ftdi_usb_reset() failed\n");
 
 
        if (r >= 0)
        if (r >= 0)
                r = seq_purge( ftdic, 1, 0 );
                r = seq_purge( ftdic, 1, 0 );
 
 
        /* set TCK Divisor */
        /* set TCK Divisor */
        if (r >= 0) {
        if (r >= 0) {
                uint8_t buf[3] = {TCK_DIVISOR, 0x00, 0x00};
                uint8_t buf[3] = {TCK_DIVISOR, 0x00, 0x00};
                r = usbconn_ftdi_write( conn, buf, 3, 0 );
                r = usbconn_ftdi_write( conn, buf, 3, 0 );
        }
        }
 
 
        /* switch off loopback */
        /* switch off loopback */
        if (r >= 0) {
        if (r >= 0) {
                uint8_t buf[1] = {LOOPBACK_END};
                uint8_t buf[1] = {LOOPBACK_END};
                r = usbconn_ftdi_write( conn, buf, 1, 0 );
                r = usbconn_ftdi_write( conn, buf, 1, 0 );
        }
        }
 
 
        if (r >= 0)
        if (r >= 0)
                r = usbconn_ftdi_read( conn, NULL, 0 );
                r = usbconn_ftdi_read( conn, NULL, 0 );
 
 
        if (r >= 0)
        if (r >= 0)
                if ((r = my_ftdi_usb_reset( ftdic )) < 0)
                if ((r = my_ftdi_usb_reset( ftdic )) < 0)
                        printf("my_ftdi_usb_reset() failed\n");
                        printf("my_ftdi_usb_reset() failed\n");
 
 
        if (r >= 0)
        if (r >= 0)
                r = seq_purge( ftdic, 1, 0 );
                r = seq_purge( ftdic, 1, 0 );
 
 
        if (r < 0) {
        if (r < 0) {
                ftdi_usb_close( ftdic );
                ftdi_usb_close( ftdic );
                ftdi_deinit( ftdic );
                ftdi_deinit( ftdic );
                /* mark ftdi layer as not initialized */
                /* mark ftdi layer as not initialized */
                params->ftdic = NULL;
                params->ftdic = NULL;
        }
        }
 
 
        return r < 0 ? -1 : 0;
        return r < 0 ? -1 : 0;
}
}
 
 
static int usbconn_ftdi_close(usbconn_t *conn) {
static int usbconn_ftdi_close(usbconn_t *conn) {
        ftdi_param_t *params = conn->params;
        ftdi_param_t *params = conn->params;
 
 
        if (params->ftdic) {
        if (params->ftdic) {
                my_ftdi_usb_close(params->ftdic);
                my_ftdi_usb_close(params->ftdic);
                my_ftdi_deinit(params->ftdic);
                my_ftdi_deinit(params->ftdic);
                params->ftdic = NULL;
                params->ftdic = NULL;
        }
        }
 
 
        return 0;
        return 0;
}
}
 
 
static void usbconn_ftdi_free( usbconn_t *conn )
static void usbconn_ftdi_free( usbconn_t *conn )
{
{
  ftdi_param_t *params = conn->params;
  ftdi_param_t *params = conn->params;
 
 
  if (params->send_buf) free( params->send_buf );
  if (params->send_buf) free( params->send_buf );
  if (params->recv_buf) free( params->recv_buf );
  if (params->recv_buf) free( params->recv_buf );
  if (params->ftdic)    free( params->ftdic );
  if (params->ftdic)    free( params->ftdic );
  if (params->serial)   free( params->serial );
  if (params->serial)   free( params->serial );
 
 
  free( conn->params );
  free( conn->params );
  free( conn );
  free( conn );
}
}
 
 
usbconn_t * usbconn_ftdi_connect() {
usbconn_t * usbconn_ftdi_connect() {
 
 
        usbconn_t *conn            = malloc( sizeof( usbconn_t ) );
        usbconn_t *conn            = malloc( sizeof( usbconn_t ) );
        ftdi_param_t *params       = malloc( sizeof( ftdi_param_t ) );
        ftdi_param_t *params       = malloc( sizeof( ftdi_param_t ) );
        struct ftdi_context *ftdic = malloc( sizeof( struct ftdi_context ) );
        struct ftdi_context *ftdic = malloc( sizeof( struct ftdi_context ) );
 
 
        if (params) {
        if (params) {
                params->send_buf_len   = FTDX_MAXSEND;
                params->send_buf_len   = FTDX_MAXSEND;
                params->send_buffered  = 0;
                params->send_buffered  = 0;
                params->send_buf       = (uint8_t *) malloc( params->send_buf_len );
                params->send_buf       = (uint8_t *) malloc( params->send_buf_len );
                params->recv_buf_len   = FTDI_MAXRECV;
                params->recv_buf_len   = FTDI_MAXRECV;
                params->to_recv        = 0;
                params->to_recv        = 0;
                params->recv_write_idx = 0;
                params->recv_write_idx = 0;
                params->recv_read_idx  = 0;
                params->recv_read_idx  = 0;
                params->recv_buf       = (uint8_t *) malloc( params->recv_buf_len );
                params->recv_buf       = (uint8_t *) malloc( params->recv_buf_len );
        }
        }
 
 
        if (!conn || !params || !ftdic || !params->send_buf || !params->recv_buf) {
        if (!conn || !params || !ftdic || !params->send_buf || !params->recv_buf) {
                printf("Can't allocate memory for ftdi context structures\n");
                printf("Can't allocate memory for ftdi context structures\n");
 
 
                if (conn) free( conn );
                if (conn) free( conn );
                if (params) free( params );
                if (params) free( params );
                if (ftdic) free( ftdic );
                if (ftdic) free( ftdic );
                if (params->send_buf) free( params->send_buf );
                if (params->send_buf) free( params->send_buf );
                if (params->recv_buf) free( params->recv_buf );
                if (params->recv_buf) free( params->recv_buf );
                return NULL;
                return NULL;
        }
        }
 
 
        conn->driver = &usbconn_ft2232_mpsse_driver;
        conn->driver = &usbconn_ft2232_mpsse_driver;
        conn->cable  = &usbconn_ft2232_mpsse_CableID2;
        conn->cable  = &usbconn_ft2232_mpsse_CableID2;
 
 
        ftdi_init( ftdic );
        ftdi_init( ftdic );
        params->ftdic  = ftdic;
        params->ftdic  = ftdic;
        params->pid    = conn->cable->pid;
        params->pid    = conn->cable->pid;
        params->vid    = conn->cable->vid;
        params->vid    = conn->cable->vid;
        params->serial = NULL;
        params->serial = NULL;
 
 
        conn->params = params;
        conn->params = params;
 
 
        printf("Structs successfully initialized\n");
        printf("Structs successfully initialized\n");
 
 
        /* do a test open with the specified cable paramters,
        /* do a test open with the specified cable paramters,
           alternatively we could use libusb to detect the presence of the
           alternatively we could use libusb to detect the presence of the
           specified USB device         */
           specified USB device         */
        if (usbconn_ftdi_common_open(conn) != 0) {
        if (usbconn_ftdi_common_open(conn) != 0) {
                printf("Connection failed\n");
                printf("Connection failed\n");
                usbconn_ftdi_free(conn);
                usbconn_ftdi_free(conn);
                printf("Freeing structures.\n");
                printf("Freeing structures.\n");
                return NULL;
                return NULL;
        }
        }
 
 
        my_ftdi_usb_close( ftdic );
        my_ftdi_usb_close( ftdic );
 
 
        printf("Connected to libftdi driver.\n");
        printf("Connected to libftdi driver.\n");
 
 
        return conn;
        return conn;
}
}
 
 
 
 
 
 
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
/// High level functions to generate Tx/Rx commands
/// High level functions to generate Tx/Rx commands
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
 
 
int cable_ft2232_write_bytes(usbconn_t *conn, unsigned char *buf, int len, int postread) {
int cable_ft2232_write_bytes(usbconn_t *conn, unsigned char *buf, int len, int postread) {
 
 
        int cur_command_size;
        int cur_command_size;
        int max_command_size;
        int max_command_size;
        int cur_chunk_len;
        int cur_chunk_len;
        int recv;
        int recv;
        int xferred;
        int xferred;
        int i;
        int i;
        unsigned char *mybuf;
        unsigned char *mybuf;
 
 
        if(len == 0)
        if(len == 0)
                return 0;
                return 0;
        debug("write_bytes(length=%d, postread=%s)\n", len, ((postread > 0) ? "TRUE" : "FALSE"));
        debug("write_bytes(length=%d, postread=%s)\n", len, ((postread > 0) ? "TRUE" : "FALSE"));
        recv = 0;
        recv = 0;
        max_command_size = min(len, 65536)+3;
        max_command_size = min(len, 65536)+3;
        mybuf = (unsigned char *) malloc( max_command_size );
        mybuf = (unsigned char *) malloc( max_command_size );
 
 
        /// Command OPCODE: write bytes
        /// Command OPCODE: write bytes
        mybuf[0] = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_WRITE_NEG;
        mybuf[0] = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_WRITE_NEG;
        if(postread) // if postread is enabled it will buffer incoming bytes
        if(postread) // if postread is enabled it will buffer incoming bytes
                mybuf[0] = mybuf[0] | MPSSE_DO_READ;
                mybuf[0] = mybuf[0] | MPSSE_DO_READ;
 
 
        // We divide the transmitting stream of bytes in chunks with a maximun length of 65536 bytes each.
        // We divide the transmitting stream of bytes in chunks with a maximun length of 65536 bytes each.
        while(len > 0) {
        while(len > 0) {
                cur_chunk_len = min(len, 65536);
                cur_chunk_len = min(len, 65536);
                len = len - cur_chunk_len;
                len = len - cur_chunk_len;
                cur_command_size = cur_chunk_len + 3;
                cur_command_size = cur_chunk_len + 3;
 
 
                /// Low and High bytes of the length field
                /// Low and High bytes of the length field
                mybuf[1] = (unsigned char) ( cur_chunk_len - 1);
                mybuf[1] = (unsigned char) ( cur_chunk_len - 1);
                mybuf[2] = (unsigned char) ((cur_chunk_len - 1) >> 8);
                mybuf[2] = (unsigned char) ((cur_chunk_len - 1) >> 8);
 
 
                debug("\tOPCODE:  0x%x\n", mybuf[0]);
                debug("\tOPCODE:  0x%x\n", mybuf[0]);
                debug("\tLENGTL:  0x%02x\n", mybuf[1]);
                debug("\tLENGTL:  0x%02x\n", mybuf[1]);
                debug("\tLENGTH:  0x%02x\n", mybuf[2]);
                debug("\tLENGTH:  0x%02x\n", mybuf[2]);
 
 
                /// The rest of the command is filled with the bytes that will be transferred
                /// The rest of the command is filled with the bytes that will be transferred
                memcpy(&(mybuf[3]), buf, cur_chunk_len );
                memcpy(&(mybuf[3]), buf, cur_chunk_len );
                buf = buf + cur_chunk_len;
                buf = buf + cur_chunk_len;
                for(i = 0; i< cur_chunk_len; i++)
                for(i = 0; i< cur_chunk_len; i++)
                        if(debug>1) debug("\tBYTE%3d: 0x%02x\n", i, mybuf[3+i]);
                        if(debug>1) debug("\tBYTE%3d: 0x%02x\n", i, mybuf[3+i]);
 
 
                /// Finally we can ransmit the command
                /// Finally we can ransmit the command
                xferred = usbconn_ftdi_write( conn, mybuf, cur_command_size, (postread ? cur_chunk_len : 0) );
                xferred = usbconn_ftdi_write( conn, mybuf, cur_command_size, (postread ? cur_chunk_len : 0) );
                if(xferred != cur_command_size)
                if(xferred != cur_command_size)
                        return -1;
                        return -1;
 
 
                // If OK, the update the number of incoming bytes that are being buffered for a posterior read
                // If OK, the update the number of incoming bytes that are being buffered for a posterior read
                if(postread)
                if(postread)
                        recv = recv + cur_chunk_len;
                        recv = recv + cur_chunk_len;
        }
        }
        debug("\tPOSTREAD: %u bytes\n", recv);
        debug("\tPOSTREAD: %u bytes\n", recv);
 
 
        // Returns the number of buffered incoming bytes
        // Returns the number of buffered incoming bytes
        return recv;
        return recv;
}
}
 
 
int cable_ft2232_write_bits(usbconn_t *conn, unsigned char *buf, int len, int postread, int with_tms)
int cable_ft2232_write_bits(usbconn_t *conn, unsigned char *buf, int len, int postread, int with_tms)
{
{
        int max_command_size;
        int max_command_size;
        int max_chunk_len;
        int max_chunk_len;
        int cur_chunk_len;
        int cur_chunk_len;
        int recv;
        int recv;
        int xferred;
        int xferred;
        int i;
        int i;
        unsigned char *mybuf;
        unsigned char *mybuf;
 
 
        if(len == 0)
        if(len == 0)
                return 0;
                return 0;
 
 
        max_command_size = 3;
        max_command_size = 3;
        mybuf = (unsigned char *) malloc( max_command_size );
        mybuf = (unsigned char *) malloc( max_command_size );
 
 
        if(!with_tms) {
        if(!with_tms) {
                /// Command OPCODE: write bits (can write up to 8 bits in a single command)
                /// Command OPCODE: write bits (can write up to 8 bits in a single command)
                max_chunk_len = 8;
                max_chunk_len = 8;
                mybuf[0] = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_WRITE_NEG | MPSSE_BITMODE;
                mybuf[0] = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_WRITE_NEG | MPSSE_BITMODE;
        }
        }
        else {
        else {
                /// Command OPCODE: 0x4B write bit with tms (can write up to 1 bits in a single command)
                /// Command OPCODE: 0x4B write bit with tms (can write up to 1 bits in a single command)
                max_chunk_len = 1;
                max_chunk_len = 1;
                mybuf[0] = MPSSE_WRITE_TMS|MPSSE_LSB|MPSSE_BITMODE|MPSSE_WRITE_NEG;
                mybuf[0] = MPSSE_WRITE_TMS|MPSSE_LSB|MPSSE_BITMODE|MPSSE_WRITE_NEG;
        }
        }
 
 
        if(postread) // (OPCODE += 0x20) if postread is enabled it will buffer incoming bits
        if(postread) // (OPCODE += 0x20) if postread is enabled it will buffer incoming bits
                mybuf[0] = mybuf[0] | MPSSE_DO_READ;
                mybuf[0] = mybuf[0] | MPSSE_DO_READ;
 
 
        // We divide the transmitting stream of bytes in chunks with a maximun length of max_chunk_len bits each.
        // We divide the transmitting stream of bytes in chunks with a maximun length of max_chunk_len bits each.
        i=0;
        i=0;
        recv = 0;
        recv = 0;
        while(len > 0) {
        while(len > 0) {
                cur_chunk_len = min(len, max_chunk_len);
                cur_chunk_len = min(len, max_chunk_len);
                len = len - cur_chunk_len;
                len = len - cur_chunk_len;
 
 
                /// Bits length field
                /// Bits length field
                mybuf[1] = (unsigned char) ( cur_chunk_len - 1);
                mybuf[1] = (unsigned char) ( cur_chunk_len - 1);
 
 
                debug("\tOPCODE:  0x%x\n", mybuf[0]);
                debug("\tOPCODE:  0x%x\n", mybuf[0]);
                debug("\tLENGTH:  0x%02x\n", mybuf[1]);
                debug("\tLENGTH:  0x%02x\n", mybuf[1]);
 
 
                if(!with_tms) {
                if(!with_tms) {
                        /// The last byte of the command is filled with the bits that will be transferred
                        /// The last byte of the command is filled with the bits that will be transferred
                        debug("\tDATA[%d]  0x%02x\n", (i/8), buf[i/8]);
                        debug("\tDATA[%d]  0x%02x\n", (i/8), buf[i/8]);
                        mybuf[2] = buf[i/8];
                        mybuf[2] = buf[i/8];
                        i=i+8;
                        i=i+8;
                }
                }
                else {
                else {
                        //TODO: seleccionar el bit a transmitir
                        //TODO: seleccionar el bit a transmitir
                        mybuf[2] = 0x01 | ((buf[(i/8)] >> (i%8)) << 7);
                        mybuf[2] = 0x01 | ((buf[(i/8)] >> (i%8)) << 7);
                        i++;
                        i++;
                }
                }
 
 
                debug("\tBYTE%3d: 0x%02x\n", i, mybuf[2]);
                debug("\tBYTE%3d: 0x%02x\n", i, mybuf[2]);
 
 
                /// Finally we can transmmit the command
                /// Finally we can transmmit the command
                xferred = usbconn_ftdi_write( conn, mybuf, max_command_size, (postread ? 1 : 0) );
                xferred = usbconn_ftdi_write( conn, mybuf, max_command_size, (postread ? 1 : 0) );
                if(xferred != max_command_size)
                if(xferred != max_command_size)
                        return -1;
                        return -1;
 
 
                // If OK, the update the number of incoming bytes that are being buffered for a posterior read
                // If OK, the update the number of incoming bytes that are being buffered for a posterior read
                if(postread)
                if(postread)
                        recv = recv + 1;
                        recv = recv + 1;
        }
        }
        debug("\tPOSTREAD: %u bytes\n", recv);
        debug("\tPOSTREAD: %u bytes\n", recv);
 
 
        return recv;
        return recv;
}
}
 
 
int cable_ft2232_read_packed_bits(usbconn_t *conn, uint8_t *buf, int packet_len, int bits_per_packet, int offset)
int cable_ft2232_read_packed_bits(usbconn_t *conn, uint8_t *buf, int packet_len, int bits_per_packet, int offset)
{
{
        unsigned char *mybuf;
        unsigned char *mybuf;
        unsigned char dst_mask;
        unsigned char dst_mask;
        unsigned char src_mask;
        unsigned char src_mask;
        int row_offset;
        int row_offset;
        int dst_row;
        int dst_row;
        int dst_col;
        int dst_col;
        int src_row;
        int src_row;
        int src_col;
        int src_col;
        int i;
        int i;
        int r;
        int r;
 
 
        if(packet_len == 0 || bits_per_packet == 0)
        if(packet_len == 0 || bits_per_packet == 0)
                return 0;
                return 0;
 
 
        mybuf = (unsigned char *) malloc( packet_len );
        mybuf = (unsigned char *) malloc( packet_len );
        if((r=usbconn_ftdi_read( conn, mybuf, packet_len )) < 0) {
        if((r=usbconn_ftdi_read( conn, mybuf, packet_len )) < 0) {
                debug("Read failed\n");
                debug("Read failed\n");
                return -1;
                return -1;
        }
        }
 
 
        if(bits_per_packet < 8) {
        if(bits_per_packet < 8) {
                for(i=0; i < packet_len; i++){ // rotate bits to the left side
                for(i=0; i < packet_len; i++){ // rotate bits to the left side
//                      debug("[MYDBG] unaligned bits[%d]=%02x\n", i, mybuf[i]);                        
//                      debug("[MYDBG] unaligned bits[%d]=%02x\n", i, mybuf[i]);                        
                        mybuf[i] = (mybuf[i] >> (8-bits_per_packet));
                        mybuf[i] = (mybuf[i] >> (8-bits_per_packet));
//                      debug("[MYDBG]   aligned bits[%d]=%02x\n", i, mybuf[i]);
//                      debug("[MYDBG]   aligned bits[%d]=%02x\n", i, mybuf[i]);
                }
                }
                for(i=offset; i < (packet_len*bits_per_packet+offset); i++) {
                for(i=offset; i < (packet_len*bits_per_packet+offset); i++) {
                        dst_row = i / 8;
                        dst_row = i / 8;
                        dst_col = i % 8;
                        dst_col = i % 8;
                        src_row = (i-offset) / bits_per_packet;
                        src_row = (i-offset) / bits_per_packet;
                        src_col = (i-offset) % bits_per_packet;
                        src_col = (i-offset) % bits_per_packet;
                        dst_mask = ~(1 << dst_col);
                        dst_mask = ~(1 << dst_col);
                        src_mask = (1 << src_col);
                        src_mask = (1 << src_col);
//                      debug("[MYDBG] i=%4d dst[%3d][%3d] dst_mask=%02x dst_val=%02x dst_masked=%02x\n", i, dst_row, dst_col, dst_mask, buf[dst_row], (buf[dst_row] & dst_mask));
//                      debug("[MYDBG] i=%4d dst[%3d][%3d] dst_mask=%02x dst_val=%02x dst_masked=%02x\n", i, dst_row, dst_col, dst_mask, buf[dst_row], (buf[dst_row] & dst_mask));
//                      debug("[MYDBG] i=%4d src[%3d][%3d] src_mask=%02x src_val=%02x src_masked=%02x\n", i, src_row, src_col, src_mask, mybuf[src_row], (mybuf[src_row] & src_mask));
//                      debug("[MYDBG] i=%4d src[%3d][%3d] src_mask=%02x src_val=%02x src_masked=%02x\n", i, src_row, src_col, src_mask, mybuf[src_row], (mybuf[src_row] & src_mask));
                        if(dst_col >= src_col)
                        if(dst_col >= src_col)
                                buf[dst_row] = (buf[dst_row] & dst_mask) | ((mybuf[src_row] & src_mask) << (dst_col - src_col));
                                buf[dst_row] = (buf[dst_row] & dst_mask) | ((mybuf[src_row] & src_mask) << (dst_col - src_col));
                        else
                        else
                                buf[dst_row] = (buf[dst_row] & dst_mask) | ((mybuf[src_row] & src_mask) >> (dst_col - src_col));
                                buf[dst_row] = (buf[dst_row] & dst_mask) | ((mybuf[src_row] & src_mask) >> (dst_col - src_col));
                }
                }
 
 
        }
        }
        else if(bits_per_packet == 8){
        else if(bits_per_packet == 8){
                row_offset = offset / 8;
                row_offset = offset / 8;
//              debug("[MYDBG] Row offset=%d\n", row_offset);
//              debug("[MYDBG] Row offset=%d\n", row_offset);
                memcpy( &(buf[row_offset]), mybuf, packet_len);
                memcpy( &(buf[row_offset]), mybuf, packet_len);
        }
        }
        else {
        else {
                return -1;
                return -1;
        }
        }
 
 
//      debug("read_bits()-> %x\n", *buf);
//      debug("read_bits()-> %x\n", *buf);
        return ((r < 1) ? -1 : 0);
        return ((r < 1) ? -1 : 0);
}
}
 
 
int cable_ft2232_write_stream(usbconn_t *conn, unsigned char *buf, int len, int postread, int with_tms) {
int cable_ft2232_write_stream(usbconn_t *conn, unsigned char *buf, int len, int postread, int with_tms) {
        int len_bytes;
        int len_bytes;
        int len_bits;
        int len_bits;
        int len_tms_bits;
        int len_tms_bits;
        unsigned char mybuf;
        unsigned char mybuf;
 
 
        len_tms_bits = ((with_tms) ? 1 : 0);
        len_tms_bits = ((with_tms) ? 1 : 0);
        len_bytes = ((len -len_tms_bits) / 8);
        len_bytes = ((len -len_tms_bits) / 8);
        len_bits  = ((len -len_tms_bits) % 8);
        len_bits  = ((len -len_tms_bits) % 8);
 
 
        debug("[MYDBG] cable_ft2232_write_stream(len=%d postread=%d tms=%d) = %d bytes %dbits %dtms_bits\n", len, postread, with_tms, len_bytes, len_bits, len_tms_bits);
        debug("[MYDBG] cable_ft2232_write_stream(len=%d postread=%d tms=%d) = %d bytes %dbits %dtms_bits\n", len, postread, with_tms, len_bytes, len_bits, len_tms_bits);
 
 
        if(len_bytes > 0)
        if(len_bytes > 0)
                cable_ft2232_write_bytes(conn, buf, len_bytes, postread);
                cable_ft2232_write_bytes(conn, buf, len_bytes, postread);
 
 
        if(len_bits > 0)
        if(len_bits > 0)
                cable_ft2232_write_bits(conn, &(buf[len_bytes]), len_bits, postread, 0);
                cable_ft2232_write_bits(conn, &(buf[len_bytes]), len_bits, postread, 0);
 
 
        if(len_tms_bits > 0) {
        if(len_tms_bits > 0) {
                mybuf = (buf[len_bytes] >> len_bits);
                mybuf = (buf[len_bytes] >> len_bits);
                cable_ft2232_write_bits(conn, &mybuf, 1, postread, 1);
                cable_ft2232_write_bits(conn, &mybuf, 1, postread, 1);
        }
        }
 
 
        return 0;
        return 0;
}
}
 
 
int cable_ft2232_read_stream(usbconn_t *conn, unsigned char *buf, int len, int with_tms) {
int cable_ft2232_read_stream(usbconn_t *conn, unsigned char *buf, int len, int with_tms) {
        int len_bytes;
        int len_bytes;
        int len_bits;
        int len_bits;
        int len_tms_bits;
        int len_tms_bits;
 
 
        len_tms_bits = ((with_tms) ? 1 : 0);
        len_tms_bits = ((with_tms) ? 1 : 0);
        len_bytes = ((len -len_tms_bits) / 8);
        len_bytes = ((len -len_tms_bits) / 8);
        len_bits  = ((len -len_tms_bits) % 8);
        len_bits  = ((len -len_tms_bits) % 8);
 
 
        debug("[MYDBG] cable_ft2232_read_stream(len=%d tms=%d) = %d bytes %dbits %dtms_bits\n", len, with_tms, len_bytes, len_bits, len_tms_bits);
        debug("[MYDBG] cable_ft2232_read_stream(len=%d tms=%d) = %d bytes %dbits %dtms_bits\n", len, with_tms, len_bytes, len_bits, len_tms_bits);
 
 
        if(len_bytes > 0)
        if(len_bytes > 0)
                cable_ft2232_read_packed_bits(conn, buf, len_bytes, 8, 0);
                cable_ft2232_read_packed_bits(conn, buf, len_bytes, 8, 0);
 
 
        if(len_bits > 0)
        if(len_bits > 0)
                cable_ft2232_read_packed_bits(conn, buf, 1, len_bits, (len_bytes * 8));
                cable_ft2232_read_packed_bits(conn, buf, 1, len_bits, (len_bytes * 8));
 
 
        if(len_tms_bits > 0)
        if(len_tms_bits > 0)
                cable_ft2232_read_packed_bits(conn, buf, 1, 1, (len_bits + (len_bytes * 8)));
                cable_ft2232_read_packed_bits(conn, buf, 1, 1, (len_bits + (len_bytes * 8)));
 
 
        return 0;
        return 0;
}
}
 
 
 
 
 
 
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
/// Advanced Jtag debugger driver interface.
/// Advanced Jtag debugger driver interface.
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
 
 
 
jtag_cable_t *cable_ftdi_get_driver(void)
 
{
 
  return &ft2232_cable_driver;
 
}
 
 
int cable_ftdi_init() {
int cable_ftdi_init() {
        int err = APP_ERR_NONE;
        int err = APP_ERR_NONE;
        int res = 0;
        int res = 0;
        unsigned char  *buf = malloc(10);
        unsigned char  *buf = malloc(10);
 
 
        ft2232_device = usbconn_ftdi_connect();
        ft2232_device = usbconn_ftdi_connect();
 
 
        if((res = usbconn_ftdi_mpsse_open(ft2232_device)) != 0)
        if((res = usbconn_ftdi_mpsse_open(ft2232_device)) != 0)
                err |= APP_ERR_USB;
                err |= APP_ERR_USB;
        printf("Open MPSSE mode returned: %s\n", ((res != 0) ? "FAIL" : "OK") );
        printf("Open MPSSE mode returned: %s\n", ((res != 0) ? "FAIL" : "OK") );
 
 
        ftdi_param_t *params = ft2232_device->params;
        ftdi_param_t *params = ft2232_device->params;
        //struct ftdi_context * ftdic = params->ftdic;
        //struct ftdi_context * ftdic = params->ftdic;
 
 
        buf[0]= SET_BITS_LOW;
        buf[0]= SET_BITS_LOW;
        buf[1]= 0x00;
        buf[1]= 0x00;
        buf[2]= 0x0b;
        buf[2]= 0x0b;
        buf[3]= TCK_DIVISOR;
        buf[3]= TCK_DIVISOR;
        buf[4]= 0x01;
        buf[4]= 0x01;
        buf[5]= 0x00;
        buf[5]= 0x00;
        buf[6]= SET_BITS_HIGH;
        buf[6]= SET_BITS_HIGH;
        buf[7]= ~0x04;
        buf[7]= ~0x04;
        buf[8]= 0x04;
        buf[8]= 0x04;
        buf[9]= SEND_IMMEDIATE;
        buf[9]= SEND_IMMEDIATE;
        if(usbconn_ftdi_write( ft2232_device , buf, 10, 0) != 10) {
        if(usbconn_ftdi_write( ft2232_device , buf, 10, 0) != 10) {
                err |= APP_ERR_USB;
                err |= APP_ERR_USB;
                printf("Initial write failed\n");
                printf("Initial write failed\n");
        }
        }
 
 
        usbconn_ftdi_flush( params );
        usbconn_ftdi_flush( params );
 
 
        return err;
        return err;
}
}
 
 
int cable_ftdi_close() {
int cable_ftdi_close() {
        usbconn_ftdi_close(ft2232_device);
        usbconn_ftdi_close(ft2232_device);
        usbconn_ftdi_free(ft2232_device);
        usbconn_ftdi_free(ft2232_device);
 
 
        return APP_ERR_NONE;
        return APP_ERR_NONE;
}
}
 
 
int cable_ftdi_flush() {
int cable_ftdi_flush() {
        ftdi_param_t *params = ft2232_device->params;
        ftdi_param_t *params = ft2232_device->params;
        usbconn_ftdi_flush( params );
        usbconn_ftdi_flush( params );
 
 
        return APP_ERR_NONE;
        return APP_ERR_NONE;
}
}
 
 
int cable_ftdi_write_bit(uint8_t packet) {
int cable_ftdi_write_bit(uint8_t packet) {
        int err = APP_ERR_NONE;
        int err = APP_ERR_NONE;
        unsigned char buf;
        unsigned char buf;
        int tms;
        int tms;
 
 
        buf = ((packet & TDO) ? 0x01 : 0x00);
        buf = ((packet & TDO) ? 0x01 : 0x00);
        tms = ((packet & TMS) ? 1 : 0);
        tms = ((packet & TMS) ? 1 : 0);
 
 
        if(cable_ft2232_write_stream(ft2232_device, &buf, 1, 0, tms) < 0)
        if(cable_ft2232_write_stream(ft2232_device, &buf, 1, 0, tms) < 0)
                err |= APP_ERR_COMM;
                err |= APP_ERR_COMM;
 
 
        cable_ftdi_flush();
        cable_ftdi_flush();
 
 
        return err;
        return err;
 
 
}
}
 
 
int cable_ftdi_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
int cable_ftdi_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
 
 
        int err = APP_ERR_NONE;
        int err = APP_ERR_NONE;
        unsigned char buf;
        unsigned char buf;
        int tms;
        int tms;
 
 
        buf = ((packet_out & TDO) ? 0x01 : 0x00);
        buf = ((packet_out & TDO) ? 0x01 : 0x00);
        tms = ((packet_out & TMS) ? 1 : 0);
        tms = ((packet_out & TMS) ? 1 : 0);
 
 
        if(cable_ft2232_write_stream(ft2232_device, &buf, 1, 1, tms) < 0)
        if(cable_ft2232_write_stream(ft2232_device, &buf, 1, 1, tms) < 0)
                err = APP_ERR_COMM;
                err = APP_ERR_COMM;
 
 
        if(cable_ft2232_read_stream(ft2232_device, ((unsigned char *)bit_in), 1, tms) < 0)
        if(cable_ft2232_read_stream(ft2232_device, ((unsigned char *)bit_in), 1, tms) < 0)
                err = APP_ERR_COMM;
                err = APP_ERR_COMM;
 
 
        return err;
        return err;
}
}
 
 
int cable_ftdi_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
int cable_ftdi_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
        int err = APP_ERR_NONE;
        int err = APP_ERR_NONE;
 
 
        if(cable_ft2232_write_stream(ft2232_device, ((unsigned char *)stream), len_bits, 0, set_last_bit) < 0)
        if(cable_ft2232_write_stream(ft2232_device, ((unsigned char *)stream), len_bits, 0, set_last_bit) < 0)
                err |= APP_ERR_COMM;
                err |= APP_ERR_COMM;
 
 
        cable_ftdi_flush();
        cable_ftdi_flush();
 
 
        return err;
        return err;
}
}
 
 
int cable_ftdi_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
int cable_ftdi_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
        int err = APP_ERR_NONE;
        int err = APP_ERR_NONE;
        if(cable_ft2232_write_stream(ft2232_device, ((unsigned char *)outstream), len_bits, 1, set_last_bit) < 0)
        if(cable_ft2232_write_stream(ft2232_device, ((unsigned char *)outstream), len_bits, 1, set_last_bit) < 0)
                err |= APP_ERR_COMM;
                err |= APP_ERR_COMM;
        if(cable_ft2232_read_stream(ft2232_device, ((unsigned char *)instream), len_bits, set_last_bit) < 0)
        if(cable_ft2232_read_stream(ft2232_device, ((unsigned char *)instream), len_bits, set_last_bit) < 0)
                err |= APP_ERR_COMM;
                err |= APP_ERR_COMM;
 
 
        return err;
        return err;
}
}
 
 
int cable_ftdi_opt(int c, char *str) {
int cable_ftdi_opt(int c, char *str) {
        fprintf(stderr, "Unknown parameter '%c'\n", c);
        fprintf(stderr, "Unknown parameter '%c'\n", c);
        return APP_ERR_BAD_PARAM;
        return APP_ERR_BAD_PARAM;
}
}
 
 
/// ----------------------------------------------------------------------------------------------
/// ----------------------------------------------------------------------------------------------
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.