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

Subversion Repositories gecko3

[/] [gecko3/] [trunk/] [GECKO3COM/] [gecko3com-fw/] [gecko3-util/] [gecko3-util.c] - Rev 33

Go to most recent revision | Compare with Previous | Blame | View Log

/* GECKO3COM
 *
 * Copyright (C) 2008 by
 *   ___    ____  _   _
 *  (  _`\ (  __)( ) ( )   
 *  | (_) )| (_  | |_| |   Berne University of Applied Sciences
 *  |  _ <'|  _) |  _  |   School of Engineering and
 *  | (_) )| |   | | | |   Information Technology
 *  (____/'(_)   (_) (_)
 *
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */
 
/*********************************************************************/
/** \file     gecko3-util.c
 *********************************************************************
 * \brief     simple small helper tool for GECKO3COM
 *
 *            with this tool you can set the serial number, hw revision
 *            and FPGA type of a GECKO3COM driven device. 
 *            mainly this is the GECKO3main but the firmware could be
 *            used on other boards. \n
 *            Based on existing code of dfu-util and testlibusb
 *
 * \warning   does only work on little endian machines! 
 *
 * \author    Christoph Zimmermann bfh.ch
 * \date      2009-1-23 first version
 * \date      2009-8-25 fixed some little bugs. option --device works now, 
 *                      counts connected GECKO3 boards now correct.
 *
*/
 
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <usb.h>
#include <errno.h>
 
#include "gecko3-util.h"
 
#define VERSION               "1.1"
 
 
/* global variables */
int debug;
static int verbose = 0;
 
/* type definitions */
struct usb_vendprod {
	u_int16_t vendor;
	u_int16_t product;
};
 
struct gecko3_if {
	u_int16_t vendor;
	u_int16_t product;
	u_int8_t configuration;
	u_int8_t interface;
	u_int8_t altsetting;
	unsigned int flags;
	struct usb_device *dev;
 
	struct usb_dev_handle *dev_handle;
};
 
static struct option opts[] = {
	{ "help", 0, 0, 'h' },
	{ "version", 0, 0, 'V' },
	{ "verbose", 0, 0, 'v' },
	{ "device", 1, 0, 'd' },
	{ "transfer-size", 1, 0, 't' },
	{ "set-serial", 1, 0, 's' },
	{ "set-hw-rev", 1, 0, 'r' },
	{ "set-fpga-type", 1, 0, 'f' },
	{ "set-fpga-idcode", 1, 0, 'i' },
};
 
/*----------------------------------------------------------------------------*/
/* start of functions block */
 
/* define a portable function for reading a 16bit little-endian word */
unsigned short get_int16_le(const void *p)
{
    const unsigned char *cp = p;
 
    return ( cp[0] ) | ( ((unsigned short)cp[1]) << 8 );
}
 
static int _get_first_cb(struct gecko3_if *dif, void *v)
{
	struct gecko3_if *v_dif = v;
 
	memcpy(v_dif, dif, sizeof(*v_dif)-sizeof(struct usb_dev_handle *));
 
	/* return a value that makes find_gecko3_if return immediately */
	return 1;
}
 
 
/* Iterate over all matching devices within system */
static int iterate_gecko3_devices(struct gecko3_if *dif,
    int (*action)(struct usb_device *dev, void *user), void *user)
{
	struct usb_bus *usb_bus;
	struct usb_device *dev;
 
	/* Walk the tree and find our device. */
	for (usb_bus = usb_get_busses(); NULL != usb_bus;
	     usb_bus = usb_bus->next) {
		for (dev = usb_bus->devices; NULL != dev; dev = dev->next) {
			int retval;
 
			if (dif && \
		    	    (dev->descriptor.idVendor == dif->vendor && \
			     dev->descriptor.idProduct == dif->product)) {
			  retval = action(dev, user);
			  if (retval)
			    return retval;
			}
		}
	}
	return 0;
}
 
 
static int found_gecko3_device(struct usb_device *dev, void *user)
{
	struct gecko3_if *dif = user;
 
	dif->dev = dev;
	return 1;
}
 
 
/* Find the first device, save it in gecko3_if->dev */
static int get_first_gecko3_device(struct gecko3_if *dif)
{
	return iterate_gecko3_devices(dif, found_gecko3_device, dif);
}
 
 
static int count_one_gecko3_device(struct usb_device *dev, void *user)
{
	int *num = user;
 
	(*num)++;
	return 0;
}
 
 
/* Count matching devices within system */
static int count_gecko3_devices(struct gecko3_if *dif)
{
	int num_found = 0;
 
	iterate_gecko3_devices(dif, count_one_gecko3_device, &num_found);
	return num_found;
}
 
