ftd2xx parport driver added

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@782 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Arnim Läuger 17 years ago
parent ee467a71e6
commit e828e317e4

@ -109,7 +109,7 @@ dnl LIBFTDI_CFLAGS=`$HAVELIBFTDI --cflags`
AC_DEFINE(HAVE_LIBFTDI, 1, [Define if you have libftdi])
else
AM_CONDITIONAL(HAVE_LIBFTDI, false)
AC_MSG_WARN([*** libftdi-config not found. No support for FTDI-based USB JTAG cables.])
AC_MSG_WARN([*** libftdi-config not found. No support for FTDI-based USB JTAG cables via libftdi.])
fi
dnl check for libusb-config
@ -126,6 +126,16 @@ else
AC_MSG_WARN([*** libusb-config not found. Omitting support for some USB JTAG cables.])
fi
dnl check for availability of libftd2xx
AC_CHECK_LIB([ftd2xx], [FT_Open], [
AM_CONDITIONAL(HAVE_LIBFTD2XX, true)
AC_DEFINE(HAVE_LIBFTD2XX, 1, [define if you have libftd2xx])
LIBS="-lftd2xx $LIBS"
],[
AM_CONDITIONAL(HAVE_LIBFTD2XX, false)
AC_MSG_WARN([*** libftd2xx not found. No support for FTDI-based USB JTAG cables via libftd2xx.])
])
CFLAGS="$CFLAGS -Wall"
CPPFLAGS="$CPPFLAGS -I\$(top_srcdir) -I\$(top_srcdir)/include"
@ -145,9 +155,16 @@ if test ${HAVELIBUSB:-no} != no ; then
else
FLAG_HAVELIBUSB=no
fi
if echo $LIBS | grep -q 'ftd2xx' ; then
FLAG_HAVELIBFTD2XX=yes
else
FLAG_HAVELIBFTD2XX=no
fi
AC_MSG_RESULT([
jtag is now configured for
USB cable support: $FLAG_HAVELIBUSB
FTDI cable support: $FLAG_HAVELIBFTDI
USB cable support : $FLAG_HAVELIBUSB
FTDI cable support
via libftdi : $FLAG_HAVELIBFTDI
via libftd2xx : $FLAG_HAVELIBFTD2XX
])

@ -89,6 +89,10 @@ cmd_cable_help( void )
"Usage: %s VID:PID:S/N CABLE\n"
"Usage: %s VID:PID:S/N CABLE\n"
#endif
#ifdef HAVE_LIBFTD2XX
"Usage: %s VID:PID:S/N CABLE\n"
"Usage: %s VID:PID:S/N CABLE\n"
#endif
#ifdef HAVE_LIBUSB
"Usage: %s VID:PID:S/N CABLE\n"
#endif
@ -96,7 +100,7 @@ cmd_cable_help( void )
"\n"
"PORTADDR parallel port address (e.g. 0x378)\n"
"CABLE cable type\n"
#if defined HAVE_LIBUSB || defined HAVE_LIBFTDI
#if defined HAVE_LIBUSB || defined HAVE_LIBFTDI || defined HAVE_LIBFTD2XX
"DEV ppdev device (e.g. /dev/parport0)\n"
"VID empty or USB vendor ID, hex (e.g. 09FB)\n"
"PID empty or USB product ID, hex (e.g. 6001)\n"
@ -109,6 +113,9 @@ cmd_cable_help( void )
#ifdef HAVE_LIBFTDI
"cable ftdi", "cable ftdi-mpsse",
#endif
#ifdef HAVE_LIBFTD2XX
"cable ftd2xx", "cable ftd2xx-mpsse",
#endif
#ifdef HAVE_LIBUSB
"cable xpcu",
#endif

@ -62,3 +62,7 @@ libtap_a_SOURCES += \
cable/ft2232.c
endif
if HAVE_LIBFTD2XX
libtap_a_SOURCES += \
parport/ftd2xx.c
endif

@ -23,8 +23,6 @@
*
*/
#include <ftdi.h>
#include "sysdep.h"
#include "cable.h"
@ -52,6 +50,34 @@
#define FT2232_MAX_TCK_FREQ 6000000
/* repeat the definitions for MPSSE command processor here
since we cannot rely on the existence of ftdih. even though
they're defined there */
/* Shifting commands IN MPSSE Mode*/
#define MPSSE_WRITE_NEG 0x01 /* Write TDI/DO on negative TCK/SK edge*/
#define MPSSE_BITMODE 0x02 /* Write bits, not bytes */
#define MPSSE_READ_NEG 0x04 /* Sample TDO/DI on negative TCK/SK edge */
#define MPSSE_LSB 0x08 /* LSB first */
#define MPSSE_DO_WRITE 0x10 /* Write TDI/DO */
#define MPSSE_DO_READ 0x20 /* Read TDO/DI */
#define MPSSE_WRITE_TMS 0x40 /* Write TMS/CS */
/* FTDI MPSSE commands */
#define SET_BITS_LOW 0x80
/*BYTE DATA*/
/*BYTE Direction*/
#define SET_BITS_HIGH 0x82
/*BYTE DATA*/
/*BYTE Direction*/
#define GET_BITS_LOW 0x81
#define GET_BITS_HIGH 0x83
#define LOOPBACK_START 0x84
#define LOOPBACK_END 0x85
#define TCK_DIVISOR 0x86
/* bit and bitmask definitions for GPIO commands */
#define BIT_TCK 0
#define BIT_TDI 1
#define BIT_TDO 2

@ -32,6 +32,10 @@ extern parport_driver_t direct_parport_driver;
#ifdef HAVE_LINUX_PPDEV_H
extern parport_driver_t ppdev_parport_driver;
#endif /* HAVE_LINUX_PPDEV_H */
#ifdef HAVE_LIBFTD2XX
extern parport_driver_t ftd2xx_parport_driver;
extern parport_driver_t ftd2xx_mpsse_parport_driver;
#endif /* HAVE_LIBFTD2xx */
#ifdef HAVE_LIBFTDI
extern parport_driver_t ftdi_parport_driver;
extern parport_driver_t ftdi_mpsse_parport_driver;
@ -47,12 +51,16 @@ parport_driver_t *parport_drivers[] = {
#ifdef HAVE_LINUX_PPDEV_H
&ppdev_parport_driver,
#endif /* HAVE_LINUX_PPDEV_H */
#ifdef HAVE_LIBFTD2XX
&ftd2xx_parport_driver,
&ftd2xx_mpsse_parport_driver,
#endif /* HAVE_LIBFTD2XX */
#ifdef HAVE_LIBFTDI
&ftdi_parport_driver,
&ftdi_mpsse_parport_driver,
#endif /* HAVE_LIBFTDI */
#ifdef HAVE_LIBUSB
&xpcu_pp_driver,
&xpcu_pp_driver,
#endif /* HAVE_LIBUSB */
NULL /* last must be NULL */
};
@ -92,4 +100,3 @@ parport_set_control( parport_t *port, uint8_t data )
{
return port->driver->set_control( port, data );
}

