Blame main.c

Packit 7488c9
/*
Packit 7488c9
 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
Packit 7488c9
 * Copyright (c) 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
Packit 7488c9
 * Copyright (c) 2008 Roger Williams (rawqux@users.sourceforge.net)
Packit 7488c9
 *
Packit 7488c9
 *    This source code is free software; you can redistribute it
Packit 7488c9
 *    and/or modify it in source code form under the terms of the GNU
Packit 7488c9
 *    General Public License as published by the Free Software
Packit 7488c9
 *    Foundation; either version 2 of the License, or (at your option)
Packit 7488c9
 *    any later version.
Packit 7488c9
 *
Packit 7488c9
 *    This program is distributed in the hope that it will be useful,
Packit 7488c9
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 7488c9
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 7488c9
 *    GNU General Public License for more details.
Packit 7488c9
 *
Packit 7488c9
 *    You should have received a copy of the GNU General Public License
Packit 7488c9
 *    along with this program; if not, write to the Free Software
Packit 7488c9
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Packit 7488c9
 */
Packit 7488c9
#ident "$Id: main.c,v 1.10 2008/10/13 21:25:29 dbrownell Exp $"
Packit 7488c9
Packit 7488c9
/*
Packit 7488c9
 * This program supports loading firmware into a target USB device
Packit 7488c9
 * that is discovered and referenced by the hotplug usb agent. It can
Packit 7488c9
 * also do other useful things, like set the permissions of the device
Packit 7488c9
 * and create a symbolic link for the benefit of applications that are
Packit 7488c9
 * looking for the device.
Packit 7488c9
 *
Packit 7488c9
 *     -I <path>       -- Download this firmware (intel hex)
Packit 7488c9
 *     -t <type>       -- uController type: an21, fx, fx2, fx2lp
Packit 7488c9
 *     -s <path>       -- use this second stage loader
Packit 7488c9
 *     -c <byte>       -- Download to EEPROM, with this config byte
Packit 7488c9
 *
Packit 7488c9
 *     -L <path>       -- Create a symbolic link to the device.
Packit 7488c9
 *     -m <mode>       -- Set the permissions on the device after download.
Packit 7488c9
 *     -D <path>       -- Use this device, instead of $DEVICE
Packit 7488c9
 *
Packit 7488c9
 *     -V              -- Print version ID for program
Packit 7488c9
 *
Packit 7488c9
 * This program is intended to be started by hotplug scripts in
Packit 7488c9
 * response to a device appearing on the bus. It therefore also
Packit 7488c9
 * expects these environment variables which are passed by hotplug to
Packit 7488c9
 * its sub-scripts:
Packit 7488c9
 *
Packit 7488c9
 *     DEVICE=<path>
Packit 7488c9
 *         This is the path to the device is /proc/bus/usb. It is the
Packit 7488c9
 *         complete path to the device, that I can pass to open and
Packit 7488c9
 *         manipulate as a USB device.
Packit 7488c9
 */
Packit 7488c9
Packit 7488c9
# include  <stdlib.h>
Packit 7488c9
# include  <stdio.h>
Packit 7488c9
# include  <getopt.h>
Packit 7488c9
# include  <string.h>
Packit 7488c9
Packit 7488c9
# include  <sys/types.h>
Packit 7488c9
# include  <sys/stat.h>
Packit 7488c9
# include  <fcntl.h>
Packit 7488c9
# include  <unistd.h>
Packit 7488c9
Packit 7488c9
# include  "ezusb.h"
Packit 7488c9
Packit 7488c9
#ifndef	FXLOAD_VERSION
Packit 7488c9
#	define FXLOAD_VERSION (__DATE__ " (development)")
Packit 7488c9
#endif
Packit 7488c9
Packit 7488c9
#include <errno.h>
Packit 7488c9
#include <syslog.h>
Packit 7488c9
#include <stdarg.h>
Packit 7488c9
Packit 7488c9
Packit 7488c9
static int dosyslog=0;
Packit 7488c9
Packit 7488c9
void logerror(const char *format, ...)
Packit 7488c9
    __attribute__ ((format (__printf__, 1, 2)));
