📄 main.c.svn-base
字号:
/* * dfu-util * * (C) 2007-2008 by OpenMoko, Inc. * Written by Harald Welte <laforge@openmoko.org> * * Based on existing code of dfu-programmer-0.4 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <string.h>#include <getopt.h>#include <usb.h>#include <errno.h>#include "dfu.h"#include "usb_dfu.h"#include "sam7dfu.h"#include "dfu-version.h"#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_USBPATH_H#include <usbpath.h>#endif/* define a portable function for reading a 16bit little-endian word */unsigned short get_int16_le(const void *p){ const unsigned char *cp = p; return ( cp[0] ) | ( ((unsigned short)cp[1]) << 8 );}int debug;static int verbose = 0;#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */#define DFU_IFF_VENDOR 0x0100#define DFU_IFF_PRODUCT 0x0200#define DFU_IFF_CONFIG 0x0400#define DFU_IFF_IFACE 0x0800#define DFU_IFF_ALT 0x1000#define DFU_IFF_DEVNUM 0x2000#define DFU_IFF_PATH 0x4000struct usb_vendprod { u_int16_t vendor; u_int16_t product;};struct dfu_if { u_int16_t vendor; u_int16_t product; u_int8_t configuration; u_int8_t interface; u_int8_t altsetting; int bus; u_int8_t devnum; const char *path; unsigned int flags; struct usb_device *dev; struct usb_dev_handle *dev_handle;};static int _get_first_cb(struct dfu_if *dif, void *v){ struct dfu_if *v_dif = v; memcpy(v_dif, dif, sizeof(*v_dif)-sizeof(struct usb_dev_handle *)); /* return a value that makes find_dfu_if return immediately */ return 1;}/* Find a DFU interface (and altsetting) in a given device */static int find_dfu_if(struct usb_device *dev, int (*handler)(struct dfu_if *, void *), void *v){ struct usb_config_descriptor *cfg; struct usb_interface_descriptor *intf; struct usb_interface *uif; struct dfu_if _dif, *dfu_if = &_dif; int cfg_idx, intf_idx, alt_idx; int rc; memset(dfu_if, 0, sizeof(*dfu_if)); for (cfg_idx = 0; cfg_idx < dev->descriptor.bNumConfigurations; cfg_idx++) { cfg = &dev->config[cfg_idx]; /* in some cases, noticably FreeBSD if uid != 0, * the configuration descriptors are empty */ if (!cfg) return 0; for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; intf_idx++) { uif = &cfg->interface[intf_idx]; if (!uif) return 0; for (alt_idx = 0; alt_idx < uif->num_altsetting; alt_idx++) { intf = &uif->altsetting[alt_idx]; if (!intf) return 0; if (intf->bInterfaceClass == 0xfe && intf->bInterfaceSubClass == 1) { dfu_if->dev = dev; dfu_if->vendor = dev->descriptor.idVendor; dfu_if->product = dev->descriptor.idProduct; dfu_if->configuration = cfg_idx; dfu_if->interface = intf->bInterfaceNumber; dfu_if->altsetting = intf->bAlternateSetting; if (intf->bInterfaceProtocol == 2) dfu_if->flags |= DFU_IFF_DFU; else dfu_if->flags &= ~DFU_IFF_DFU; if (!handler) return 1; rc = handler(dfu_if, v); if (rc != 0) return rc; } } } } return 0;}static int get_first_dfu_if(struct dfu_if *dif){ return find_dfu_if(dif->dev, &_get_first_cb, (void *) dif);}#define MAX_STR_LEN 64static int print_dfu_if(struct dfu_if *dfu_if, void *v){ struct usb_device *dev = dfu_if->dev; int if_name_str_idx; char name[MAX_STR_LEN+1] = "UNDEFINED"; if_name_str_idx = dev->config[dfu_if->configuration] .interface[dfu_if->interface] .altsetting[dfu_if->altsetting].iInterface; if (if_name_str_idx) { if (!dfu_if->dev_handle) dfu_if->dev_handle = usb_open(dfu_if->dev); if (dfu_if->dev_handle) usb_get_string_simple(dfu_if->dev_handle, if_name_str_idx, name, MAX_STR_LEN); } printf("Found %s: [0x%04x:0x%04x] devnum=%u, cfg=%u, intf=%u, " "alt=%u, name=\"%s\"\n", dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime", dev->descriptor.idVendor, dev->descriptor.idProduct, dev->devnum, dfu_if->configuration, dfu_if->interface, dfu_if->altsetting, name); return 0;}static int alt_by_name(struct dfu_if *dfu_if, void *v){ struct usb_device *dev = dfu_if->dev; int if_name_str_idx; char name[MAX_STR_LEN+1] = "UNDEFINED"; if_name_str_idx = dev->config[dfu_if->configuration].interface[dfu_if->interface]. altsetting[dfu_if->altsetting].iInterface; if (!if_name_str_idx) return 0; if (!dfu_if->dev_handle) dfu_if->dev_handle = usb_open(dfu_if->dev); if (!dfu_if->dev_handle) return 0; if (usb_get_string_simple(dfu_if->dev_handle, if_name_str_idx, name, MAX_STR_LEN) < 0) return 0; /* should we return an error here ? */ if (strcmp(name, v)) return 0; /* * Return altsetting+1 so that we can use return value 0 to indicate * "not found". */ return dfu_if->altsetting+1;}static int _count_cb(struct dfu_if *dif, void *v){ int *count = v; (*count)++; return 0;}/* Count DFU interfaces within a single device */static int count_dfu_interfaces(struct usb_device *dev){ int num_found = 0; find_dfu_if(dev, &_count_cb, (void *) &num_found); return num_found;}/* Iterate over all matching DFU capable devices within system */static int iterate_dfu_devices(struct dfu_if *dif, int (*action)(struct usb_device *dev, void *user), void *user){ struct usb_bus *usb_bus; struct usb_device *dev; /* Walk the tree and find our device. */ for (usb_bus = usb_get_busses(); NULL != usb_bus; usb_bus = usb_bus->next) { for (dev = usb_bus->devices; NULL != dev; dev = dev->next) { int retval; if (dif && (dif->flags & (DFU_IFF_VENDOR|DFU_IFF_PRODUCT)) && (dev->descriptor.idVendor != dif->vendor || dev->descriptor.idProduct != dif->product)) continue; if (dif && (dif->flags & DFU_IFF_DEVNUM) && (atoi(usb_bus->dirname) != dif->bus || dev->devnum != dif->devnum)) continue; if (!count_dfu_interfaces(dev)) continue; retval = action(dev, user); if (retval) return retval; } } return 0;}static int found_dfu_device(struct usb_device *dev, void *user){ struct dfu_if *dif = user; dif->dev = dev; return 1;}/* Find the first DFU-capable device, save it in dfu_if->dev */static int get_first_dfu_device(struct dfu_if *dif){ return iterate_dfu_devices(dif, found_dfu_device, dif);}static int count_one_dfu_device(struct usb_device *dev, void *user){ int *num = user; (*num)++; return 0;}/* Count DFU capable devices within system */static int count_dfu_devices(struct dfu_if *dif){ int num_found = 0; iterate_dfu_devices(dif, count_one_dfu_device, &num_found); return num_found;}static int list_dfu_interfaces(void){ struct usb_bus *usb_bus; struct usb_device *dev; /* Walk the tree and find our device. */ for (usb_bus = usb_get_busses(); NULL != usb_bus; usb_bus = usb_bus->next ) { for (dev = usb_bus->devices; NULL != dev; dev = dev->next) { find_dfu_if(dev, &print_dfu_if, NULL); } } return 0;}static int parse_vendprod(struct usb_vendprod *vp, const char *str){ unsigned long vend, prod; const char *colon; colon = strchr(str, ':'); if (!colon || strlen(colon) < 2) return -EINVAL; vend = strtoul(str, NULL, 16); prod = strtoul(colon+1, NULL, 16); if (vend > 0xffff || prod > 0xffff) return -EINVAL; vp->vendor = vend; vp->product = prod; return 0;}#ifdef HAVE_USBPATH_Hstatic int resolve_device_path(struct dfu_if *dif){ int res; res = usb_path2devnum(dif->path); if (res < 0) return -EINVAL; if (!res) return 0; dif->bus = atoi(dif->path); dif->devnum = res; dif->flags |= DFU_IFF_DEVNUM; return res;}#else /* HAVE_USBPATH_H */static int resolve_device_path(struct dfu_if *dif){ fprintf(stderr, "USB device paths are not supported by this dfu-util.\n"); exit(1);}#endif /* !HAVE_USBPATH_H */static void help(void){ printf("Usage: dfu-util [options] ...\n" " -h --help\t\t\tPrint this help message\n" " -V --version\t\t\tPrint the version number\n" " -l --list\t\t\tList the currently attached DFU capable USB devices\n" " -d --device vendor:product\tSpecify Vendor/Product ID of DFU device\n" " -p --path bus-port. ... .port\tSpecify path to DFU device\n" " -c --cfg config_nr\t\tSpecify the Configuration of DFU device\n" " -i --intf intf_nr\t\tSpecify the DFU Interface number\n" " -a --alt alt\t\t\tSpecify the Altsetting of the DFU Interface\n" "\t\t\t\tby name or by number\n" " -t --transfer-size\t\tSpecify the number of bytes per USB Transfer\n" " -U --upload file\t\tRead firmware from device into <file>\n" " -D --download file\t\tWrite firmware from <file> into device\n" " -R --reset\t\t\tIssue USB Reset signalling once we're finished\n" );}static void print_version(void){ printf("dfu-util version %s\n", VERSION "+svn" DFU_UTIL_VERSION);}static struct option opts[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, { "verbose", 0, 0, 'v' }, { "list", 0, 0, 'l' }, { "device", 1, 0, 'd' }, { "path", 1, 0, 'p' }, { "configuration", 1, 0, 'c' }, { "cfg", 1, 0, 'c' }, { "interface", 1, 0, 'i' }, { "intf", 1, 0, 'i' }, { "altsetting", 1, 0, 'a' }, { "alt", 1, 0, 'a' }, { "transfer-size", 1, 0, 't' }, { "upload", 1, 0, 'U' }, { "download", 1, 0, 'D' }, { "reset", 0, 0, 'R' },};enum mode { MODE_NONE, MODE_UPLOAD, MODE_DOWNLOAD,};int main(int argc, char **argv)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -