Merged usb_abstraction branch, [1880985] Revise cable+parport -> cable+lowlevel
git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1090 b68d4a1b-bc3d-0410-92ed-d4ac073336b7master
parent
d593528b35
commit
77804164d6
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* $Id: usbconn.h 809 2007-12-04 07:06:49Z kawk $
|
||||
*
|
||||
* USB Device Connection Driver Interface
|
||||
* Copyright (C) 2008 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 <kawk>, 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef USBCONN_H
|
||||
#define USBCONN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct usbconn_t usbconn_t;
|
||||
|
||||
#include "cable.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
char *desc;
|
||||
char *driver;
|
||||
int32_t vid;
|
||||
int32_t pid;
|
||||
} usbconn_cable_t;
|
||||
|
||||
typedef struct {
|
||||
const char *type;
|
||||
usbconn_t *(*connect)( const char **, int, usbconn_cable_t *);
|
||||
void (*free)( usbconn_t * );
|
||||
int (*open)( usbconn_t * );
|
||||
int (*close)( usbconn_t * );
|
||||
} usbconn_driver_t;
|
||||
|
||||
struct usbconn_t {
|
||||
usbconn_driver_t *driver;
|
||||
void *params;
|
||||
cable_t *cable;
|
||||
};
|
||||
|
||||
usbconn_t *usbconn_connect( const char **, int, usbconn_cable_t *);
|
||||
int usbconn_free( usbconn_t *conn );
|
||||
int usbconn_open( usbconn_t *conn );
|
||||
int usbconn_close( usbconn_t *conn );
|
||||
extern usbconn_driver_t *usbconn_drivers[];
|
||||
|
||||
#endif /* USBCONN_H */
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* $Id: usbconn/libusb.h,v 1.7 2003/08/19 09:05:25 telka Exp $
|
||||
*
|
||||
* Link driver for accessing USB devices via libusb
|
||||
*
|
||||
* Copyright (C) 2008 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, 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _USBCONN_LIBUSB_H
|
||||
#define _USBCONN_LIBUSB_H 1
|
||||
|
||||
#include <usb.h>
|
||||
|
||||
typedef struct {
|
||||
struct usb_device *dev;
|
||||
struct usb_dev_handle *handle;
|
||||
} libusb_param_t;
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* $Id: generic.c 1003 2008-02-10 10:00:30Z kawk $
|
||||
*
|
||||
* Copyright (C) 2003 ETC s.r.o.
|
||||
*
|
||||
* 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 Marcel Telka <marcel@telka.sk>, 2003.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cable.h"
|
||||
#include "chain.h"
|
||||
#include "parport.h"
|
||||
#include "generic.h"
|
||||
#include "generic_parport.h"
|
||||
|
||||
#include <cmd.h>
|
||||
|
||||
#undef VERBOSE
|
||||
|
||||
#ifdef VERBOSE
|
||||
void
|
||||
print_vector(int len, char *vec)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<len;i++) printf("%c",vec[i]?'1':'0');
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
generic_parport_connect( char *params[], cable_t *cable )
|
||||
{
|
||||
generic_params_t *cable_params = malloc( sizeof *cable_params );
|
||||
parport_t *port;
|
||||
int i;
|
||||
|
||||
if ( cmd_params( params ) < 3 ) {
|
||||
printf( _("not enough arguments!\n") );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* search parport driver list */
|
||||
for (i = 0; parport_drivers[i]; i++)
|
||||
if (strcasecmp( params[1], parport_drivers[i]->type ) == 0)
|
||||
break;
|
||||
if (!parport_drivers[i]) {
|
||||
printf( _("Unknown port driver: %s\n"), params[1] );
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* set up parport driver */
|
||||
port = parport_drivers[i]->connect( (const char **) ¶ms[2],
|
||||
cmd_params( params ) - 2 );
|
||||
|
||||
if (port == NULL) {
|
||||
printf( _("Error: Cable connection failed!\n") );
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (!cable_params) {
|
||||
free( cable_params );
|
||||
free( cable );
|
||||
return 4;
|
||||
}
|
||||
|
||||
cable->link.port = port;
|
||||
cable->params = cable_params;
|
||||
cable->chain = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
generic_parport_free( cable_t *cable )
|
||||
{
|
||||
cable->link.port->driver->parport_free( cable->link.port );
|
||||
free( cable->params );
|
||||
free( cable );
|
||||
}
|
||||
|
||||
void
|
||||
generic_parport_done( cable_t *cable )
|
||||
{
|
||||
parport_close( cable->link.port );
|
||||
}
|
||||
|
||||
void
|
||||
generic_parport_help( const char *cablename )
|
||||
{
|
||||
printf( _(
|
||||
"Usage: cable %s parallel PORTADDR\n"
|
||||
#if HAVE_LINUX_PPDEV_H
|
||||
" or: cable %s ppdev PPDEV\n"
|
||||
#endif
|
||||
#if HAVE_DEV_PPBUS_PPI_H
|
||||
" or: cable %s ppi PPIDEV\n"
|
||||
#endif
|
||||
"\n"
|
||||
"PORTADDR parallel port address (e.g. 0x378)\n"
|
||||
#if HAVE_LINUX_PPDEV_H
|
||||
"PPDEF ppdev device (e.g. /dev/parport0)\n"
|
||||
#endif
|
||||
#if HAVE_DEV_PPBUS_PPI_H
|
||||
"PPIDEF ppi device (e.g. /dev/ppi0)\n"
|
||||
#endif
|
||||
"\n"
|
||||
),
|
||||
#if HAVE_LINUX_PPDEV_H
|
||||
cablename,
|
||||
#endif
|
||||
#if HAVE_DEV_PPBUS_PPI_H
|
||||
cablename,
|
||||
#endif
|
||||
cablename
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* $Id: generic.h 1002 2008-02-10 09:50:59Z kawk $
|
||||
*
|
||||
* Copyright (C) 2003 ETC s.r.o.
|
||||
*
|
||||
* 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 Marcel Telka <marcel@telka.sk>, 2003.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GENERIC_PARPORT_H
|
||||
#define GENERIC_PARPORT_H
|
||||
|
||||
#include "cable.h"
|
||||
#include "parport.h"
|
||||
|
||||
int generic_parport_connect( char *params[], cable_t *cable );
|
||||
void generic_parport_free( cable_t *cable );
|
||||
void generic_parport_done( cable_t *cable );
|
||||
void generic_parport_help( const char *name );
|
||||
|
||||
#endif /* GENERIC_H */
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* $Id: generic.c 1003 2008-02-10 10:00:30Z kawk $
|
||||
*
|
||||
* Copyright (C) 2003 ETC s.r.o.
|
||||
*
|
||||
* 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 Marcel Telka <marcel@telka.sk>, 2003.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cable.h"
|
||||
#include "chain.h"
|
||||
#include "generic.h"
|
||||
#include "generic_usbconn.h"
|
||||
|
||||
#include <cmd.h>
|
||||
|
||||
#undef VERBOSE
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
extern usbconn_cable_t usbconn_cable_xpc_int;
|
||||
extern usbconn_cable_t usbconn_cable_xpc_ext;
|
||||
extern usbconn_cable_t usbconn_cable_jlink;
|
||||
#endif
|
||||
|
||||
usbconn_cable_t *usbconn_cables[] =
|
||||
{
|
||||
#ifdef HAVE_LIBUSB
|
||||
&usbconn_cable_xpc_int,
|
||||
&usbconn_cable_xpc_ext,
|
||||
&usbconn_cable_jlink,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
int
|
||||
generic_usbconn_connect( char *params[], cable_t *cable )
|
||||
{
|
||||
usbconn_cable_t user_specified = {
|
||||
NULL, /* no name */
|
||||
NULL, /* no string pattern */
|
||||
NULL, /* no specific driver */
|
||||
-1, /* no VID */
|
||||
-1, /* no PID */
|
||||
};
|
||||
|
||||
int paramc = cmd_params( params );
|
||||
generic_params_t *cable_params;
|
||||
usbconn_t *conn = NULL;
|
||||
int i;
|
||||
|
||||
cable_params = malloc( sizeof(generic_params_t) );
|
||||
|
||||
if (!cable_params)
|
||||
{
|
||||
free( cable );
|
||||
return 4;
|
||||
}
|
||||
|
||||
if(strcasecmp(params[0], "usb") != 0)
|
||||
{
|
||||
user_specified.name = params[0];
|
||||
}
|
||||
|
||||
/* parse arguments beyond the cable name */
|
||||
for (i = 1; i < paramc; i++)
|
||||
{
|
||||
if(strncasecmp("pid=", params[i], 4) == 0)
|
||||
{
|
||||
user_specified.pid = strtol( params[i] + 4, NULL, 10 );
|
||||
}
|
||||
else if(strncasecmp("vid=", params[i], 4) == 0)
|
||||
{
|
||||
user_specified.vid = strtol( params[i] + 4, NULL, 10 );
|
||||
}
|
||||
else if(strncasecmp("desc=", params[i], 5) == 0)
|
||||
{
|
||||
user_specified.desc = params[i] + 5;
|
||||
}
|
||||
else if(strncasecmp("driver=", params[i], 7) == 0)
|
||||
{
|
||||
user_specified.driver = params[i] + 7;
|
||||
}
|
||||
}
|
||||
|
||||
/* search usbconn driver list */
|
||||
for (i = 0; usbconn_drivers[i] && !conn; i++)
|
||||
{
|
||||
if ((user_specified.driver == NULL)
|
||||
|| (strcasecmp(user_specified.name, usbconn_drivers[i]->type) == 0))
|
||||
{
|
||||
int j;
|
||||
|
||||
/* search cable list */
|
||||
for (j = 0; usbconn_cables[j] && !conn; j++)
|
||||
{
|
||||
if((user_specified.name == NULL)
|
||||
|| (strcasecmp(user_specified.name, usbconn_cables[j]->name) == 0))
|
||||
{
|
||||
if(strcasecmp(usbconn_cables[j]->driver, usbconn_drivers[i]->type) == 0)
|
||||
{
|
||||
usbconn_cable_t cable_try = *(usbconn_cables[j]);
|
||||
|
||||
if(user_specified.vid >= 0) cable_try.vid = user_specified.vid;
|
||||
if(user_specified.pid >= 0) cable_try.pid = user_specified.pid;
|
||||
if(user_specified.desc != 0) cable_try.desc = user_specified.desc;
|
||||
|
||||
conn = usbconn_drivers[i]->connect( (const char **) ¶ms[1],
|
||||
paramc - 1, &cable_try );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!conn) {
|
||||
printf( _("Couldn't connect to suitable USB device.\n") );
|
||||
return 2;
|
||||
}
|
||||
|
||||
cable->link.usb = conn;
|
||||
cable->params = cable_params;
|
||||
cable->chain = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
generic_usbconn_free( cable_t *cable )
|
||||
{
|
||||
cable->link.usb->driver->free( cable->link.usb );
|
||||
free( cable->params );
|
||||
free( cable );
|
||||
}
|
||||
|
||||
void
|
||||
generic_usbconn_done( cable_t *cable )
|
||||
{
|
||||
usbconn_close( cable->link.usb );
|
||||
}
|
||||
|
||||
void
|
||||
generic_usbconn_help( const char *cablename )
|
||||
{
|
||||
printf( _(
|
||||
"Usage: cable %s [vid=VID] [pid=PID] [desc=DESC] [...]\n"
|
||||
"\n"
|
||||
"VID USB Device Vendor ID (hex, e.g. 0abc)\n"
|
||||
"PID USB Device Product ID (hex, e.g. 0abc)\n"
|
||||
"DESC Some string to match in description or serial no.\n"
|
||||
"\n"
|
||||
),
|
||||
cablename
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* $Id: generic.h 1002 2008-02-10 09:50:59Z kawk $
|
||||
*
|
||||
* Copyright (C) 2003 ETC s.r.o.
|
||||
*
|
||||
* 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 Marcel Telka <marcel@telka.sk>, 2003.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GENERIC_USBCONN_H
|
||||
#define GENERIC_USBCONN_H
|
||||
|
||||
#include "cable.h"
|
||||
#include "usbconn.h"
|
||||
|
||||
int generic_usbconn_connect( char *params[], cable_t *cable );
|
||||
void generic_usbconn_done( cable_t *cable );
|
||||
void generic_usbconn_help( const char *name );
|
||||
void generic_usbconn_free( cable_t *cable );
|
||||
|
||||
#endif /* GENERIC_H */
|
@ -0,0 +1,503 @@
|
||||
/*
|
||||
* $Id: jlink.c,v 1.8 2003/08/19 08:42:20 telka Exp $
|
||||
*
|
||||
* Segger J-Link cable driver
|
||||
*
|
||||
* Large portions of code were taken from the OpenOCD driver written by
|
||||
* Juergen Stuber, which in turn was based on Dominic Rath's and Benedikt
|
||||
* Sauter's usbprog.c. Therefore most of this code is actually
|
||||
*
|
||||
* Copyright (C) 2007 Juergen Stuber
|
||||
*
|
||||
* Modified to work in UrJTAG by K. Waschk in 2008.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "generic.h"
|
||||
#include "generic_usbconn.h"
|
||||
|
||||
#include "usbconn.h"
|
||||
#include "usbconn/libusb.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#include "cable.h"
|
||||
#include "chain.h"
|
||||
|
||||
#include "jtag.h"
|
||||
|
||||
#include <usb.h>
|
||||
#include <string.h>
|
||||
|
||||
#define INFO printf
|
||||
#define ERROR printf
|
||||
#define DEBUG printf
|
||||
|
||||
#define JLINK_WRITE_ENDPOINT 0x02
|
||||
#define JLINK_READ_ENDPOINT 0x81
|
||||
|
||||
#define JLINK_USB_TIMEOUT 100
|
||||
|
||||
#define JLINK_IN_BUFFER_SIZE 2064
|
||||
#define JLINK_OUT_BUFFER_SIZE 2064
|
||||
|
||||
/* Global USB buffers */
|
||||
static char usb_in_buffer[JLINK_IN_BUFFER_SIZE];
|
||||
static char usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
|
||||
|
||||
/* Constants for JLink command */
|
||||
#define JLINK_SPEED_COMMAND 0x05
|
||||
#define JLINK_TAP_SEQUENCE_COMMAND 0xcd
|
||||
#define JLINK_SET_SRST_LOW_COMMAND 0xdc
|
||||
#define JLINK_SET_SRST_HIGH_COMMAND 0xdd
|
||||
#define JLINK_SET_TRST_LOW_COMMAND 0xde
|
||||
#define JLINK_SET_TRST_HIGH_COMMAND 0xdf
|
||||
|
||||
#define JLINK_MAX_SPEED 12000
|
||||
|
||||
|
||||
/* Queue command functions */
|
||||
static void jlink_reset( cable_t *cable, int trst, int srst);
|
||||
static void jlink_simple_command( cable_t *cable, uint8_t command );
|
||||
|
||||
/* J-Link tap buffer functions */
|
||||
static void jlink_tap_init();
|
||||
static int jlink_tap_execute();
|
||||
static void jlink_tap_append_step(int tms, int tdi);
|
||||
|
||||
/* Jlink lowlevel functions */
|
||||
static int jlink_usb_message( cable_t *cable, int out_length, int in_length);
|
||||
static int jlink_usb_write( cable_t *cable, unsigned int out_length);
|
||||
static int jlink_usb_read( cable_t *cable );
|
||||
static void jlink_debug_buffer(uint8_t *buffer, int length);
|
||||
|
||||
|
||||
|
||||
void jlink_set_frequency( cable_t *cable, uint32_t frequency )
|
||||
{
|
||||
int result;
|
||||
int speed = frequency / 1E3;
|
||||
|
||||
if (1 <= speed && speed <= JLINK_MAX_SPEED)
|
||||
{
|
||||
usb_out_buffer[0] = JLINK_SPEED_COMMAND;
|
||||
usb_out_buffer[1] = (speed >> 0) & 0xff;
|
||||
usb_out_buffer[2] = (speed >> 8) & 0xff;
|
||||
|
||||
result = jlink_usb_write( cable, 3 );
|
||||
|
||||
if (result != 3)
|
||||
{
|
||||
ERROR("J-Link setting speed failed (%d)\n", result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO("Requested speed %dkHz exceeds maximum of %dkHz, ignored\n",
|
||||
speed, JLINK_MAX_SPEED);
|
||||
}
|
||||
}
|
||||
|
||||
void jlink_reset( cable_t *cable, int trst, int srst)
|
||||
{
|
||||
DEBUG("trst: %i, srst: %i\n", trst, srst);
|
||||
|
||||
/* Signals are active low */
|
||||
if (trst == 0)
|
||||
{
|
||||
jlink_simple_command( cable, JLINK_SET_TRST_HIGH_COMMAND);
|
||||
}
|
||||
else if (trst == 1)
|
||||
{
|
||||
jlink_simple_command( cable, JLINK_SET_TRST_LOW_COMMAND);
|
||||
}
|
||||
|
||||
if (srst == 0)
|
||||
{
|
||||
jlink_simple_command( cable, JLINK_SET_SRST_HIGH_COMMAND);
|
||||
}
|
||||
else if (srst == 1)
|
||||
{
|
||||
jlink_simple_command( cable, JLINK_SET_SRST_LOW_COMMAND);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void jlink_simple_command( cable_t *cable, uint8_t command)
|
||||
{
|
||||
int result;
|
||||
|
||||
DEBUG("simple_command: 0x%02x\n", command);
|
||||
|
||||
usb_out_buffer[0] = command;
|
||||
result = jlink_usb_write( cable, 1 );
|
||||
|
||||
if (result != 1)
|
||||
{
|
||||
ERROR("J-Link command 0x%02x failed (%d)\n", command, result);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* J-Link tap functions */
|
||||
|
||||
/* We use the maximal value observed */
|
||||
#define JLINK_TAP_BUFFER_SIZE 390
|
||||
|
||||
static int tap_length;
|
||||
static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE];
|
||||
static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE];
|
||||
|
||||
static int last_tdo;
|
||||
|
||||
static void jlink_tap_init()
|
||||
{
|
||||
tap_length = 0;
|
||||
}
|
||||
|
||||
static void jlink_tap_append_step(int tms, int tdi)
|
||||
{
|
||||
int index = tap_length >> 3;
|
||||
|
||||
if (index < JLINK_TAP_BUFFER_SIZE)
|
||||
{
|
||||
int bit_index = tap_length & 7;
|
||||
uint8_t bit = 1 << bit_index;
|
||||
|
||||
if(bit_index == 0)
|
||||
{
|
||||
tms_buffer[index] = 0;
|
||||
tdi_buffer[index] = 0;
|
||||
};
|
||||
|
||||
if(tms) tms_buffer[index] |= bit;
|
||||
if(tdi) tdi_buffer[index] |= bit;
|
||||
|
||||
tap_length++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("jlink_tap_append_step, overflow\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Pad and send a tap sequence to the device, and receive the answer.
|
||||
* For the purpose of padding we assume that we are in idle or pause state. */
|
||||
static int jlink_tap_execute( cable_t *cable )
|
||||
{
|
||||
int byte_length;
|
||||
int tms_offset;
|
||||
int tdi_offset;
|
||||
int i;
|
||||
int result;
|
||||
|
||||
if (tap_length > 0)
|
||||
{
|
||||
byte_length = (tap_length + 7) >> 3;
|
||||
usb_out_buffer[0] = JLINK_TAP_SEQUENCE_COMMAND;
|
||||
usb_out_buffer[1] = (tap_length >> 0) & 0xff;
|
||||
usb_out_buffer[2] = (tap_length >> 8) & 0xff;
|
||||
|
||||
tms_offset = 3;
|
||||
for (i = 0; i < byte_length; i++)
|
||||
{
|
||||
usb_out_buffer[tms_offset + i] = tms_buffer[i];
|
||||
}
|
||||
|
||||
tdi_offset = tms_offset + byte_length;
|
||||
for (i = 0; i < byte_length; i++)
|
||||
{
|
||||
usb_out_buffer[tdi_offset + i] = tdi_buffer[i];
|
||||
}
|
||||
|
||||
result = jlink_usb_message(
|
||||
cable,
|
||||
3 + 2 * byte_length,
|
||||
byte_length);
|
||||
|
||||
if (result == byte_length)
|
||||
{
|
||||
int bit_index = (tap_length - 1) & 7;
|
||||
uint8_t bit = 1 << bit_index;
|
||||
|
||||
last_tdo = ((usb_in_buffer[byte_length-1]) & bit ) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR(
|
||||
"jlink_tap_execute, wrong result %d, expected %d",
|
||||
result,
|
||||
byte_length);
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
jlink_tap_init();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* Send a message and receive the reply. */
|
||||
static int jlink_usb_message(
|
||||
cable_t *cable,
|
||||
int out_length,
|
||||
int in_length)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = jlink_usb_write( cable, out_length );
|
||||
if (result == out_length)
|
||||
{
|
||||
result = jlink_usb_read( cable );
|
||||
if (result == in_length)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR(
|
||||
"usb_bulk_read failed (requested=%d, result=%d)\n",
|
||||
in_length,
|
||||
result);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR(
|
||||
"usb_bulk_write failed (requested=%d, result=%d)\n",
|
||||
out_length,
|
||||
result);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* Write data from out_buffer to USB. */
|
||||
static int jlink_usb_write( cable_t *cable, unsigned int out_length )
|
||||
{
|
||||
int result;
|
||||
struct usb_dev_handle *jlink;
|
||||
jlink = ((libusb_param_t*)(cable->link.usb->params))->handle;
|
||||
|
||||
if (out_length > JLINK_OUT_BUFFER_SIZE)
|
||||
{
|
||||
ERROR("jlink_jtag_write illegal out_length=%d (max=%d)\n", out_length,
|
||||
JLINK_OUT_BUFFER_SIZE);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = usb_bulk_write(
|
||||
jlink,
|
||||
JLINK_WRITE_ENDPOINT,
|
||||
usb_out_buffer,
|
||||
out_length,
|
||||
JLINK_USB_TIMEOUT);
|
||||
|
||||
DEBUG("jlink_usb_write, out_length = %d, result = %d\n", out_length, result);
|
||||
jlink_debug_buffer(usb_out_buffer, out_length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* Read data from USB into in_buffer. */
|
||||
static int jlink_usb_read( cable_t *cable )
|
||||
{
|
||||
struct usb_dev_handle *jlink;
|
||||
jlink = ((libusb_param_t*)(cable->link.usb->params))->handle;
|
||||
|
||||
int result = usb_bulk_read(
|
||||
jlink,
|
||||
JLINK_READ_ENDPOINT,
|
||||
usb_in_buffer,
|
||||
JLINK_IN_BUFFER_SIZE,
|
||||
JLINK_USB_TIMEOUT);
|
||||
|
||||
DEBUG("jlink_usb_read, result = %d\n", result);
|
||||
jlink_debug_buffer(usb_in_buffer, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#define BYTES_PER_LINE 16
|
||||
|
||||
static void jlink_debug_buffer(uint8_t *buffer, int length)
|
||||
{
|
||||
char line[81];
|
||||
char s[4];
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < length; i += BYTES_PER_LINE)
|
||||
{
|
||||
snprintf(line, 5, "%04x", i);
|
||||
for (j = i; j < i + BYTES_PER_LINE && j < length; j++)
|
||||
{
|
||||
snprintf(s, 4, " %02x", buffer[j]);
|
||||
strcat(line, s);
|
||||
}
|
||||
DEBUG(line);
|
||||
DEBUG("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
jlink_init( cable_t *cable )
|
||||
{
|
||||
int result;
|
||||
struct usb_dev_handle *jlink;
|
||||
|
||||
if (usbconn_open( cable->link.usb )) return -1;
|
||||
|
||||
jlink = ((libusb_param_t*)(cable->link.usb->params))->handle;
|
||||
|
||||
jlink_tap_init();
|
||||
|
||||
result = jlink_usb_read( cable );
|
||||
if (result != 2 || usb_in_buffer[0] != 0x07 || usb_in_buffer[1] != 0x00)
|
||||
{
|
||||
INFO("J-Link initial read failed, don't worry (result=%d)\n", result);
|
||||
}
|
||||
|
||||
INFO("J-Link JTAG Interface ready\n");
|
||||
|
||||
jlink_set_frequency( cable, 4E6 );
|
||||
jlink_reset( cable, 0, 0);
|
||||
jlink_tap_init();
|
||||
|
||||
|
||||
PARAM_TRST(cable) = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int tdo_cache;
|
||||
|
||||
static void
|
||||
jlink_clock( cable_t *cable, int tms, int tdi, int n )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
jlink_tap_append_step(tms, tdi);
|
||||
}
|
||||
jlink_tap_execute( cable );
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
jlink_get_tdo( cable_t *cable )
|
||||
{
|
||||
// TODO: This is the TDO _before_ last clock occured
|
||||
// ... Anyone knows how to get the current TDO state?
|
||||
|
||||
return last_tdo;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
jlink_copy_out_data( cable_t *cable, int len, int offset, char *buf )
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
int bit = (1<<(i&7));
|
||||
int byte = i>>3;
|
||||
buf[offset+i] = (usb_in_buffer[byte] & bit) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
jlink_transfer( cable_t *cable, int len, char *in, char *out )
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for(j=0, i=0; i<len; i++)
|
||||
{
|
||||
jlink_tap_append_step(0, in[i]);
|
||||
|
||||
if(tap_length >= 8*JLINK_TAP_BUFFER_SIZE)
|
||||
{
|
||||
jlink_tap_execute( cable );
|
||||
if(out) jlink_copy_out_data( cable, i-j, j, out);
|
||||
j = i;
|
||||
}
|
||||
};
|
||||
if(tap_length > 0)
|
||||
{
|
||||
jlink_tap_execute( cable );
|
||||
if(out) jlink_copy_out_data( cable, i-j, j, out);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
jlink_set_trst( cable_t *cable, int trst )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
cable_driver_t jlink_cable_driver = {
|
||||
"jlink",
|
||||
N_("Segger/IAR J-Link, Atmel SAM-ICE and others."),
|
||||
generic_usbconn_connect,
|
||||
generic_disconnect,
|
||||
generic_usbconn_free,
|
||||
jlink_init,
|
||||
generic_usbconn_done,
|
||||
jlink_set_frequency,
|
||||
jlink_clock,
|
||||
jlink_get_tdo,
|
||||
jlink_transfer,
|
||||
jlink_set_trst,
|
||||
generic_get_trst,
|
||||
generic_flush_using_transfer,
|
||||
generic_usbconn_help
|
||||
};
|
||||
|
||||
usbconn_cable_t usbconn_cable_jlink = {
|
||||
"jlink", /* cable name */
|
||||
NULL, /* string pattern, not used */
|
||||
"libusb", /* usbconn driver */
|
||||
0x1366, /* VID */
|
||||
0x0101 /* PID */
|
||||
};
|
||||
|
||||
|
@ -1,292 +0,0 @@
|
||||
/*
|
||||
* $Id: ftdi.c,v 1.7 2003/08/19 09:05:25 telka Exp $
|
||||
*
|
||||
* Driver for Xilinx Platform Cable USB
|
||||
* Copyright (C) 2007 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, 2007.
|
||||
* Structure taken from ppdev.c, written by Marcel Telka, 2003.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
|
||||
#include <fcntl.h>
|
||||
#if __CYGWIN__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STROPTS_H
|
||||
#include <stropts.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <usb.h>
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct usb_device *find_xpcu(void)
|
||||
{
|
||||
struct usb_device *xpcu_dev = NULL;
|
||||
|
||||
if(usb_find_devices()<0)
|
||||
{
|
||||
perror("find_xpcu: usb_find_devices failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
|
||||
for (bus = usb_busses; bus && !xpcu_dev; bus = bus->next)
|
||||
{
|
||||
struct usb_device *dev;
|
||||
|
||||
for (dev = bus->devices; dev && !xpcu_dev; dev = dev->next)
|
||||
{
|
||||
if(dev->descriptor.idVendor == 0x3fd)
|
||||
{
|
||||
if(dev->descriptor.idProduct == 0x8)
|
||||
{
|
||||
xpcu_dev = dev;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Found Xilinx device with unknown PID %04X. No firmware loaded?\n",
|
||||
dev->descriptor.idProduct);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
return xpcu_dev;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int xpcu_init()
|
||||
{
|
||||
struct usb_device *xpcu_dev = find_xpcu();
|
||||
struct usb_dev_handle *xpcu;
|
||||
|
||||
if(xpcu_dev == NULL)
|
||||
{
|
||||
fprintf(stderr, "xpcu_reset: no device found\n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
xpcu = usb_open(xpcu_dev);
|
||||
if(xpcu == NULL)
|
||||
{
|
||||
perror("xpcu_reset: usb_open() failed");
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(usb_reset(xpcu) < 0)
|
||||
{
|
||||
perror("xpcu_reset: usb_reset() failed");
|
||||
return -1;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int xpcu_close(struct usb_dev_handle *xpcu)
|
||||
{
|
||||
usb_release_interface(xpcu, 0);
|
||||
usb_close(xpcu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int xpcu_request_28(struct usb_dev_handle *xpcu, int value)
|
||||
{
|
||||
/* Maybe clock speed setting? */
|
||||
|
||||
if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0028, value, NULL, 0, 1000)<0)
|
||||
{
|
||||
perror("usb_control_msg(0x28.x)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int xpcu_write_gpio(struct usb_dev_handle *xpcu, uint8_t bits)
|
||||
{
|
||||
if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0030, bits, NULL, 0, 1000)<0)
|
||||
{
|
||||
perror("usb_control_msg(0x30.0x00) (write port E)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int xpcu_read_gpio(struct usb_dev_handle *xpcu, uint8_t *bits)
|
||||
{
|
||||
if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0038, 0, (char*)bits, 1, 1000)<0)
|
||||
{
|
||||
perror("usb_control_msg(0x38.0x00) (read port E)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
int xpcu_read_firmware_version(struct usb_dev_handle *xpcu, uint16_t *buf)
|
||||
{
|
||||
if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0000, (char*)buf, 2, 1000)<0)
|
||||
{
|
||||
perror("usb_control_msg(0x50.0) (read_firmware_version)");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
int xpcu_read_cpld_version(struct usb_dev_handle *xpcu, uint16_t *buf)
|
||||
{
|
||||
if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0001, (char*)buf, 2, 1000)<0)
|
||||
{
|
||||
perror("usb_control_msg(0x50.1) (read_cpld_version)");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
int xpcu_raise_ioa5(struct usb_dev_handle *xpcu)
|
||||
{
|
||||
if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0018, 0x0000, NULL, 0, 1000)<0)
|
||||
{
|
||||
perror("usb_control_msg(0x18.0x00) (raise IOA.5");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
int xpcu_select_gpio(struct usb_dev_handle *xpcu, int chain)
|
||||
{
|
||||
if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0052, chain, NULL, 0, 1000)<0)
|
||||
{
|
||||
perror("usb_control_msg(0x52.x) (select gpio)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int xpcu_open(struct usb_dev_handle **xpcu)
|
||||
{
|
||||
uint16_t buf;
|
||||
struct usb_device *xpcu_dev = find_xpcu();
|
||||
|
||||
if(xpcu_dev == NULL)
|
||||
{
|
||||
fprintf(stderr, "xpcu_open: no device found\n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
*xpcu = usb_open(xpcu_dev);
|
||||
if(*xpcu == NULL)
|
||||
{
|
||||
perror("xpcu_open: usb_open() failed");
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(usb_claim_interface(*xpcu, 0) != 0)
|
||||
{
|
||||
perror("xpcu_open: usb_claim_interface failed");
|
||||
usb_close(*xpcu);
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
if(xpcu_request_28(*xpcu, 0x11)<0)
|
||||
{
|
||||
usb_close(*xpcu);
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(xpcu_write_gpio(*xpcu, 8)<0)
|
||||
{
|
||||
usb_close(*xpcu);
|
||||
return -1;
|
||||
};
|
||||
|
||||
/* Read firmware version (constant embedded in firmware) */
|
||||
|
||||
if(xpcu_read_firmware_version(*xpcu, &buf) < 0)
|
||||
{
|
||||
usb_close(*xpcu);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("firmware version = 0x%04X (%u)\n", buf, buf);
|
||||
};
|
||||
|
||||
/* Read CPLD version (via GPIF) */
|
||||
|
||||
if(xpcu_read_cpld_version(*xpcu, &buf) < 0)
|
||||
{
|
||||
usb_close(*xpcu);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("cable CPLD version = 0x%04X (%u)\n", buf, buf);
|
||||
if(buf == 0)
|
||||
{
|
||||
printf("Warning: version '0' can't be correct. Please try resetting the cable\n");
|
||||
};
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBUSB */
|
@ -1,273 +0,0 @@
|
||||
/*
|
||||
* $Id: ftdi.c,v 1.7 2003/08/19 09:05:25 telka Exp $
|
||||
*
|
||||
* Driver for Xilinx Platform Cable USB
|
||||
* Copyright (C) 2007 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, 2007.
|
||||
* Structure taken from ppdev.c, written by Marcel Telka, 2003.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
|
||||
#include <fcntl.h>
|
||||
#if __CYGWIN__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STROPTS_H
|
||||
#include <stropts.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "parport.h"
|
||||
#include "cable.h"
|
||||
|
||||
#include "xpcu.h"
|
||||
|
||||
typedef struct {
|
||||
char *serial;
|
||||
unsigned int vendor_id;
|
||||
unsigned int product_id;
|
||||
usb_dev_handle *dev;
|
||||
} xpcu_params_t;
|
||||
|
||||
parport_driver_t xpcu_pp_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 */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static parport_t *
|
||||
xpcu_pp_alloc( const char *vidpid )
|
||||
{
|
||||
xpcu_params_t *params = malloc( sizeof *params );
|
||||
parport_t *parport = malloc( sizeof *parport );
|
||||
port_node_t *node = malloc( sizeof *node );
|
||||
|
||||
if (!node || !parport || !params) {
|
||||
free( node );
|
||||
free( parport );
|
||||
free( params );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
params->product_id = 0;
|
||||
params->vendor_id = 0;
|
||||
params->serial = NULL;
|
||||
params->dev = 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 = &xpcu_pp_driver;
|
||||
parport->cable = NULL;
|
||||
|
||||
node->port = parport;
|
||||
node->next = ports;
|
||||
|
||||
ports = node;
|
||||
|
||||
return parport;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
xpcu_pp_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( ((xpcu_params_t *) port->params)->serial );
|
||||
free( port->params );
|
||||
free( port );
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
parport_t *
|
||||
xpcu_pp_connect( const char **par, int parnum )
|
||||
{
|
||||
port_node_t *pn;
|
||||
parport_t *parport;
|
||||
|
||||
|
||||
if (parnum != 1) {
|
||||
printf( _("Syntax error!\n") );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (pn = ports; pn; pn = pn->next)
|
||||
if (strcmp( pn->port->params, par[0] ) == 0) {
|
||||
printf( _("Disconnecting %s, device %s\n"), _(pn->port->cable->driver->description), par[0] );
|
||||
pn->port->cable->driver->disconnect( pn->port->cable );
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef TODO
|
||||
printf( _("Initializing %s, device %s\n"), _(cable_drivers[i]->description), par[0] );
|
||||
#else
|
||||
printf( _("Initializing device %s\n"), par[0] );
|
||||
#endif
|
||||
|
||||
parport = xpcu_pp_alloc( par[0] );
|
||||
if (!parport) {
|
||||
printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return parport;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
xpcu_pp_open( parport_t *parport )
|
||||
{
|
||||
xpcu_params_t *p = parport->params;
|
||||
|
||||
usb_init();
|
||||
|
||||
if(usb_find_busses()<0)
|
||||
{
|
||||
perror("usb_find_busses failed");
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(xpcu_init() < 0)
|
||||
{
|
||||
fprintf (stderr, "can't initialize XPCU\n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(xpcu_open(&(p->dev)) < 0)
|
||||
{
|
||||
fprintf (stderr, "can't open XPCU\n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
if(xpcu_raise_ioa5(p->dev)<0) return -1;
|
||||
|
||||
/* access external chain by default */
|
||||
if(xpcu_select_gpio(p->dev, 0)<0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
xpcu_pp_close( parport_t *parport )
|
||||
{
|
||||
xpcu_params_t *p = parport->params;
|
||||
xpcu_close(p->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
xpcu_pp_set_data( parport_t *parport, uint8_t data )
|
||||
{
|
||||
xpcu_params_t *p = parport->params;
|
||||
|
||||
if(xpcu_write_gpio(p->dev, data) < 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
xpcu_pp_get_data( parport_t *parport )
|
||||
{
|
||||
unsigned char d;
|
||||
xpcu_params_t *p = parport->params;
|
||||
|
||||
if(xpcu_read_gpio(p->dev, &d) < 0) return 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
xpcu_pp_get_status( parport_t *parport )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
xpcu_pp_set_control( parport_t *parport, uint8_t data )
|
||||
{
|
||||
xpcu_params_t *p = parport->params;
|
||||
|
||||
if(xpcu_select_gpio(p->dev, data)<0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
parport_driver_t xpcu_pp_driver = {
|
||||
"xpcu",
|
||||
xpcu_pp_connect,
|
||||
xpcu_pp_free,
|
||||
xpcu_pp_open,
|
||||
xpcu_pp_close,
|
||||
xpcu_pp_set_data,
|
||||
xpcu_pp_get_data,
|
||||
xpcu_pp_get_status,
|
||||
xpcu_pp_set_control
|
||||
};
|
||||
|
||||
#endif /* HAVE_LIBUSB */
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* $Id: usbconn.c 851 2007-12-15 22:53:24Z kawk $
|
||||
*
|
||||
* Copyright (C) 2008 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 <kawk>, 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "usbconn.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
extern usbconn_driver_t usbconn_libusb_driver;
|
||||
#endif /* HAVE_LIBUSB */
|
||||
|
||||
usbconn_driver_t *usbconn_drivers[] = {
|
||||
#ifdef HAVE_LIBUSB
|
||||
&usbconn_libusb_driver,
|
||||
#endif /* HAVE_LIBUSB */
|
||||
NULL /* last must be NULL */
|
||||
};
|
||||
|
||||
int
|
||||
usbconn_open( usbconn_t *conn )
|
||||
{
|
||||
return conn->driver->open( conn );
|
||||
}
|
||||
|
||||
int
|
||||
usbconn_close( usbconn_t *conn )
|
||||
{
|
||||
return conn->driver->close( conn );
|
||||
}
|
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* $Id: ftdi.c,v 1.7 2003/08/19 09:05:25 telka Exp $
|
||||
*
|
||||
* Link driver for accessing USB devices via libusb
|
||||
*
|
||||
* Copyright (C) 2008 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, 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
|
||||
#include <fcntl.h>
|
||||
#if __CYGWIN__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STROPTS_H
|
||||
#include <stropts.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "parport.h"
|
||||
#include "cable.h"
|
||||
#include "usbconn.h"
|
||||
|
||||
typedef struct {
|
||||
struct usb_device *dev;
|
||||
struct usb_dev_handle *handle;
|
||||
} libusb_param_t;
|
||||
|
||||
usbconn_driver_t usbconn_libusb_driver;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
libusb_match_desc(struct usb_device *dev, char *desc)
|
||||
{
|
||||
int r = 0;
|
||||
char buf[256];
|
||||
usb_dev_handle *handle;
|
||||
|
||||
if(desc == NULL) return 1;
|
||||
|
||||
handle = usb_open(dev);
|
||||
if(handle == NULL)
|
||||
{
|
||||
perror("libusb: usb_open() failed");
|
||||
return 0;
|
||||
}
|
||||
if(dev->descriptor.iManufacturer)
|
||||
{
|
||||
r = usb_get_string_simple(handle, dev->descriptor.iManufacturer, buf, sizeof(buf));
|
||||
if(r > 0)
|
||||
{
|
||||
if(strstr(buf, desc) == NULL) r = 0;
|
||||
}
|
||||
}
|
||||
if(r <= 0 && dev->descriptor.iProduct)
|
||||
{
|
||||
r = usb_get_string_simple(handle, dev->descriptor.iProduct, buf, sizeof(buf));
|
||||
if(r > 0)
|
||||
{
|
||||
if(strstr(buf, desc) == NULL) r = 0;
|
||||
}
|
||||
}
|
||||
if(r <= 0 && dev->descriptor.iSerialNumber)
|
||||
{
|
||||
r = usb_get_string_simple(handle, dev->descriptor.iSerialNumber, buf, sizeof(buf));
|
||||
if(r > 0)
|
||||
{
|
||||
if(strstr(buf, desc) == NULL) r = 0;
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
return r > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
usbconn_t *
|
||||
usbconn_libusb_connect( const char **param, int paramc, usbconn_cable_t *template )
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *found_dev = NULL;
|
||||
usbconn_t *libusb_conn;
|
||||
libusb_param_t *libusb_params;
|
||||
|
||||
usb_init();
|
||||
if(usb_find_busses()<0)
|
||||
{
|
||||
perror("libusb: usb_find_busses failed");
|
||||
return NULL;
|
||||
}
|
||||
if(usb_find_devices()<0)
|
||||
{
|
||||
perror("libusb: usb_find_devices failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (bus = usb_busses; bus && !found_dev; bus = bus->next)
|
||||
{
|
||||
struct usb_device *dev;
|
||||
|
||||
for (dev = bus->devices; dev && !found_dev; dev = dev->next)
|
||||
{
|
||||
if(((template->vid<0)||(dev->descriptor.idVendor == template->vid))
|
||||
&&((template->pid<0)||(dev->descriptor.idProduct == template->pid)))
|
||||
{
|
||||
if(libusb_match_desc(dev, template->desc))
|
||||
{
|
||||
found_dev = dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found_dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
libusb_conn = malloc( sizeof(usbconn_t) );
|
||||
libusb_params = malloc(sizeof(libusb_param_t));
|
||||
if(libusb_params == NULL || libusb_conn == NULL)
|
||||
{
|
||||
printf(_("Out of memory\n"));
|
||||
free(libusb_params);
|
||||
free(libusb_conn);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
libusb_params->dev = found_dev;
|
||||
libusb_params->handle = NULL;
|
||||
libusb_conn->params = libusb_params;
|
||||
libusb_conn->driver = &usbconn_libusb_driver;
|
||||
libusb_conn->cable = NULL;
|
||||
|
||||
return libusb_conn;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
usbconn_libusb_open( usbconn_t *conn )
|
||||
{
|
||||
libusb_param_t *p = conn->params;
|
||||
|
||||
p->handle = usb_open(p->dev);
|
||||
if(p->handle == NULL)
|
||||
{
|
||||
perror("libusb: usb_open() failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 1
|
||||
usb_set_configuration(p->handle,
|
||||
p->dev->config[0].bConfigurationValue);
|
||||
#endif
|
||||
if(usb_claim_interface(p->handle, 0) != 0)
|
||||
{
|
||||
perror("libusb: usb_claim_interface failed");
|
||||
usb_close(p->handle);
|
||||
p->handle = NULL;
|
||||
}
|
||||
#if 1
|
||||
else
|
||||
{
|
||||
usb_set_altinterface(p->handle, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if(p->handle == NULL)
|
||||
{
|
||||
/* TODO: disconnect? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
usbconn_libusb_close( usbconn_t *conn )
|
||||
{
|
||||
libusb_param_t *p = conn->params;
|
||||
if(p->handle != NULL)
|
||||
{
|
||||
usb_release_interface(p->handle, 0);
|
||||
usb_close(p->handle);
|
||||
}
|
||||
p->handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
usbconn_libusb_free( usbconn_t *conn )
|
||||
{
|
||||
free( conn->params );
|
||||
free( conn );
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
usbconn_driver_t usbconn_libusb_driver = {
|
||||
"libusb",
|
||||
usbconn_libusb_connect,
|
||||
usbconn_libusb_free,
|
||||
usbconn_libusb_open,
|
||||
usbconn_libusb_close
|
||||
};
|
||||
|
||||
#endif /* HAVE_LIBUSB */
|
Loading…
Reference in New Issue