From 65066704be0ab9b534c70f1b93c734bf538328d7 Mon Sep 17 00:00:00 2001 From: Oron Peled Date: Thu, 15 Mar 2012 20:45:57 +0000 Subject: [PATCH] xpp: clobber fpga_load * It was replaced long ago by astribank_hexload/astribank_tool/astribank_allow * It hasn't been used for several releases now, nor updated. * Time to move into the eternal bit-bucket. * Left (very) few strings as a tribute... Signed-off-by: Oron Peled Acked-by: Tzafrir Cohen git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10504 17933a7a-c749-41c5-a318-cba88f637d49 --- xpp/Makefile | 9 +- xpp/README.Astribank | 24 +- xpp/astribank_hexload.8 | 14 +- xpp/fpga_load.8 | 86 ---- xpp/fpga_load.c | 1052 --------------------------------------- 5 files changed, 20 insertions(+), 1165 deletions(-) delete mode 100644 xpp/fpga_load.8 delete mode 100644 xpp/fpga_load.c diff --git a/xpp/Makefile b/xpp/Makefile index 6fa04a4..8cbfae9 100644 --- a/xpp/Makefile +++ b/xpp/Makefile @@ -80,12 +80,12 @@ TARGETS = .perlcheck astribank_is_starting PROG_INSTALL = astribank_is_starting MAN_INSTALL = $(PROG_INSTALL:%=%.8) ifeq (1,$(PBX_USB)) -TARGETS += fpga_load \ +TARGETS += \ astribank_tool \ astribank_hexload \ astribank_allow \ test_parse -PROG_INSTALL += fpga_load astribank_tool astribank_hexload astribank_allow +PROG_INSTALL += astribank_tool astribank_hexload astribank_allow endif ifneq (,$(PERLLIBDIR)) PROG_INSTALL += $(PERL_SCRIPTS) @@ -122,9 +122,6 @@ endif CFLAGS += -I. -Ixtalk -fpga_load: fpga_load.o hexfile.o -fpga_load: LIBS+=$(EXTRA_LIBS) $(USB_LIB) - astribank_hexload: $(ABHEXLOAD_OBJS) astribank_hexload: LIBS+=$(EXTRA_LIBS) $(USB_LIB) astribank_hexload: CFLAGS+=$(OCT_CFLAGS) @@ -138,8 +135,6 @@ astribank_allow: LIBS+=$(EXTRA_LIBS) $(USB_LIB) astribank_is_starting: astribank_is_starting.o astribank_is_starting: LIBS+=$(EXTRA_LIBS) -fpga_load.o: CFLAGS+=-D_GNU_SOURCE # We use memrchr() - hex2iic: hex2iic.o iic.o hexfile.o test_parse: test_parse.o hexfile.o diff --git a/xpp/README.Astribank b/xpp/README.Astribank index 7f61886..f606881 100644 --- a/xpp/README.Astribank +++ b/xpp/README.Astribank @@ -45,7 +45,8 @@ Building and Installation ------------------------- Apart from the standard DAHDI build requirements, you also need: -* *libusb development headers* to build the fpga_load firmware loader. +* *libusb development headers* to build the Astribank firmware tools + (astribank_tool, astribank_hexload, astribank_allow). This is typically the package libusb-dev on Debian (and derivatives like Ubuntu) or libusb-devel on RedHat (and derivatives like CentOS/Trixbox). @@ -561,9 +562,9 @@ Check USB level status. You can use one of the following utilities for it: - If lsusb shows the Product ID as *11x1* - only the USB firmware is loaded and not the FPGA firmware is loaded. If this is still the case after a while - either the firmware loading has failed or you don't have - fpga_load. Make sure you have libusb-dev(el) installed when - building DAHDI. After you have installed it, you may need to re-run - ./configure . + astribank_hexload/astribank_tool. Make sure you have libusb-dev(el) + installed when building DAHDI. After you have installed it, you may need + to re-run ./configure . - It should list all of your Astribank devices. If it doesn't (for more than period of time needed for the initial firmware loading) - Check that the Astribank is connected indeed. @@ -698,7 +699,7 @@ Reset the firmware: Or disconnect the Astribank from the power and reocnnect. On some older versions of the USB firmware resetting the firmware (or any operation of -fpga_load) would fail if the driver is loaded. Hence you would need to +astribank_tool) would fail if the driver is loaded. Hence you would need to run `rmmod xpp_usb` . In the end, reload the drivers. @@ -960,9 +961,9 @@ disconnects and then connects again itself with USB Product ID 11x1 (and a new device number). In the second stage, the "FPGA" firmware is loaded. -The second-stage firmware loading is performed by using program fpga_load, -which is built in the directory xpp/utils and then copied to folder -/usr/sbin during DAHDI installation. +The second-stage firmware loading is performed by using program +astribank_hexload and astribank_tool, which are built in the directory +xpp/utils and then copied to folder /usr/sbin during DAHDI installation. The command syntax is similar to the syntax of fxload. You can use the following command in order to load the FPGA firmware manually: @@ -978,13 +979,6 @@ following command in order to load the FPGA firmware manually: # reenumerate (disconnect and reconnect) astribank_tool -D /dev/bus/usb/MMM/NNN -n -With older USB firmwares (before the one included in e.g. dahdi-linux -2.2) you needed to use instead of all the above: - - # pick the right name according to the device ID. FPGA_1151.hex is for - # 115x Astribanks: - fpga_load -D /dev/bus/usb/MMM/NNN -I /usr/share/dahdi/FPGA_1151.hex - Please note, that NNN value differs from that that was used for the fxload command due to the fact that device has "reconnected" itself with another Product ID number. So you need to run lsusb again and get diff --git a/xpp/astribank_hexload.8 b/xpp/astribank_hexload.8 index 7024ba5..76fa491 100644 --- a/xpp/astribank_hexload.8 +++ b/xpp/astribank_hexload.8 @@ -17,11 +17,15 @@ astribank_hexload \- Xorcom Astribank (xpp) firmware loader .SH DESCRIPTION .B astribank_hexload -is a second-stage firmware loader for Xorcom Astribanks. Note that some -older models use fpga_load(8) instead. +is a second-stage firmware loader for Xorcom Astribanks. -It is used to load a file in the Intel HEX format into a Xorcom -Astribank. It can be used to load either an FPGA firmware or a PIC +Note that some very old models use fpga_load(8) instead. +This legacy tool hasn't been used for several releases. +It can be found in version 2.6 and below of dahdi-tools. + +The astribank_hexload(8) program is used to load a file in the +Intel HEX format into a Xorcom Astribank. +It can be used to load either an FPGA firmware or a PIC firmware. It is normally run by the script xpp_fxloader. .SH OPTIONS @@ -92,7 +96,7 @@ what you'd normally use for FXS, FXO and T1. .RE .SH SEE ALSO -fxload(8), lsusb(8), astribank_tool(8), fpga_load(8) +fxload(8), lsusb(8), astribank_tool(8) .SH AUTHOR This manual page was written by Tzafrir Cohen . diff --git a/xpp/fpga_load.8 b/xpp/fpga_load.8 deleted file mode 100644 index dd21db0..0000000 --- a/xpp/fpga_load.8 +++ /dev/null @@ -1,86 +0,0 @@ -.TH "FPGA_LOAD" "8" "16 April 2006" "" "" - -.SH NAME -fpga_load \- Xorcom Astribank (xpp) firmware tool -.SH SYNOPSIS - -.B fpga_load -[\fB-g\fR] [\fB-r\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR - -.B fpga_load -[\fB-g\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR \fB-I \fIfirmware.hex\fR [\fB-b \fIdump.bin\fR] [\fB-i\fR] - -.B fpga_load -h - -.SH DESCRIPTION -.B fpga_load -loads the FPGA firmware to the Xorcom Astribank device. -The syntax resembles that of fxload(8). - -.SH OPTIONS -.B -b -.I dump.bin -.RS -Before writing firmware, bump the processed binary file to -.I dump.bin\fR. -.RE - -.B -D -.I DEVICE -.RS -Required. The device to read from/write to. On modern UDEV-based system -this is usually /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, -where \fIbus_num\fR and \fIdevice_num\fR are the first two numbers in the -output of lsusb(8). -On older systems that use usbfs, it is usually -/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR. -.RE - -.B -r -.RS -Reset the Astribank and renumerate its USB connection to power on product ID. -.RE - -.B -g -.RS -Dump all eeprom data to standard output. -.RE - -.B -I -.I fireware_file -.RS -The firmware file to write to the device. -.RE - -.B -i -.RS -Show information about the firmware file (valid only with \fB-I\fR option). -Example: -.PP - ./FPGA_1151.hex: Version=3297 Checksum=58270 - -In particular, the calculated checksum should match the output of \fIsum(1)\fR -on the binary firmware file generated by the \fB-b\fR option. -.RE - -.B -v -.RS -Increase verbosity. May be used multiple times. -.RE - -.B -h -.RS -Displays usage message. -.RE - -.SH SEE ALSO -fxload(8), lsusb(8) - -.SH AUTHOR -This manual page was written by Tzafrir Cohen . -Permission is granted to copy, distribute and/or modify this document under -the terms of the GNU General Public License, Version 2 any -later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public -License can be found in /usr/share/common-licenses/GPL. diff --git a/xpp/fpga_load.c b/xpp/fpga_load.c deleted file mode 100644 index e120b26..0000000 --- a/xpp/fpga_load.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2006-2008, Xorcom - * - * All rights reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hexfile.h" - -static const char rcsid[] = "$Id$"; - -#define ERR(fmt, arg...) do { \ - if(verbose >= LOG_ERR) \ - fprintf(stderr, "%s: ERROR (%d): " fmt, \ - progname, __LINE__, ## arg); \ - } while(0); -#define INFO(fmt, arg...) do { \ - if(verbose >= LOG_INFO) \ - fprintf(stderr, "%s: " fmt, \ - progname, ## arg); \ - } while(0); -#define DBG(fmt, arg...) do { \ - if(verbose >= LOG_DEBUG) \ - fprintf(stderr, "%s: DBG: " fmt, \ - progname, ## arg); \ - } while(0); - -static int verbose = LOG_WARNING; -static char *progname; -static int disconnected = 0; - -#define MAX_HEX_LINES 10000 -#define PACKET_SIZE 512 -#define EEPROM_SIZE 16 -#define LABEL_SIZE 8 -#define TIMEOUT 5000 - - -/* My device parameters */ -#define MY_EP_OUT 0x04 -#define MY_EP_IN 0x88 - -#define FPGA_EP_OUT 0x02 -#define FPGA_EP_IN 0x86 - -/* USB firmware types */ -#define USB_11xx 0 -#define USB_FIRMWARE_II 1 - -#define TYPE_ENTRY(t,ni,n,ne,out,in,...) \ - [t] = { \ - .type_code = (t), \ - .num_interfaces = (ni), \ - .my_interface_num = (n), \ - .num_endpoints = (ne), \ - .my_ep_in = (in), \ - .my_ep_out = (out), \ - .name = #t, \ - .endpoints = { __VA_ARGS__ }, \ - } - -static const struct astribank_type { - int type_code; - int num_interfaces; - int my_interface_num; - int num_endpoints; - int my_ep_out; - int my_ep_in; - char *name; - int endpoints[4]; /* for matching */ -} astribank_types[] = { - TYPE_ENTRY(USB_11xx, 1, 0, 4, MY_EP_OUT, MY_EP_IN, - FPGA_EP_OUT, - MY_EP_OUT, - FPGA_EP_IN, - MY_EP_IN), - TYPE_ENTRY(USB_FIRMWARE_II, 2, 1, 2, MY_EP_OUT, MY_EP_IN, - MY_EP_OUT, - MY_EP_IN), -}; -#undef TYPE_ENTRY - -enum fpga_load_packet_types { - PT_STATUS_REPLY = 0x01, - PT_DATA_PACKET = 0x01, -#ifdef XORCOM_INTERNAL - PT_EEPROM_SET = 0x04, -#endif - PT_EEPROM_GET = 0x08, - PT_RENUMERATE = 0x10, - PT_RESET = 0x20, - PT_BAD_COMMAND = 0xAA -}; - -struct myeeprom { - uint8_t source; - uint16_t vendor; - uint16_t product; - uint8_t release_major; - uint8_t release_minor; - uint8_t reserved; - uint8_t label[LABEL_SIZE]; -} PACKED; - -struct fpga_packet_header { - struct { - uint8_t op; - } PACKED header; - union { - struct { - uint16_t seq; - uint8_t status; - } PACKED status_reply; - struct { - uint16_t seq; - uint8_t reserved; - uint8_t data[ZERO_SIZE]; - } PACKED data_packet; - struct { - struct myeeprom data; - } PACKED eeprom_set; - struct { - struct myeeprom data; - } PACKED eeprom_get; - } d; -} PACKED; - -enum fpga_load_status { - FW_FAIL_RESET = 1, - FW_FAIL_TRANS = 2, - FW_TRANS_OK = 4, - FW_CONFIG_DONE = 8 -}; - -struct my_usb_device { - struct usb_device *dev; - usb_dev_handle *handle; - int my_interface_num; - int my_ep_out; - int my_ep_in; - char iManufacturer[BUFSIZ]; - char iProduct[BUFSIZ]; - char iSerialNumber[BUFSIZ]; - char iInterface[BUFSIZ]; - int is_usb2; - struct myeeprom eeprom; - const struct astribank_type *abtype; -}; - -const char *load_status2str(enum fpga_load_status s) -{ - switch(s) { - case FW_FAIL_RESET: return "FW_FAIL_RESET"; - case FW_FAIL_TRANS: return "FW_FAIL_TRANS"; - case FW_TRANS_OK: return "FW_TRANS_OK"; - case FW_CONFIG_DONE: return "FW_CONFIG_DONE"; - default: return "UNKNOWN"; - } -} - -/* return 1 if: - * - str has a number - * - It is larger than 0 - * - It equals num - */ -int num_matches(int num, const char* str) { - int str_val = atoi(str); - if (str_val <= 0) - return 0; - return (str_val == num); -} - -struct usb_device *dev_of_path(const char *path) -{ - struct usb_bus *bus; - struct usb_device *dev; - char dirname[PATH_MAX]; - char filename[PATH_MAX]; - const char *p; - int bnum; - int dnum; - int ret; - - assert(path != NULL); - if(access(path, F_OK) < 0) { - perror(path); - return NULL; - } - /* Find last '/' */ - if((p = (const char *)memrchr(path, '/', strlen(path))) == NULL) { - ERR("Missing a '/' in %s\n", path); - return NULL; - } - /* Get the device number */ - ret = sscanf(p + 1, "%d", &dnum); - if(ret != 1) { - ERR("Path tail is not a device number: '%s'\n", p); - return NULL; - } - /* Search for a '/' before that */ - p = (const char *)memrchr(path, '/', p - path); - if(p == NULL) - p = path; /* Relative path */ - else - p++; /* skip '/' */ - /* Get the bus number */ - ret = sscanf(p, "%d", &bnum); - if(ret != 1) { - ERR("Path tail is not a bus number: '%s'\n", p); - return NULL; - } - sprintf(dirname, "%03d", bnum); - sprintf(filename, "%03d", dnum); - for (bus = usb_busses; bus; bus = bus->next) { - if (! num_matches(bnum, bus->dirname)) - //if(strcmp(bus->dirname, dirname) != 0) - continue; - for (dev = bus->devices; dev; dev = dev->next) { - //if(strcmp(dev->filename, filename) == 0) - if (num_matches(dnum, dev->filename)) - return dev; - } - } - ERR("no usb device match '%s'\n", path); - return NULL; -} - -int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *handle) -{ - char tmp[BUFSIZ]; - int ret; - - if (!item) - return 0; - ret = usb_get_string_simple(handle, item, tmp, BUFSIZ); - if (ret <= 0) - return ret; - return snprintf(buf, len, "%s", tmp); -} - -void my_usb_device_cleanup(struct my_usb_device *mydev) -{ - assert(mydev != NULL); - if(!mydev->handle) { - return; /* Nothing to do */ - } - if(!disconnected) { - if(usb_release_interface(mydev->handle, mydev->abtype->my_interface_num) != 0) { - ERR("Releasing interface: usb: %s\n", usb_strerror()); - } - } - if(usb_close(mydev->handle) != 0) { - ERR("Closing device: usb: %s\n", usb_strerror()); - } - disconnected = 1; - mydev->handle = NULL; -} - -static void show_device_info(const struct my_usb_device *mydev) -{ - const struct myeeprom *eeprom; - uint8_t data[LABEL_SIZE + 1]; - - assert(mydev != NULL); - eeprom = &mydev->eeprom; - memset(data, 0, LABEL_SIZE + 1); - memcpy(data, eeprom->label, LABEL_SIZE); - printf("USB Firmware Type: [%s]\n", mydev->abtype->name); - printf("USB iManufacturer: [%s]\n", mydev->iManufacturer); - printf("USB iProduct: [%s]\n", mydev->iProduct); - printf("USB iSerialNumber: [%s]\n", mydev->iSerialNumber); - printf("EEPROM Source: 0x%02X\n", eeprom->source); - printf("EEPROM Vendor: 0x%04X\n", eeprom->vendor); - printf("EEPROM Product: 0x%04X\n", eeprom->product); - printf("EEPROM Release: %d.%03d\n", eeprom->release_major, eeprom->release_minor); - printf("EEPROM Label: HEX(%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X) [%s]\n", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7], data); -} - -void dump_packet(const char *msg, const char *buf, int len) -{ - int i; - - for(i = 0; i < len; i++) - INFO("%s: %2d> 0x%02X\n", msg, i, (uint8_t)buf[i]); -} - -int send_usb(const char *msg, struct my_usb_device *mydev, struct fpga_packet_header *phead, int len, int timeout) -{ - char *p = (char *)phead; - int ret; - - if(verbose >= LOG_DEBUG) - dump_packet(msg, p, len); - if(mydev->my_ep_out & USB_ENDPOINT_IN) { - ERR("send_usb called with an input endpoint 0x%x\n", mydev->my_ep_out); - return -EINVAL; - } - ret = usb_bulk_write(mydev->handle, mydev->my_ep_out, p, len, timeout); - if(ret < 0) { - /* - * If the device was gone, it may be the - * result of renumeration. Ignore it. - */ - if(ret != -ENODEV) { - ERR("bulk_write to endpoint 0x%x failed: %s\n", mydev->my_ep_out, usb_strerror()); - dump_packet("send_usb[ERR]", p, len); - } else { - disconnected = 1; - my_usb_device_cleanup(mydev); - } - return ret; - } else if(ret != len) { - ERR("bulk_write to endpoint 0x%x short write: %s\n", mydev->my_ep_out, usb_strerror()); - dump_packet("send_usb[ERR]", p, len); - return -EFAULT; - } - return ret; -} - -int recv_usb(const char *msg, struct my_usb_device *mydev, char *buf, size_t len, int timeout) -{ - int ret; - - if(mydev->my_ep_in & USB_ENDPOINT_OUT) { - ERR("recv_usb called with an output endpoint 0x%x\n", mydev->my_ep_in); - return -EINVAL; - } - ret = usb_bulk_read(mydev->handle, mydev->my_ep_in, buf, len, timeout); - if(ret < 0) { - ERR("bulk_read from endpoint 0x%x failed: %s\n", mydev->my_ep_in, usb_strerror()); - return ret; - } - if(verbose >= LOG_DEBUG) - dump_packet(msg, buf, ret); - return ret; -} - -int flush_read(struct my_usb_device *mydev) -{ - char tmpbuf[BUFSIZ]; - int ret; - - memset(tmpbuf, 0, BUFSIZ); - ret = recv_usb("flush_read", mydev, tmpbuf, sizeof(tmpbuf), TIMEOUT); - if(ret < 0 && ret != -ETIMEDOUT) { - ERR("ret=%d\n", ret); - return ret; - } else if(ret > 0) { - DBG("Got %d bytes:\n", ret); - dump_packet(__FUNCTION__, tmpbuf, ret); - } - return 0; -} - -#ifdef XORCOM_INTERNAL -int eeprom_set(struct my_usb_device *mydev, const struct myeeprom *eeprom) -{ - int ret; - int len; - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - - DBG("%s Start...\n", __FUNCTION__); - assert(mydev != NULL); - phead->header.op = PT_EEPROM_SET; - memcpy(&phead->d.eeprom_set.data, eeprom, EEPROM_SIZE); - len = sizeof(phead->d.eeprom_set) + sizeof(phead->header.op); - ret = send_usb("eeprom_set[W]", mydev, phead, len, TIMEOUT); - if(ret < 0) - return ret; - ret = recv_usb("eeprom_set[R]", mydev, buf, sizeof(buf), TIMEOUT); - if(ret <= 0) - return ret; - phead = (struct fpga_packet_header *)buf; - if(phead->header.op == PT_BAD_COMMAND) { - ERR("Firmware rejected PT_EEPROM_SET command\n"); - return -EINVAL; - } else if(phead->header.op != PT_EEPROM_SET) { - ERR("Got unexpected reply op=%d\n", phead->header.op); - return -EINVAL; - } - return 0; -} -#endif - -int eeprom_get(struct my_usb_device *mydev) -{ - int ret; - int len; - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - struct myeeprom *eeprom; - - assert(mydev != NULL); - eeprom = &mydev->eeprom; - DBG("%s Start...\n", __FUNCTION__); - phead->header.op = PT_EEPROM_GET; - len = sizeof(phead->header.op); /* warning: sending small packet */ - ret = send_usb("eeprom_get[W]", mydev, phead, len, TIMEOUT); - if(ret < 0) - return ret; - ret = recv_usb("eeprom_get[R]", mydev, buf, sizeof(buf), TIMEOUT); - if(ret <= 0) - return ret; - phead = (struct fpga_packet_header *)buf; - if(phead->header.op == PT_BAD_COMMAND) { - ERR("PT_BAD_COMMAND\n"); - return -EINVAL; - } else if(phead->header.op != PT_EEPROM_GET) { - ERR("Got unexpected reply op=%d\n", phead->header.op); - return -EINVAL; - } - memcpy(eeprom, &phead->d.eeprom_get.data, EEPROM_SIZE); - return 0; -} - -int send_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq) -{ - int ret; - int len; - uint8_t *data; - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - enum fpga_load_status status; - - assert(mydev != NULL); - assert(hexline != NULL); - if(hexline->d.content.header.tt != TT_DATA) { - DBG("Non data record %d type = %d\n", seq, hexline->d.content.header.tt); - return 0; - } - len = hexline->d.content.header.ll; /* don't send checksum */ - data = hexline->d.content.tt_data.data; - phead->header.op = PT_DATA_PACKET; - phead->d.data_packet.seq = seq; - phead->d.data_packet.reserved = 0x00; - memcpy(phead->d.data_packet.data, data, len); - len += sizeof(hexline->d.content.header); - DBG("%04d+\r", seq); - ret = send_usb("hexline[W]", mydev, phead, len, TIMEOUT); - if(ret < 0) - return ret; - ret = recv_usb("hexline[R]", mydev, buf, sizeof(buf), TIMEOUT); - if(ret <= 0) - return ret; - DBG("%04d-\r", seq); - phead = (struct fpga_packet_header *)buf; - if(phead->header.op != PT_STATUS_REPLY) { - ERR("Got unexpected reply op=%d\n", phead->header.op); - dump_packet("hexline[ERR]", buf, ret); - return -EINVAL; - } - status = (enum fpga_load_status)phead->d.status_reply.status; - switch(status) { - case FW_TRANS_OK: - case FW_CONFIG_DONE: - break; - case FW_FAIL_RESET: - case FW_FAIL_TRANS: - ERR("status reply %s (%d)\n", load_status2str(status), status); - dump_packet("hexline[ERR]", buf, ret); - return -EPROTO; - default: - ERR("Unknown status reply %d\n", status); - dump_packet("hexline[ERR]", buf, ret); - return -EPROTO; - } - return 0; -} - -//. returns > 0 - ok, the number of lines sent -//. returns < 0 - error number -int send_splited_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq, uint8_t maxwidth) -{ - struct hexline *extraline; - int linessent = 0; - int allocsize; - int extra_offset = 0; - unsigned int this_line = 0; - uint8_t bytesleft = 0; - - assert(mydev != NULL); - if(!hexline) { - ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt); - return -EINVAL; - } - bytesleft = hexline->d.content.header.ll; - // split the line into several lines - while (bytesleft > 0) { - int status; - this_line = (bytesleft >= maxwidth) ? maxwidth : bytesleft; - allocsize = sizeof(struct hexline) + this_line + 1; - // generate the new line - if((extraline = (struct hexline *)malloc(allocsize)) == NULL) { - ERR("Not enough memory for spliting the lines\n" ); - return -EINVAL; - } - memset(extraline, 0, allocsize); - extraline->d.content.header.ll = this_line; - extraline->d.content.header.offset = hexline->d.content.header.offset + extra_offset; - extraline->d.content.header.tt = hexline->d.content.header.tt; - memcpy( extraline->d.content.tt_data.data, hexline->d.content.tt_data.data+extra_offset, this_line); - status = send_hexline(mydev, extraline, seq+linessent ); - // cleanups - free(extraline); - extra_offset += this_line; - bytesleft -= this_line; - if (status) - return status; - linessent++; - } - return linessent; -} - -int match_usb_device_identity(const struct usb_config_descriptor *config_desc, - const struct astribank_type *ab) -{ - struct usb_interface *interface; - struct usb_interface_descriptor *iface_desc; - - if(config_desc->bNumInterfaces <= ab->my_interface_num) - return 0; - interface = &config_desc->interface[ab->my_interface_num]; - iface_desc = interface->altsetting; - - return iface_desc->bInterfaceClass == 0xFF && - iface_desc->bInterfaceNumber == ab->my_interface_num && - iface_desc->bNumEndpoints == ab->num_endpoints; -} - -const struct astribank_type *my_usb_device_identify(const char devpath[], struct my_usb_device *mydev) -{ - struct usb_device_descriptor *dev_desc; - struct usb_config_descriptor *config_desc; - int i; - - assert(mydev != NULL); - usb_init(); - usb_find_busses(); - usb_find_devices(); - mydev->dev = dev_of_path(devpath); - if(!mydev->dev) { - ERR("Bailing out\n"); - return 0; - } - dev_desc = &mydev->dev->descriptor; - config_desc = mydev->dev->config; - for(i = 0; i < sizeof(astribank_types)/sizeof(astribank_types[0]); i++) { - if(match_usb_device_identity(config_desc, &astribank_types[i])) { - DBG("Identified[%d]: interfaces=%d endpoints=%d: \"%s\"\n", - i, - astribank_types[i].num_interfaces, - astribank_types[i].num_endpoints, - astribank_types[i].name); - return &astribank_types[i]; - } - } - return NULL; -} - -int my_usb_device_init(const char devpath[], struct my_usb_device *mydev, const struct astribank_type *abtype) -{ - struct usb_device_descriptor *dev_desc; - struct usb_config_descriptor *config_desc; - struct usb_interface *interface; - struct usb_interface_descriptor *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int ret; - int i; - - assert(mydev != NULL); - usb_init(); - usb_find_busses(); - usb_find_devices(); - mydev->dev = dev_of_path(devpath); - if(!mydev->dev) { - ERR("Bailing out\n"); - return 0; - } - mydev->handle = usb_open(mydev->dev); - if(!mydev->handle) { - ERR("Failed to open usb device '%s/%s': %s\n", mydev->dev->bus->dirname, mydev->dev->filename, usb_strerror()); - return 0; - } - if(usb_claim_interface(mydev->handle, abtype->my_interface_num) != 0) { - ERR("usb_claim_interface: %s\n", usb_strerror()); - return 0; - } - dev_desc = &mydev->dev->descriptor; - config_desc = mydev->dev->config; - if (!config_desc) { - ERR("usb interface without a configuration\n"); - return 0; - } - interface = &config_desc->interface[abtype->my_interface_num]; - iface_desc = interface->altsetting; - endpoint = iface_desc->endpoint; - mydev->is_usb2 = (endpoint->wMaxPacketSize == 512); - for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) { - if(endpoint->bEndpointAddress != abtype->endpoints[i]) { - ERR("Wrong endpoint 0x%X (at index %d)\n", endpoint->bEndpointAddress, i); - return 0; - } - if(endpoint->bEndpointAddress == MY_EP_OUT || endpoint->bEndpointAddress == MY_EP_IN) { - if(endpoint->wMaxPacketSize > PACKET_SIZE) { - ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize); - return 0; - } - } - } - mydev->abtype = abtype; - mydev->my_ep_in = abtype->my_ep_in; - mydev->my_ep_out = abtype->my_ep_out; - ret = get_usb_string(mydev->iManufacturer, BUFSIZ, dev_desc->iManufacturer, mydev->handle); - ret = get_usb_string(mydev->iProduct, BUFSIZ, dev_desc->iProduct, mydev->handle); - ret = get_usb_string(mydev->iSerialNumber, BUFSIZ, dev_desc->iSerialNumber, mydev->handle); - ret = get_usb_string(mydev->iInterface, BUFSIZ, iface_desc->iInterface, mydev->handle); - INFO("ID=%04X:%04X Manufacturer=[%s] Product=[%s] SerialNumber=[%s] Interface=[%s]\n", - dev_desc->idVendor, - dev_desc->idProduct, - mydev->iManufacturer, - mydev->iProduct, - mydev->iSerialNumber, - mydev->iInterface); - if(usb_clear_halt(mydev->handle, mydev->my_ep_out) != 0) { - ERR("Clearing output endpoint: %s\n", usb_strerror()); - return 0; - } - if(usb_clear_halt(mydev->handle, mydev->my_ep_in) != 0) { - ERR("Clearing input endpoint: %s\n", usb_strerror()); - return 0; - } - if(flush_read(mydev) < 0) { - ERR("flush_read failed\n"); - return 0; - } - return 1; -} - -int renumerate_device(struct my_usb_device *mydev, enum fpga_load_packet_types pt) -{ - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - int ret; - - assert(mydev != NULL); - DBG("Renumerating with 0x%X\n", pt); - phead->header.op = pt; - ret = send_usb("renumerate[W]", mydev, phead, 1, TIMEOUT); - if(ret < 0 && ret != -ENODEV) - return ret; -#if 0 - /* - * FIXME: we count on our USB firmware to reset the device... should we? - */ - ret = usb_reset(mydev->handle); - if(ret < 0) { - ERR("usb_reset: %s\n", usb_strerror()); - return -ENODEV; - } -#endif - return 0; -} - -/* - * Returns: true on success, false on failure - */ -int fpga_load(struct my_usb_device *mydev, const struct hexdata *hexdata) -{ - unsigned int i; - unsigned int j = 0; - int ret; - int finished = 0; - const char *v = hexdata->version_info; - - v = (v[0]) ? v : "Unknown"; - assert(mydev != NULL); - INFO("FPGA_LOAD (version %s)\n", v); - /* - * i - is the line number - * j - is the sequence number, on USB 2, i=j, but on - * USB 1 send_splited_hexline may increase the sequence - * number, as it needs - */ - for(i = 0; i < hexdata->maxlines; i++) { - struct hexline *hexline = hexdata->lines[i]; - - if(!hexline) - break; - if(finished) { - ERR("Extra data after End Of Data Record (line %d)\n", i); - return 0; - } - if(hexline->d.content.header.tt == TT_EOF) { - DBG("End of data\n"); - finished = 1; - continue; - } - if(mydev->is_usb2) { - if((ret = send_hexline(mydev, hexline, i)) != 0) { - perror("Failed sending hexline"); - return 0; - } - } else { - if((ret = send_splited_hexline(mydev, hexline, j, 60)) < 0) { - perror("Failed sending hexline (splitting did not help)"); - return 0; - } - j += ret; - } - } - DBG("Finished...\n"); - return 1; -} - -#include - -void usage() -{ - fprintf(stderr, "Usage: %s -D {/proc/bus/usb|/dev/bus/usb}// [options...]\n", progname); - fprintf(stderr, "\tOptions:\n"); - fprintf(stderr, "\t\t[-r] # Reset the device\n"); - fprintf(stderr, "\t\t[-b ] # Output to \n"); - fprintf(stderr, "\t\t[-I ] # Input from \n"); - fprintf(stderr, "\t\t[-H ] # Output to ('-' is stdout)\n"); - fprintf(stderr, "\t\t[-i] # Show hexfile information\n"); - fprintf(stderr, "\t\t[-g] # Get eeprom from device\n"); - fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); -#ifdef XORCOM_INTERNAL - fprintf(stderr, "\t\t[-C srC byte] # Set Address sourCe (default: C0)\n"); - fprintf(stderr, "\t\t[-V vendorid] # Set Vendor id on device\n"); - fprintf(stderr, "\t\t[-P productid] # Set Product id on device\n"); - fprintf(stderr, "\t\t[-R release] # Set Release. 2 dot separated decimals\n"); - fprintf(stderr, "\t\t[-L label] # Set label.\n"); -#endif - exit(1); -} - -static void parse_report_func(int level, const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - if(level <= verbose) - vfprintf(stderr, msg, ap); - va_end(ap); -} - -#ifdef XORCOM_INTERNAL -static void eeprom_fill(struct myeeprom *myeeprom, - const char vendor[], - const char product[], - const char release[], - const char label[], - const char source[]) -{ - // FF: address source is from device. C0: from eeprom - if (source) - myeeprom->source = strtoul(source, NULL, 0); - else - myeeprom->source = 0xC0; - if(vendor) - myeeprom->vendor = strtoul(vendor, NULL, 0); - if(product) - myeeprom->product = strtoul(product, NULL, 0); - if(release) { - int release_major = 0; - int release_minor = 0; - - sscanf(release, "%d.%d", &release_major, &release_minor); - myeeprom->release_major = release_major; - myeeprom->release_minor = release_minor; - } - if(label) { - /* padding */ - memset(myeeprom->label, 0, LABEL_SIZE); - memcpy(myeeprom->label, label, strlen(label)); - } -} -#endif - -int main(int argc, char *argv[]) -{ - const struct astribank_type *abtype; - struct my_usb_device mydev; - const char *devpath = NULL; - const char *binfile = NULL; - const char *inhexfile = NULL; - const char *outhexfile = NULL; - struct hexdata *hexdata = NULL; - int opt_reset = 0; - int opt_info = 0; - int opt_read_eeprom = 0; - int opt_output_width = 0; - int output_is_set = 0; -#ifdef XORCOM_INTERNAL - int opt_write_eeprom = 0; - char *vendor = NULL; - char *source = NULL; - char *product = NULL; - char *release = NULL; - char *label = NULL; - const char options[] = "rib:D:ghH:I:vw:C:V:P:R:S:"; -#else - const char options[] = "rib:D:ghH:I:vw:"; -#endif - int ret = 0; - - progname = argv[0]; - assert(sizeof(struct fpga_packet_header) <= PACKET_SIZE); - assert(sizeof(struct myeeprom) == EEPROM_SIZE); - while (1) { - int c; - - c = getopt (argc, argv, options); - if (c == -1) - break; - - switch (c) { - case 'D': - devpath = optarg; - if(output_is_set++) { - ERR("Cannot set -D. Another output option is already selected\n"); - return 1; - } - break; - case 'r': - opt_reset = 1; - break; - case 'i': - opt_info = 1; - break; - case 'b': - binfile = optarg; - if(output_is_set++) { - ERR("Cannot set -b. Another output option is already selected\n"); - return 1; - } - break; - case 'g': - opt_read_eeprom = 1; - break; - case 'H': - outhexfile = optarg; - if(output_is_set++) { - ERR("Cannot set -H. Another output option is already selected\n"); - return 1; - } - break; - case 'I': - inhexfile = optarg; - break; -#ifdef XORCOM_INTERNAL - case 'V': - vendor = optarg; - break; - case 'C': - source = optarg; - break; - case 'P': - product = optarg; - break; - case 'R': - release = optarg; - break; - case 'S': - label = optarg; - { - const char GOOD_CHARS[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789" - "-_."; - int len = strlen(label); - int goodlen = strspn(label, GOOD_CHARS); - - if(len > LABEL_SIZE) { - ERR("Label too long (%d > %d)\n", len, LABEL_SIZE); - usage(); - } - if(goodlen != len) { - ERR("Bad character in label number (pos=%d)\n", goodlen); - usage(); - } - } - break; -#endif - case 'w': - opt_output_width = strtoul(optarg, NULL, 0); - break; - case 'v': - verbose++; - break; - case 'h': - default: - ERR("Unknown option '%c'\n", c); - usage(); - } - } - - if (optind != argc) { - usage(); - } - if(inhexfile) { -#ifdef XORCOM_INTERNAL - if(vendor || product || release || label || source ) { - ERR("The -I option is exclusive of -[VPRSC]\n"); - return 1; - } -#endif - parse_hexfile_set_reporting(parse_report_func); - hexdata = parse_hexfile(inhexfile, MAX_HEX_LINES); - if(!hexdata) { - ERR("Bailing out\n"); - exit(1); - } - if(opt_info) { - printf("%s: Version=%s Checksum=%d\n", - inhexfile, hexdata->version_info, - bsd_checksum(hexdata)); - } - if(binfile) { - dump_binary(hexdata, binfile); - return 0; - } - if(outhexfile) { - if(opt_output_width) - dump_hexfile2(hexdata, outhexfile, opt_output_width); - else - dump_hexfile(hexdata, outhexfile); - return 0; - } - } -#ifdef XORCOM_INTERNAL - else if(vendor || product || release || label || source ) { - if(outhexfile) { - FILE *fp; - - if(strcmp(outhexfile, "-") == 0) - fp = stdout; - else if((fp = fopen(outhexfile, "w")) == NULL) { - perror(outhexfile); - return 1; - } - memset(&mydev.eeprom, 0, sizeof(struct myeeprom)); - eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); - gen_hexline((uint8_t *)&mydev.eeprom, 0, sizeof(mydev.eeprom), fp); - gen_hexline(NULL, 0, 0, fp); /* EOF */ - return 0; - } - } -#endif - if(!devpath) { - ERR("Missing device path\n"); - usage(); - } - DBG("Startup %s\n", devpath); - if((abtype = my_usb_device_identify(devpath, &mydev)) == NULL) { - ERR("Bad device. Does not match our types.\n"); - usage(); - } - INFO("FIRMWARE: %s (type=%d)\n", abtype->name, abtype->type_code); - if(!my_usb_device_init(devpath, &mydev, abtype)) { - ERR("Failed to initialize USB device '%s'\n", devpath); - ret = -ENODEV; - goto dev_err; - } - ret = eeprom_get(&mydev); - if(ret < 0) { - ERR("Failed reading eeprom\n"); - goto dev_err; - } -#ifdef XORCOM_INTERNAL - if(vendor || product || release || label || source ) { - eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); - opt_write_eeprom = 1; - opt_read_eeprom = 1; - } -#endif - if(opt_read_eeprom) { - show_device_info(&mydev); - } - if(hexdata) { - if (!mydev.is_usb2) - INFO("Warning: working on a low end USB1 backend\n"); - if(!fpga_load(&mydev, hexdata)) { - ERR("FPGA loading failed\n"); - ret = -ENODEV; - goto dev_err; - } - ret = renumerate_device(&mydev, PT_RENUMERATE); - if(ret < 0) { - ERR("Renumeration failed: errno=%d\n", ret); - goto dev_err; - } - } -#ifdef XORCOM_INTERNAL - else if(opt_write_eeprom) { - if(abtype->type_code == USB_FIRMWARE_II) { - ERR("No EEPROM burning command in %s. Use fxload for that\n", - abtype->name); - goto dev_err; - } - ret = eeprom_set(&mydev, &mydev.eeprom); - if(ret < 0) { - ERR("Failed writing eeprom: %s\n", strerror(-ret)); - goto dev_err; - } - printf("------- RESULTS -------\n"); - show_device_info(&mydev); - } -#endif - if(opt_reset) { - DBG("Reseting to default\n"); - ret = renumerate_device(&mydev, PT_RESET); - if(ret < 0) { - ERR("Renumeration to default failed: errno=%d\n", ret); - goto dev_err; - } - } - DBG("Exiting\n"); -dev_err: - my_usb_device_cleanup(&mydev); - return ret; -}