static int parse_vendprod(struct usb_vendprod *vp, const char *str)
{
	unsigned long vend, prod;
	const char *colon;
 
	colon = strchr(str, ':');
	if (!colon || strlen(colon) < 2)
		return -EINVAL;
 
	vend = strtoul(str, NULL, 16);
	prod = strtoul(colon+1, NULL, 16);
 
	if (vend > 0xffff || prod > 0xffff)
		return -EINVAL;
 
	vp->vendor = vend;
	vp->product = prod;
 
	return 0;
}
 
static void help(void)
{
	printf("Usage: gecko3-util [options] ...\n"
		"  -h --help\t\t\tPrint this help message\n"
		"  -V --version\t\t\tPrint the version number\n"
		"  -v --verbose\n"
		"  -d --device vendor:product\tSpecify Vendor/Product ID of GECKO3COM device\n"
		"  -t --transfer-size\t\tSpecify the number of bytes per USB Transfer\n"
		"  -s --set-serial\t\tWrite the Serial Number. Expects a String as argument\n"
		"  -r --set-hw-rev\t\tWrite the Hardware Revision. Only one digit\n"
		"  -f --set-fpga-type\t\tWrite the FPGA type. Formated as ASCII String\n"
		"  -i --set-fpga-idcode\t\tWrite the FPGA JTAG IDCODE. This is a 32bit Integer value\n"
		);
}
 
static void print_version(void)
{
	printf("gecko3-util version %s\n", VERSION);
}
 
/*----------------------------------------------------------------------------*/
 
