/* * Copyright (c) 2002,03 Bernd Walter Computer Technology * http://www.bwct.de * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Thanks to FTDI for providing me the programming specs. * * $URL: https://devel.bwct.de/svn/projects/usb/fdti232/eeprom/trunk/ftdi-eeprom.c $ * $Date: 2003-02-16 05:02:35 +0100 (Sun, 16 Feb 2003) $ * $Author: ticso $ * $Rev: 309 $ */ #include #include #include #include #include #include #include #include #include #include #include #include "ftdi-eeprom.h" static int fd; static int do_write; /* * ftdi-eeprom: programm to write 93c46 EEPROM devices on * FTDI usb chips over usb */ int main(int argc, char *argv[]) { int ch; static char *devname; static int addr; union { u_int8_t *d8; u_int16_t *d16; } data; int wptr; u_int16_t vendor_id, product_id, release_number; int bus_powered, remote_wakeup; u_int8_t current; char* manufacturer_string; char* product_string; char* serial_string; u_int16_t checksum, tmpsum; while ((ch = getopt(argc, argv, "wa:f:")) != -1) switch (ch) { case 'a': addr = strtol(optarg, NULL, 0); break; case 'f': devname = optarg; break; case 'w': do_write = 1; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if (devname == NULL) { usage(); /* NOTREACHED */ } fd = open(devname, O_RDWR); if (fd < 0) { fprintf(stderr, "Failed to open device: %s %s\n", devname, strerror(errno)); exit(1); } data.d8 = (u_int8_t*)malloc(128); if (data.d8 == NULL) { fprintf(stderr, "failed to malloc 128 Bytes\n"); exit(1); } bzero(data.d8, 128); if (do_write) { if (argc != 9) { free(data.d8); usage(); /* NOTREACHED */ } vendor_id = strtol(argv[0], NULL, 0); product_id = strtol(argv[1], NULL, 0); release_number = strtol(argv[2], NULL, 0); bus_powered = (strcmp(argv[3], "1") == 0) ? 1 : 0; remote_wakeup = (strcmp(argv[4], "1") == 0) ? 1 : 0; current = strtol(argv[5], NULL, 0) / 2; manufacturer_string = argv[6]; product_string = argv[7]; serial_string = argv[8]; data.d16[0x2/2] = vendor_id; data.d16[0x4/2] = product_id; data.d16[0x6/2] = release_number; data.d8[0x8 ^ END8] = 0x80; data.d8[0x8 ^ END8] |= (bus_powered) ? 0 : 0x40; data.d8[0x8 ^ END8] |= (remote_wakeup) ? 0x20 : 0; data.d8[0x9 ^ END8] = current; wptr = 0x14; data.d8[0xe ^ END8] = wptr + 0x80; data.d8[0xf ^ END8] = strlen(manufacturer_string) * 2 + 2; data.d8[wptr++ ^ END8] = data.d8[0xf ^ END8]; data.d8[wptr++ ^ END8] = 0x03; while (*manufacturer_string != '\0') { data.d16[wptr/2] = *(manufacturer_string++); wptr += 2; } data.d8[0x10 ^ END8] = wptr + 0x80; data.d8[0x11 ^ END8] = strlen(product_string) * 2 + 2; data.d8[wptr++ ^ END8] = data.d8[0x11 ^ END8]; data.d8[wptr++ ^ END8] = 0x03; while (*product_string != '\0') { data.d16[wptr/2] = *(product_string++); wptr += 2; } data.d8[0x12 ^ END8] = wptr + 0x80; data.d8[0x13 ^ END8] = strlen(serial_string) * 2 + 2; data.d8[wptr++ ^ END8] = data.d8[0x13 ^ END8]; data.d8[wptr++ ^ END8] = 0x03; while (*serial_string != '\0') { data.d16[wptr/2] = *(serial_string++); wptr += 2; } checksum = 0xaaaa; for (wptr = 0; wptr < 0x3f; wptr++) { writecell(wptr, data.d16[wptr], addr); tmpsum = data.d16[wptr] ^ checksum; checksum = tmpsum << 1; if (tmpsum & 0x8000) checksum |= 0x01; } writecell(wptr, checksum, addr); } free(data.d8); close(fd); return 0; } int writecell (int num, u_int16_t val, int addr) { struct usb_ctl_request request; int res; request.ucr_addr = addr; request.ucr_request.bmRequestType = 0x40; request.ucr_request.bRequest = 0x91; request.ucr_request.wValue[0] = val & 0xff; request.ucr_request.wValue[1] = val >> 8; request.ucr_request.wIndex[0] = num & 0xff; request.ucr_request.wIndex[1] = num >> 8; request.ucr_request.wLength[0] = 0x00; request.ucr_request.wLength[1] = 0x00; request.ucr_data = NULL; request.ucr_flags = 0; request.ucr_actlen = 0; if (addr) res = ioctl(fd, USB_REQUEST, &request); else res = ioctl(fd, USB_DO_REQUEST, &request); if (res < 0) { fprintf(stderr, "failed to write value %d into cell %d %s\n", val, num, strerror(errno)); } return res; } void usage() { fprintf(stderr, "ftdi-eeprom V1.0\n"); fprintf(stderr, "(c) 2002,03 by Bernd Walter Computer Technology\n"); fprintf(stderr, "All rights reserved.\n"); fprintf(stderr, "usage: ftdi-eeprom -f dev [-a addr] -w vendor_id product_id \\\n" " release_number bus_powered remote_wakeup current \\\n" " manufacturer_string product_string serial_string\n"); exit(1); }