Packit 7488c9
Packit 7488c9
void logerror(const char *format, ...)
Packit 7488c9
{
Packit 7488c9
    va_list ap;
Packit 7488c9
    va_start(ap, format);
Packit 7488c9
Packit 7488c9
    if(dosyslog)
Packit 7488c9
	vsyslog(LOG_ERR, format, ap);
Packit 7488c9
    else
Packit 7488c9
	vfprintf(stderr, format, ap);
Packit 7488c9
    va_end(ap);
Packit 7488c9
}
Packit 7488c9
Packit 7488c9
int main(int argc, char*argv[])
Packit 7488c9
{
Packit 7488c9
      const char	*link_path = 0;
Packit 7488c9
      const char	*ihex_path = 0;
Packit 7488c9
      const char	*device_path = getenv("DEVICE");
Packit 7488c9
      const char	*type = 0;
Packit 7488c9
      const char	*stage1 = 0;
Packit 7488c9
      mode_t		mode = 0;
Packit 7488c9
      int		opt;
Packit 7488c9
      int		config = -1;
Packit 7488c9
Packit 7488c9
      while ((opt = getopt (argc, argv, "2vV?D:I:L:c:lm:s:t:")) != EOF)
Packit 7488c9
      switch (opt) {
Packit 7488c9
Packit 7488c9
	  case '2':		// original version of "-t fx2"
Packit 7488c9
	    type = "fx2";
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 'D':
Packit 7488c9
	    device_path = optarg;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 'I':
Packit 7488c9
	    ihex_path = optarg;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 'L':
Packit 7488c9
	    link_path = optarg;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 'V':
Packit 7488c9
	    puts (FXLOAD_VERSION);
Packit 7488c9
	    return 0;
Packit 7488c9
Packit 7488c9
	  case 'c':
Packit 7488c9
	    config = strtoul (optarg, 0, 0);
Packit 7488c9
	    if (config < 0 || config > 255) {
Packit 7488c9
		logerror("illegal config byte: %s\n", optarg);
Packit 7488c9
		goto usage;
Packit 7488c9
	    }
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 'l':
Packit 7488c9
	    openlog(argv[0], LOG_CONS|LOG_NOWAIT|LOG_PERROR, LOG_USER);
Packit 7488c9
	    dosyslog=1;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 'm':
Packit 7488c9
	    mode = strtoul(optarg,0,0);
Packit 7488c9
	    mode &= 0777;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 's':
Packit 7488c9
	    stage1 = optarg;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 't':
Packit 7488c9
	    if (strcmp (optarg, "an21")		// original AnchorChips parts
Packit 7488c9
		    && strcmp (optarg, "fx")	// updated Cypress versions
Packit 7488c9
		    && strcmp (optarg, "fx2")	// Cypress USB 2.0 versions
Packit 7488c9
		    && strcmp (optarg, "fx2lp")	// updated FX2
Packit 7488c9
		    ) {
Packit 7488c9
		logerror("illegal microcontroller type: %s\n", optarg);
Packit 7488c9
		goto usage;
Packit 7488c9
	    }
Packit 7488c9
	    type = optarg;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case 'v':
Packit 7488c9
	    verbose++;
Packit 7488c9
	    break;
Packit 7488c9
Packit 7488c9
	  case '?':
Packit 7488c9
	  default:
Packit 7488c9
	    goto usage;
Packit 7488c9
Packit 7488c9
      }
Packit 7488c9
Packit 7488c9
      if (config >= 0) {
Packit 7488c9
	    if (type == 0) {
Packit 7488c9
		logerror("must specify microcontroller type %s",
Packit 7488c9
				"to write EEPROM!\n");
Packit 7488c9
		goto usage;
Packit 7488c9
	    }
Packit 7488c9
	    if (!stage1 || !ihex_path) {
Packit 7488c9
		logerror("need 2nd stage loader and firmware %s",
Packit 7488c9
				"to write EEPROM!\n");
Packit 7488c9
		goto usage;
Packit 7488c9
	    }
Packit 7488c9
	    if (link_path || mode) {
Packit 7488c9
		logerror("links and modes not set up when writing EEPROM\n");
Packit 7488c9
		goto usage;
Packit 7488c9
	    }
Packit 7488c9
      }
Packit 7488c9
Packit 7488c9
      if (!device_path) {
Packit 7488c9
	    logerror("no device specified!\n");
Packit 7488c9
usage:
Packit 7488c9
	    fputs ("usage: ", stderr);
Packit 7488c9
	    fputs (argv [0], stderr);
Packit 7488c9
	    fputs (" [-vV] [-l] [-t type] [-D devpath]\n", stderr);
Packit 7488c9
	    fputs ("\t\t[-I firmware_hexfile] ", stderr);
Packit 7488c9
	    fputs ("[-s loader] [-c config_byte]\n", stderr);
Packit 7488c9
	    fputs ("\t\t[-L link] [-m mode]\n", stderr);
Packit 7488c9
	    fputs ("... [-D devpath] overrides DEVICE= in env\n", stderr);
Packit 7488c9
	    fputs ("... device types:  one of an21, fx, fx2, fx2lp\n", stderr);
Packit 7488c9
	    fputs ("... at least one of -I, -L, -m is required\n", stderr);
Packit 7488c9
	    return -1;
Packit 7488c9
      }
Packit 7488c9
Packit 7488c9
      if (ihex_path) {
Packit 7488c9
	    int fd = open(device_path, O_RDWR);
Packit 7488c9
	    int status;
Packit 7488c9
	    int	fx2;
Packit 7488c9
Packit 7488c9
	    if (fd == -1) {
Packit 7488c9
		logerror("%s : %s\n", strerror(errno), device_path);
Packit 7488c9
		return -1;
Packit 7488c9
	    }
Packit 7488c9
Packit 7488c9
	    if (type == 0) {
Packit 7488c9
		type = "fx";	/* an21-compatible for most purposes */
Packit 7488c9
		fx2 = 0;
Packit 7488c9
	    } else if (strcmp (type, "fx2lp") == 0)
Packit 7488c9
                fx2 = 2;
Packit 7488c9
            else
Packit 7488c9
                fx2 = (strcmp (type, "fx2") == 0);
Packit 7488c9
Packit 7488c9
	    if (verbose)
Packit 7488c9
		logerror("microcontroller type: %s\n", type);
Packit 7488c9
Packit 7488c9
	    if (stage1) {
Packit 7488c9
		/* first stage:  put loader into internal memory */
Packit 7488c9
		if (verbose)
Packit 7488c9
		    logerror("1st stage:  load 2nd stage loader\n");
Packit 7488c9
		status = ezusb_load_ram (fd, stage1, fx2, 0);
Packit 7488c9
		if (status != 0)
Packit 7488c9
		    return status;
Packit 7488c9
Packit 7488c9
		/* second stage ... write either EEPROM, or RAM.  */
Packit 7488c9
		if (config >= 0)
Packit 7488c9
		    status = ezusb_load_eeprom (fd, ihex_path, type, config);
Packit 7488c9
		else
Packit 7488c9
		    status = ezusb_load_ram (fd, ihex_path, fx2, 1);
Packit 7488c9
		if (status != 0)
Packit 7488c9
		    return status;
Packit 7488c9
	    } else {
Packit 7488c9
		/* single stage, put into internal memory */
Packit 7488c9
		if (verbose)
Packit 7488c9
		    logerror("single stage:  load on-chip memory\n");
Packit 7488c9
		status = ezusb_load_ram (fd, ihex_path, fx2, 0);
Packit 7488c9
		if (status != 0)
Packit 7488c9
		    return status;
Packit 7488c9
	    }
Packit 7488c9
Packit 7488c9
	    /* some firmware won't renumerate, but typically it will.
Packit 7488c9
	     * link and chmod only make sense without renumeration...
Packit 7488c9
	     */
Packit 7488c9
      }
Packit 7488c9
Packit 7488c9
      if (link_path) {
Packit 7488c9
	    int rc = unlink(link_path);
Packit 7488c9
	    rc = symlink(device_path, link_path);
Packit 7488c9
	    if (rc == -1) {
Packit 7488c9
		  logerror("%s : %s\n", strerror(errno), link_path);
Packit 7488c9
		  return -1;
Packit 7488c9
	    }
Packit 7488c9
      }
Packit 7488c9
Packit 7488c9
      if (mode != 0) {
Packit 7488c9
	    int rc = chmod(device_path, mode);
Packit 7488c9
	    if (rc == -1) {
Packit 7488c9
		  logerror("%s : %s\n", strerror(errno), link_path);
Packit 7488c9
		  return -1;
Packit 7488c9
	    }
Packit 7488c9
      }
Packit 7488c9
Packit 7488c9
      if (!ihex_path && !link_path && !mode) {
Packit 7488c9
	    logerror("missing request! (firmware, link, or mode)\n");
Packit 7488c9
	    return -1;
Packit 7488c9
      }
Packit 7488c9
Packit 7488c9
      return 0;
Packit 7488c9
}
Packit 7488c9
Packit 7488c9
Packit 7488c9
/*
Packit 7488c9
 * $Log: main.c,v $
Packit 7488c9
 * Revision 1.10  2008/10/13 21:25:29  dbrownell
Packit 7488c9
 * Whitespace fixes.
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.9  2008/10/13 21:23:23  dbrownell
Packit 7488c9
 * From Roger Williams <roger@qux.com>:  FX2LP support
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.8  2005/01/11 03:58:02  dbrownell
Packit 7488c9
 * From Dirk Jagdmann <doj@cubic.org>:  optionally output messages to
Packit 7488c9
 * syslog instead of stderr.
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.7  2002/04/12 00:28:22  dbrownell
Packit 7488c9
 * support "-t an21" to program EEPROMs for those microcontrollers
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.6  2002/04/02 05:26:15  dbrownell
Packit 7488c9
 * version display now noiseless (-V);
Packit 7488c9
 * '-?' (usage info) convention now explicit
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.5  2002/02/26 20:10:28  dbrownell
Packit 7488c9
 * - "-s loader" option for 2nd stage loader
Packit 7488c9
 * - "-c byte" option to write EEPROM with 2nd stage
Packit 7488c9
 * - "-V" option to dump version code
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.4  2002/01/17 14:19:28  dbrownell
Packit 7488c9
 * fix warnings
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.3  2001/12/27 17:54:04  dbrownell
Packit 7488c9
 * forgot an important character :)
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.2  2001/12/27 17:43:29  dbrownell
Packit 7488c9
 * fail on firmware download errors; add "-v" flag
Packit 7488c9
 *
Packit 7488c9
 * Revision 1.1  2001/06/12 00:00:50  stevewilliams
Packit 7488c9
 *  Added the fxload program.
Packit 7488c9
 *  Rework root makefile and hotplug.spec to install in prefix
Packit 7488c9
 *  location without need of spec file for install.
Packit 7488c9
 *
Packit 7488c9
 */