|
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 |
*/
|