summaryrefslogtreecommitdiff
path: root/xpp/fpga_load.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/fpga_load.c')
-rw-r--r--xpp/fpga_load.c1052
1 files changed, 0 insertions, 1052 deletions
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 <oron@actcom.co.il>
- * 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 <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <usb.h>
-#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 <getopt.h>
-
-void usage()
-{
- fprintf(stderr, "Usage: %s -D {/proc/bus/usb|/dev/bus/usb}/<bus>/<dev> [options...]\n", progname);
- fprintf(stderr, "\tOptions:\n");
- fprintf(stderr, "\t\t[-r] # Reset the device\n");
- fprintf(stderr, "\t\t[-b <binfile>] # Output to <binfile>\n");
- fprintf(stderr, "\t\t[-I <hexfile>] # Input from <hexfile>\n");
- fprintf(stderr, "\t\t[-H <hexfile>] # Output to <hexfile> ('-' 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;
-}