int main(int argc, char **argv)
{
	struct usb_vendprod vendprod;
	struct gecko3_if _rt_dif, _dif, *dif = &_dif;
	char serial_num[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	unsigned int hw_rev;
	char fpga_type[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	char fpga_idcode[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	int num_devs;
	unsigned int transfer_size = 0;
	const char *little_endian_data;
	int ret;
 
	printf("gecko3-util - (C) 2009 by Berne University of Applied Science\n"
	       "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n");
 
	memset(dif, 0, sizeof(*dif));
	dif->vendor = GECKO3COM_VID;
	dif->product = GECKO3COM_PID;
	dif->flags = 0;
 
	usb_init();
	//usb_set_debug(255);
	usb_find_busses();
	usb_find_devices();
 
	while (1) {
		int c, option_index = 0;
		c = getopt_long(argc, argv, "hVvd:t:s:r:i:f:", opts,
				&option_index);
		if (c == -1)
			break;
 
		switch (c) {
		case 'h':
			help();
			exit(0);
			break;
		case 'V':
			print_version();
			exit(0);
			break;
		case 'v':
			verbose = 1;
			break;
		case 'd':
			/* Parse device */
			if (parse_vendprod(&vendprod, optarg) < 0) {
				fprintf(stderr, "unable to parse `%s'\n", optarg);
				exit(2);
			}
			dif->vendor = vendprod.vendor;
			dif->product = vendprod.product;
			break;
		case 't':
			transfer_size = atoi(optarg);
			break;
		case 's':
		        dif->flags |= FL_SET_SERIAL;
			strcpy(serial_num, optarg);
			break;
		case 'i':
		        dif->flags |= FL_SET_FPGA_IDCODE;
			strcpy(fpga_idcode, optarg);
			break;
		case 'r':
		        dif->flags |= FL_SET_HW_REV;
			hw_rev = atoi(optarg);
			break;
		case 'f':
		        dif->flags |= FL_SET_FPGA_TYPE;
			strcpy(fpga_type, optarg);
			break;
		default:
		        help();
		        exit(2);
		}
	}
 
 
	if (dif->flags == 0) {
		fprintf(stderr, "You need to specify one of -s, -r, -f or -i\n\n");
		help();
		exit(2);
	}
 
	num_devs = count_gecko3_devices(dif);
	if (num_devs == 0) {
		fprintf(stderr, "No GECKO3COM USB device found\n");
		exit(1);
	} else if (num_devs > 1) {
		/* We do not support more than one GECKO3COM device */
		fprintf(stderr, "More than one GECKO3COM USB device found. "
		       "We can handle only one device at the same time. "
		       "Please disconnect all but one device\n");
		exit(3);
	}
	if (!get_first_gecko3_device(dif))
		exit(3);
 
	/* We have exactly one device. It's usb_device is now in dif->dev */
 
	printf("Opening USB Device 0x%04x:0x%04x...\n", dif->vendor, dif->product);
	dif->dev_handle = usb_open(dif->dev);
	if (!dif->dev_handle) {
		fprintf(stderr, "Cannot open device: %s\n", usb_strerror());
		exit(1);
	}
 
	printf("Claiming USB Interface...\n");
	if (usb_claim_interface(dif->dev_handle,GECKO3COM_IF) < 0) {
	        fprintf(stderr, "Cannot claim interface: %s\n",
			usb_strerror());
		exit(1);
	}
 
	/* write Serial Number to the device */
	if (dif->flags & FL_SET_SERIAL) {
	       printf("Write Serial Number...\n");
	       ret = usb_control_msg(dif->dev_handle, 
				     bmRT_TYPE_VENDOR | bmRT_DIR_OUT,  /* bmRequestType */
				     VRQ_SET_SERIAL,                   /* bRequest      */
				     0,                                /* wValue        */
				     0,                                /* wIndex        */
				     serial_num,                       /* Data          */
				     SERIAL_NO_LEN,                    /* wLength       */
				     TIMEOUT);
	       if (ret < 0) {
		       fprintf(stderr, "Cannot write Serial Number: %s\n",
			       usb_strerror());
		       exit(1);
	       }
	}
 
	/* write Hardware Revision to the device */
	if (dif->flags & FL_SET_HW_REV) {
	       printf("Write Hardware Revision...\n");
	       ret = usb_control_msg(dif->dev_handle, 
				     bmRT_TYPE_VENDOR | bmRT_DIR_OUT,  /* bmRequestType */
				     VRQ_SET_HW_REV,                   /* bRequest      */
				     0,                                /* wValue        */
				     0,                                /* wIndex        */
				     (char*)(&hw_rev),                 /* Data          */
				     1,                                /* wLength       */
				     TIMEOUT);
	       if (ret < 0) {
		       fprintf(stderr, "Cannot write Hardware Revision: %s\n",
			       usb_strerror());
		       exit(1);
	       }
	}
 
	/* write FPGA Type to the device */
	if (dif->flags & FL_SET_FPGA_TYPE) {
	       printf("Write FPGA Type...\n");
	       ret = usb_control_msg(dif->dev_handle, 
				     bmRT_TYPE_VENDOR | bmRT_DIR_OUT,  /* bmRequestType */
				     VRQ_SET_FPGA_TYPE,                /* bRequest      */
				     0,                                /* wValue        */
				     0,                                /* wIndex        */
				     fpga_type,                        /* Data          */
				     FPGA_TYPE_LEN,                    /* wLength       */
				     TIMEOUT);
	       if (ret < 0) {
		       fprintf(stderr, "Cannot write FPGA Type: %s\n",
			       usb_strerror());
		       exit(1);
	       }
	}
 
	/* write FPGA IDCODE to the device */
	if (dif->flags & FL_SET_FPGA_IDCODE) {
	       printf("Write FPGA IDCODE...\n");
	       ret = usb_control_msg(dif->dev_handle, 
				     bmRT_TYPE_VENDOR | bmRT_DIR_OUT,  /* bmRequestType */
				     VRQ_SET_FPGA_IDCODE,              /* bRequest      */
				     0,                                /* wValue        */
				     0,                                /* wIndex        */
				     fpga_idcode,                      /* Data          */
				     FPGA_IDCODE_LEN,                  /* wLength       */
				     TIMEOUT);
	       if (ret < 0) {
		       fprintf(stderr, "Cannot write FPGA IDCODE: %s\n",
			       usb_strerror());
		       exit(1);
	       }
	}
 
	printf("We're done. Cleaning up...\n");
	if (usb_release_interface(dif->dev_handle, GECKO3COM_IF) < 0) {
	        fprintf(stderr, "Cannot release interface: %s\n",
			usb_strerror());
		exit(1);
	}
	if (usb_close(dif->dev_handle) < 0) {
	        fprintf(stderr, "Cannot close USB device: %s\n",
			usb_strerror());
		exit(1);
	}
	printf("Finished\n");
	exit(0);
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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