@ -0,0 +1,468 @@
/*
* $Id$
*
* libftd2xx Driver
*
* Based on libftdi driver
* Copyright (C) 2006 K. Waschk
*
* 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 Kolja Waschk, 2006.
* Structure taken from ppdev.c, written by Marcel Telka, 2003.
* Ported to libftd2xx by A. Laeuger, 2007.
*
*/
#include "sysdep.h"
#include <fcntl.h>
#include <stropts.h>
#include <unistd.h>
#include <linux/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <ftd2xx.h>
#include "parport.h"
#include "cable.h"
parport_driver_t ftd2xx_parport_driver;
parport_driver_t ftd2xx_mpsse_parport_driver;
typedef struct port_node_t port_node_t;
struct port_node_t {
parport_t *port;
port_node_t *next;
};
static port_node_t *ports = NULL; /* devices */
#define OUTBUF_LEN_STD 64
#define OUTBUF_LEN_MPSSE 4096
typedef struct {
char *serial;
unsigned int vendor_id;
unsigned int product_id;
char autoflush;
FT_HANDLE fc;
int outcount;
unsigned char *outbuf;
int outbuf_len;
} ftd2xx_params_t;
static int ftd2xx_flush_output ( ftd2xx_params_t *p );
static parport_t *
ftd2xx_parport_alloc( const char *vidpid, parport_driver_t * parport_driver, size_t outbuf_len )
{
ftd2xx_params_t *params = malloc( sizeof *params );
parport_t *parport = malloc( sizeof *parport );
port_node_t *node = malloc( sizeof *node );
unsigned char *outbuf = malloc( outbuf_len );
if (!node || !parport || !params || !outbuf) {
free( node );
free( parport );
free( params );
return NULL;
}
params->outbuf = outbuf;
params->outbuf_len = outbuf_len;
params->outcount = 0;
params->autoflush = 0;
params->product_id = 0;
params->vendor_id = 0;
params->serial = NULL;
{
char *f = strchr(vidpid, ':');
char *l = strrchr(vidpid, ':');
if(f)
{
params->vendor_id = strtoul(vidpid, NULL, 16);
params->product_id = strtoul(f+1, NULL, 16);
if(l!=f) params->serial = strdup(l+1);
};
};
parport->params = params;
parport->driver = parport_driver;
parport->cable = NULL;
node->port = parport;
node->next = ports;
ports = node;
return parport;
}
static void
ftd2xx_parport_free( parport_t *port )
{
port_node_t **prev;
for (prev = &ports; *prev; prev = &((*prev)->next))
if ((*prev)->port == port)
break;
if (*prev) {
port_node_t *pn = *prev;
*prev = pn->next;
free( pn );
}
free( ((ftd2xx_params_t *) port->params)->serial );
free( ((ftd2xx_params_t *) port->params)->outbuf );
free( port->params );
free( port );
}
static cable_driver_t *
ftd2xx_pre_connect( const char **par, int parnum )
{
int i;
port_node_t *pn;
if (parnum != 2) {
printf( _("Syntax error!\n") );
return NULL;
}
for (pn = ports; pn; pn = pn->next)
if (strcmp( pn->port->params, par[0] ) == 0) {
printf( _("Disconnecting %s from FTDI device %s\n"), _(pn->port->cable->driver->description), par[0] );
pn->port->cable->driver->disconnect( pn->port->cable );
break;
}
if (strcmp( par[1], "none" ) == 0) {
printf( _("Changed cable to 'none'\n") );
return NULL;
}
for (i = 0; cable_drivers[i]; i++)
if (strcmp( par[1], cable_drivers[i]->name ) == 0)
break;
if (!cable_drivers[i]) {
printf( _("Unknown cable: %s\n"), par[1] );
return NULL;
}
printf( _("Initializing %s on FTDI device %s\n"), _(cable_drivers[i]->description), par[0] );
return cable_drivers[i];
}
static cable_t *
ftd2xx_std_connect( const char **par, int parnum )
{
parport_t *parport;
cable_driver_t *cable_driver;
cable_t *cable;
cable_driver = ftd2xx_pre_connect(par, parnum);
if (!cable_driver)
return NULL;
parport = ftd2xx_parport_alloc( par[0], &ftd2xx_parport_driver, OUTBUF_LEN_STD );
if (!parport) {
printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ );
return NULL;
}
cable = cable_driver->connect( cable_driver, parport );
if (!cable)
ftd2xx_parport_free( parport );
return cable;
}
static cable_t *
ftd2xx_mpsse_connect( const char **par, int parnum )
{
parport_t *parport;
cable_driver_t *cable_driver;
cable_t *cable;
cable_driver = ftd2xx_pre_connect(par, parnum);
if (!cable_driver)
return NULL;
parport = ftd2xx_parport_alloc( par[0], &ftd2xx_mpsse_parport_driver, OUTBUF_LEN_MPSSE );
if (!parport) {
printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ );
return NULL;
}
cable = cable_driver->connect( cable_driver, parport );
if (!cable)
ftd2xx_parport_free( parport );
return cable;
}
static int
ftd2xx_generic_open( parport_t *parport )
{
ftd2xx_params_t *p = parport->params;
FT_STATUS status;
/* Add non-standard Vid/Pid to the linux driver */
if ((status = FT_SetVIDPID(p->vendor_id, p->product_id)) != FT_OK)
fprintf( stderr, "Warning: couldn't add %4.4x:%4.4x", p->vendor_id, p->product_id );
if ((status = FT_Open(0, &(p->fc))) != FT_OK) {
fprintf( stderr, "Error: unable to open FTDI device: %li\n", status);
return -1;
}
return 0;
}
static int
ftd2xx_std_open( parport_t *parport )
{
int r;
ftd2xx_params_t *p = parport->params;
FT_HANDLE fc;
FT_STATUS status;
r = ftd2xx_generic_open(parport);
if (r < 0)
return r;
fc = p->fc;
if ((status = FT_SetBitMode( fc, 0x00, 0x00 )) != FT_OK) {
fprintf(stderr, "Can't disable bitmode: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_SetLatencyTimer(fc, 2)) != FT_OK) {
fprintf(stderr, "Can't set latency timer: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_SetBaudRate(fc, 48000000)) != FT_OK) {
fprintf(stderr, "Can't set baudrate: %li\n", status);
FT_Close(fc);
return -1;
}
return 0;
}
static int
ftd2xx_mpsse_open( parport_t *parport )
{
int r;
ftd2xx_params_t *p = parport->params;
FT_HANDLE fc;
FT_STATUS status;
r = ftd2xx_generic_open(parport);
if (r < 0)
return r;
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) {
fprintf(stderr, "Can't reset 1 device: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_Purge(fc, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK) {
fprintf(stderr, "Can't purge buffers: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_SetBitMode( fc, 0x00, 0x00 )) != FT_OK) {
fprintf(stderr, "Can't disable bitmode: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_SetBitMode( fc, 0x0b, 0x02 /*BITMODE_MPSSE*/ )) != FT_OK) {
fprintf(stderr, "Can't set bitmode: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_ResetDevice(fc)) != FT_OK) {
fprintf(stderr, "Can't reset 2 device: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_Purge(fc, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK) {
fprintf(stderr, "Can't purge buffers: %li\n", status);
FT_Close(fc);
return -1;
}
if ((status = FT_SetLatencyTimer(fc, 2)) != FT_OK) {
fprintf(stderr, "Can't set latency timer: %li\n", status);
FT_Close(fc);
return -1;
}
return 0;
}
static int
ftd2xx_flush_output ( ftd2xx_params_t *p )
{
DWORD xferred;
FT_STATUS status;
if ((status = FT_Write( p->fc, p->outbuf, (DWORD)(p->outcount), &xferred )) != FT_OK)
fprintf( stderr, "Error: FT_Write() failed in %i\n", __LINE__ );
if(xferred > 0 && xferred < p->outcount)
{
int offset = xferred;
int remaining = p->outcount - xferred;
while(remaining)
{
printf("W\n");
if(xferred < 0) return xferred;
if ((status = FT_Write( p->fc, p->outbuf + offset, (DWORD)remaining, &xferred)) != FT_OK)
fprintf( stderr, "Error: FT_Write() failed in %i\n", __LINE__ );
if(xferred < 0)
{
memmove(p->outbuf, p->outbuf + offset, remaining);
p->outcount = remaining;
return 0;
}
offset += xferred;
remaining -= xferred;
}
};
p->outcount = 0;
return 0;
}
static int
ftd2xx_close( parport_t *parport )
{
ftd2xx_params_t *p = parport->params;
if(p->outcount > 0) ftd2xx_flush_output( p );
p->outcount = 0;
FT_SetBitMode( p->fc, 0x00, 0x00 );
FT_Close(p->fc);
return 0;
}
static int
ftd2xx_set_data( parport_t *parport, uint8_t data )
{
ftd2xx_params_t *p = parport->params;
DWORD xferred;
FT_STATUS status;
if(p->autoflush)
{
if ((status = FT_Write( p->fc, &data, 1 , &xferred)) != FT_OK)
fprintf( stderr, "Error: FT_Write() failed in %i\n", __LINE__ );
if (xferred != 1)
printf("w\n");
}
else
{
p->outbuf[p->outcount++] = data;
if(p->outcount >= p->outbuf_len)
return ftd2xx_flush_output( p );
};
return 0;
}
static int
ftd2xx_get_data( parport_t *parport )
{
DWORD xferred = 0;
FT_STATUS status;
unsigned char d;
ftd2xx_params_t *p = parport->params;
while (xferred == 0) {
if ((status = FT_Read( p->fc, &d, 1, &xferred )) != FT_OK)
printf( "Error: FT_Read() failed in %i\n", __LINE__ );
}
return d;
}
static int
ftd2xx_get_status( parport_t *parport )
{
return 0;
}
static int
ftd2xx_set_control( parport_t *parport, uint8_t data )
{
ftd2xx_params_t *p = parport->params;
p->autoflush = data;
if(p->autoflush) ftd2xx_flush_output( p );
return 0;
}
parport_driver_t ftd2xx_parport_driver = {
"ftd2xx",
ftd2xx_std_connect,
ftd2xx_parport_free,
ftd2xx_std_open,
ftd2xx_close,
ftd2xx_set_data,
ftd2xx_get_data,
ftd2xx_get_status,
ftd2xx_set_control
};
parport_driver_t ftd2xx_mpsse_parport_driver = {
"ftd2xx-mpsse",
ftd2xx_mpsse_connect,
ftd2xx_parport_free,
ftd2xx_mpsse_open,
ftd2xx_close,
ftd2xx_set_data,
ftd2xx_get_data,
ftd2xx_get_status,
ftd2xx_set_control
};

@ -1,5 +1,5 @@
/*
* $Id: ftdi.c,v 1.7 2003/08/19 09:05:25 telka Exp $
* $Id$
*
* libftdi Driver
* Copyright (C) 2006 K. Waschk

Loading…
Cancel
Save