arduino-dfu-discovery: Use DISTFILES instead of files dir

This commit is contained in:
Rui-Xiang Guo 2024-03-03 15:22:02 +08:00
parent 4d4b0994e8
commit 378320abe8
12 changed files with 13 additions and 1307 deletions

View File

@ -6,6 +6,12 @@ MASTER_SITES= ${MASTER_SITE_GITHUB:=arduino/}
GITHUB_PROJECT= dfu-discovery
GITHUB_TAG= v${PKGVERSION_NOREV}
DISTFILES= ${DEFAULT_DISTFILES}
DFU_UTIL= dfu-util-0.11
DISTFILES+= ${DFU_UTIL}.tar.gz
MASTER_SITES+= ${MASTER_SITE_SOURCEFORGE:=dfu-util/files/}
MAINTAINER= rxg@NetBSD.org
HOMEPAGE= https://github.com/arduino/dfu-discovery
COMMENT= Arduino pluggable discovery for dfu devices
@ -17,12 +23,12 @@ USE_TOOLS+= pkg-config
INSTALLATION_DIRS= arduino15/packages/builtin/tools/dfu-discovery/${PKGVERSION_NOREV}
pre-build:
${CP} -Rf ${FILESDIR}/dfu-util-0.11 ${WRKSRC}
${CP} -f ${WRKSRC}/dfu-util-0.11/src/dfuse_mem.c \
${CP} -r ${WRKDIR}/${DFU_UTIL} ${WRKSRC}
${CP} -f ${WRKSRC}/${DFU_UTIL}/src/dfuse_mem.c \
${WRKSRC}/dfu-util_dfuse_mem.c
${CP} -f ${WRKSRC}/dfu-util-0.11/src/dfu_util.c \
${CP} -f ${WRKSRC}/${DFU_UTIL}/src/dfu_util.c \
${WRKSRC}/dfu-util_dfu_util.c
${CP} -f ${WRKSRC}/dfu-util-0.11/src/quirks.c \
${CP} -f ${WRKSRC}/${DFU_UTIL}/src/quirks.c \
${WRKSRC}/dfu-util_quirks.c
${SED} -i 's/#cgo !darwin LDFLAGS: -L\/usr\/local\/lib -lusb-1.0/ \
#cgo !darwin pkg-config: libusb-1.0/g' ${WRKSRC}/main.go

View File

@ -117,6 +117,9 @@ Size (cloud.google.com_go_storage_@v_v1.6.0.mod) = 736 bytes
BLAKE2s (cloud.google.com_go_storage_@v_v1.8.0.mod) = 692c82ecdaa77da7e9949128a1c191102b66f878700060363a58ee55577abad8
SHA512 (cloud.google.com_go_storage_@v_v1.8.0.mod) = 409dad03104a4ac6b4a8c6da3540ab382345c86e48732f2b37d64ae2bc1c721d9f0a1ed0824a36085baa7102d2626e84f44706b16297623e8deb58fa9e24ba38
Size (cloud.google.com_go_storage_@v_v1.8.0.mod) = 622 bytes
BLAKE2s (dfu-util-0.11.tar.gz) = c846a5d114a3c05925936e74c0d8d75da5d0f70f34a9825f0d92b57ae1f0fffc
SHA512 (dfu-util-0.11.tar.gz) = fc5304a483ac10e35bf1b9304becdeb407b2e44d8ac51474d2fa17877e6cf71b0126f7e12ebb331d75e7adeb9c173ff5cf083a06ded5847dbe477534cf26a553
Size (dfu-util-0.11.tar.gz) = 152462 bytes
BLAKE2s (dmitri.shuralyov.com_gpu_mtl_@v_v0.0.0-20190408044501-666a987793e9.mod) = 2136184228fc4913040e8abab210d9694fa46310b1073dbb42e1697f8591c1f2
SHA512 (dmitri.shuralyov.com_gpu_mtl_@v_v0.0.0-20190408044501-666a987793e9.mod) = 196affe091247f94ceda4b56629bd62d4ee2b397f2c0f56c9534c02e43531b46705ad33543b58c1a4fc7a48e25e5923db087fe0485a93966a4086581c0d1d3e1
Size (dmitri.shuralyov.com_gpu_mtl_@v_v0.0.0-20190408044501-666a987793e9.mod) = 36 bytes

View File

@ -1,136 +0,0 @@
/*
* dfu-programmer
*
* $Id: dfu.h,v 1.2 2005/09/25 01:27:42 schmidtw Exp $
*
* 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
*/
#ifndef DFU_H
#define DFU_H
#include <libusb.h>
#include "usb_dfu.h"
#include "dfuse_mem.h"
/* DFU states */
#define STATE_APP_IDLE 0x00
#define STATE_APP_DETACH 0x01
#define STATE_DFU_IDLE 0x02
#define STATE_DFU_DOWNLOAD_SYNC 0x03
#define STATE_DFU_DOWNLOAD_BUSY 0x04
#define STATE_DFU_DOWNLOAD_IDLE 0x05
#define STATE_DFU_MANIFEST_SYNC 0x06
#define STATE_DFU_MANIFEST 0x07
#define STATE_DFU_MANIFEST_WAIT_RESET 0x08
#define STATE_DFU_UPLOAD_IDLE 0x09
#define STATE_DFU_ERROR 0x0a
/* DFU status */
#define DFU_STATUS_OK 0x00
#define DFU_STATUS_ERROR_TARGET 0x01
#define DFU_STATUS_ERROR_FILE 0x02
#define DFU_STATUS_ERROR_WRITE 0x03
#define DFU_STATUS_ERROR_ERASE 0x04
#define DFU_STATUS_ERROR_CHECK_ERASED 0x05
#define DFU_STATUS_ERROR_PROG 0x06
#define DFU_STATUS_ERROR_VERIFY 0x07
#define DFU_STATUS_ERROR_ADDRESS 0x08
#define DFU_STATUS_ERROR_NOTDONE 0x09
#define DFU_STATUS_ERROR_FIRMWARE 0x0a
#define DFU_STATUS_ERROR_VENDOR 0x0b
#define DFU_STATUS_ERROR_USBR 0x0c
#define DFU_STATUS_ERROR_POR 0x0d
#define DFU_STATUS_ERROR_UNKNOWN 0x0e
#define DFU_STATUS_ERROR_STALLEDPKT 0x0f
/* DFU commands */
#define DFU_DETACH 0
#define DFU_DNLOAD 1
#define DFU_UPLOAD 2
#define DFU_GETSTATUS 3
#define DFU_CLRSTATUS 4
#define DFU_GETSTATE 5
#define DFU_ABORT 6
/* DFU interface */
#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */
#define DFU_IFF_ALT 0x0002 /* Multiple alternate settings */
/* This is based off of DFU_GETSTATUS
*
* 1 unsigned byte bStatus
* 3 unsigned byte bwPollTimeout
* 1 unsigned byte bState
* 1 unsigned byte iString
*/
struct dfu_status {
unsigned char bStatus;
unsigned int bwPollTimeout;
unsigned char bState;
unsigned char iString;
};
struct dfu_if {
struct usb_dfu_func_descriptor func_dfu;
uint16_t quirks;
uint16_t busnum;
uint16_t devnum;
uint16_t vendor;
uint16_t product;
uint16_t bcdDevice;
uint8_t configuration;
uint8_t interface;
uint8_t altsetting;
uint8_t flags;
uint8_t bMaxPacketSize0;
char *alt_name;
char *serial_name;
libusb_device *dev;
libusb_device_handle *dev_handle;
struct dfu_if *next;
struct memsegment *mem_layout; /* for DfuSe */
};
int dfu_detach( libusb_device_handle *device,
const unsigned short interface,
const unsigned short timeout );
int dfu_download( libusb_device_handle *device,
const unsigned short interface,
const unsigned short length,
const unsigned short transaction,
unsigned char* data );
int dfu_upload( libusb_device_handle *device,
const unsigned short interface,
const unsigned short length,
const unsigned short transaction,
unsigned char* data );
int dfu_get_status( struct dfu_if *dif,
struct dfu_status *status );
int dfu_clear_status( libusb_device_handle *device,
const unsigned short interface );
int dfu_get_state( libusb_device_handle *device,
const unsigned short interface );
int dfu_abort( libusb_device_handle *device,
const unsigned short interface );
int dfu_abort_to_idle( struct dfu_if *dif);
const char *dfu_state_to_string( int state );
const char *dfu_status_to_string( int status );
#endif /* DFU_H */

View File

@ -1,60 +0,0 @@
#ifndef DFU_FILE_H
#define DFU_FILE_H
#include <stdint.h>
struct dfu_file {
/* File name */
const char *name;
/* Pointer to file loaded into memory */
uint8_t *firmware;
/* Different sizes */
struct {
off_t total;
int prefix;
int suffix;
} size;
/* From prefix fields */
uint32_t lmdfu_address;
/* From prefix fields */
uint32_t prefix_type;
/* From DFU suffix fields */
uint32_t dwCRC;
uint16_t bcdDFU;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
};
enum suffix_req {
NO_SUFFIX,
NEEDS_SUFFIX,
MAYBE_SUFFIX
};
enum prefix_req {
NO_PREFIX,
NEEDS_PREFIX,
MAYBE_PREFIX
};
enum prefix_type {
ZERO_PREFIX,
LMDFU_PREFIX,
LPCDFU_UNENCRYPTED_PREFIX
};
extern int verbose;
void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix);
void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix);
void dfu_progress_bar(const char *desc, unsigned long long curr,
unsigned long long max);
void *dfu_malloc(size_t size);
uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size);
void show_suffix_and_prefix(struct dfu_file *file);
#endif /* DFU_FILE_H */

View File

@ -1,483 +0,0 @@
/*
* Functions for detecting DFU USB entities
*
* Written by Harald Welte <laforge@openmoko.org>
* Copyright 2007-2008 by OpenMoko, Inc.
* Copyright 2013 Hans Petter Selasky <hps@bitfrost.no>
* Copyright 2016-2019 Tormod Volden <debian.tormod@gmail.com>
*
* 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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <libusb.h>
#include "portable.h"
#include "dfu.h"
#include "usb_dfu.h"
#include "dfu_file.h"
#include "dfu_util.h"
#include "quirks.h"
/*
* Look for a descriptor in a concatenated descriptor list. Will
* return upon the first match of the given descriptor type. Returns length of
* found descriptor, limited to res_size
*/
static int find_descriptor(const uint8_t *desc_list, int list_len,
uint8_t desc_type, void *res_buf, int res_size)
{
int p = 0;
if (list_len < 2)
return (-1);
while (p + 1 < list_len) {
int desclen;
desclen = (int) desc_list[p];
if (desclen == 0) {
warnx("Invalid descriptor list");
return -1;
}
if (desc_list[p + 1] == desc_type) {
if (desclen > res_size)
desclen = res_size;
if (p + desclen > list_len)
desclen = list_len - p;
memcpy(res_buf, &desc_list[p], desclen);
return desclen;
}
p += (int) desc_list[p];
}
return -1;
}
/*
* Get a string descriptor that's UTF-8 (or ASCII) encoded instead
* of UTF-16 encoded like the USB specification mandates. Some
* devices, like the GD32VF103, both violate the spec in this way
* and store important information in the serial number field. This
* function does NOT append a NUL terminator to its buffer, so you
* must use the returned length to ensure you stay within bounds.
*/
static int get_utf8_string_descriptor(libusb_device_handle *devh,
uint8_t desc_index, unsigned char *data, int length)
{
unsigned char tbuf[255];
uint16_t langid;
int r, outlen;
/* get the language IDs and pick the first one */
r = libusb_get_string_descriptor(devh, 0, 0, tbuf, sizeof(tbuf));
if (r < 0) {
warnx("Failed to retrieve language identifiers");
return r;
}
if (r < 4 || tbuf[0] < 4 || tbuf[1] != LIBUSB_DT_STRING) { /* must have at least one ID */
warnx("Broken LANGID string descriptor");
return -1;
}
langid = tbuf[2] | (tbuf[3] << 8);
r = libusb_get_string_descriptor(devh, desc_index, langid, tbuf,
sizeof(tbuf));
if (r < 0) {
warnx("Failed to retrieve string descriptor %d", desc_index);
return r;
}
if (r < 2 || tbuf[0] < 2) {
warnx("String descriptor %d too short", desc_index);
return -1;
}
if (tbuf[1] != LIBUSB_DT_STRING) { /* sanity check */
warnx("Malformed string descriptor %d, type = 0x%02x", desc_index, tbuf[1]);
return -1;
}
if (tbuf[0] > r) { /* if short read, */
warnx("Patching string descriptor %d length (was %d, received %d)", desc_index, tbuf[0], r);
tbuf[0] = r; /* fix up descriptor length */
}
outlen = tbuf[0] - 2;
if (length < outlen)
outlen = length;
memcpy(data, tbuf + 2, outlen);
return outlen;
}
/*
* Similar to libusb_get_string_descriptor_ascii but will allow
* truncated descriptors (descriptor length mismatch) seen on
* e.g. the STM32F427 ROM bootloader.
*/
static int get_string_descriptor_ascii(libusb_device_handle *devh,
uint8_t desc_index, unsigned char *data, int length)
{
unsigned char buf[255];
int r, di, si;
r = get_utf8_string_descriptor(devh, desc_index, buf, sizeof(buf));
if (r < 0)
return r;
/* convert from 16-bit unicode to ascii string */
for (di = 0, si = 0; si + 1 < r && di < length; si += 2) {
if (buf[si + 1]) /* high byte of unicode char */
data[di++] = '?';
else
data[di++] = buf[si];
}
data[di] = '\0';
return di;
}
static void probe_configuration(libusb_device *dev, struct libusb_device_descriptor *desc)
{
struct usb_dfu_func_descriptor func_dfu;
libusb_device_handle *devh;
struct dfu_if *pdfu;
struct libusb_config_descriptor *cfg;
const struct libusb_interface_descriptor *intf;
const struct libusb_interface *uif;
char alt_name[MAX_DESC_STR_LEN + 1];
char serial_name[MAX_DESC_STR_LEN + 1];
int cfg_idx;
int intf_idx;
int alt_idx;
int ret;
int has_dfu;
for (cfg_idx = 0; cfg_idx != desc->bNumConfigurations; cfg_idx++) {
memset(&func_dfu, 0, sizeof(func_dfu));
has_dfu = 0;
ret = libusb_get_config_descriptor(dev, cfg_idx, &cfg);
if (ret != 0)
return;
if (match_config_index > -1 && match_config_index != cfg->bConfigurationValue) {
libusb_free_config_descriptor(cfg);
continue;
}
/*
* In some cases, noticably FreeBSD if uid != 0,
* the configuration descriptors are empty
*/
if (!cfg)
return;
ret = find_descriptor(cfg->extra, cfg->extra_length,
USB_DT_DFU, &func_dfu, sizeof(func_dfu));
if (ret > -1)
goto found_dfu;
for (intf_idx = 0; intf_idx < cfg->bNumInterfaces;
intf_idx++) {
uif = &cfg->interface[intf_idx];
if (!uif)
break;
for (alt_idx = 0; alt_idx < cfg->interface[intf_idx].num_altsetting;
alt_idx++) {
intf = &uif->altsetting[alt_idx];
if (intf->bInterfaceClass != 0xfe ||
intf->bInterfaceSubClass != 1)
continue;
ret = find_descriptor(intf->extra, intf->extra_length, USB_DT_DFU,
&func_dfu, sizeof(func_dfu));
if (ret > -1)
goto found_dfu;
has_dfu = 1;
}
}
if (has_dfu) {
/*
* Finally try to retrieve it requesting the
* device directly This is not supported on
* all devices for non-standard types
*/
if (libusb_open(dev, &devh) == 0) {
ret = libusb_get_descriptor(devh, USB_DT_DFU, 0,
(void *)&func_dfu, sizeof(func_dfu));
libusb_close(devh);
if (ret > -1)
goto found_dfu;
}
warnx("Device has DFU interface, "
"but has no DFU functional descriptor");
/* fake version 1.0 */
func_dfu.bLength = 7;
func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
goto found_dfu;
}
libusb_free_config_descriptor(cfg);
continue;
found_dfu:
if (func_dfu.bLength == 7) {
printf("Deducing device DFU version from functional descriptor "
"length\n");
func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
} else if (func_dfu.bLength < 9) {
printf("Error obtaining DFU functional descriptor\n");
printf("Please report this as a bug!\n");
printf("Warning: Assuming DFU version 1.0\n");
func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
printf("Warning: Transfer size can not be detected\n");
func_dfu.wTransferSize = 0;
}
for (intf_idx = 0; intf_idx < cfg->bNumInterfaces;
intf_idx++) {
int multiple_alt;
if (match_iface_index > -1 && match_iface_index != intf_idx)
continue;
uif = &cfg->interface[intf_idx];
if (!uif)
break;
multiple_alt = uif->num_altsetting > 0;
for (alt_idx = 0;
alt_idx < uif->num_altsetting; alt_idx++) {
int dfu_mode;
uint16_t quirks;
quirks = get_quirks(desc->idVendor,
desc->idProduct, desc->bcdDevice);
intf = &uif->altsetting[alt_idx];
if (intf->bInterfaceClass != 0xfe ||
intf->bInterfaceSubClass != 1)
continue;
dfu_mode = (intf->bInterfaceProtocol == 2);
/* e.g. DSO Nano has bInterfaceProtocol 0 instead of 2 */
if (func_dfu.bcdDFUVersion == 0x011a && intf->bInterfaceProtocol == 0)
dfu_mode = 1;
/* LPC DFU bootloader has bInterfaceProtocol 1 (Runtime) instead of 2 */
if (desc->idVendor == 0x1fc9 && desc->idProduct == 0x000c && intf->bInterfaceProtocol == 1)
dfu_mode = 1;
/*
* Old Jabra devices may have bInterfaceProtocol 0 instead of 2.
* Also runtime PID and DFU pid are the same.
* In DFU mode, the configuration descriptor has only 1 interface.
*/
if (desc->idVendor == 0x0b0e && intf->bInterfaceProtocol == 0 && cfg->bNumInterfaces == 1)
dfu_mode = 1;
if (dfu_mode &&
match_iface_alt_index > -1 && match_iface_alt_index != intf->bAlternateSetting)
continue;
if (dfu_mode) {
if ((match_vendor_dfu >= 0 && match_vendor_dfu != desc->idVendor) ||
(match_product_dfu >= 0 && match_product_dfu != desc->idProduct)) {
continue;
}
} else {
if ((match_vendor >= 0 && match_vendor != desc->idVendor) ||
(match_product >= 0 && match_product != desc->idProduct)) {
continue;
}
}
if (match_devnum >= 0 && match_devnum != libusb_get_device_address(dev))
continue;
ret = libusb_open(dev, &devh);
if (ret) {
warnx("Cannot open DFU device %04x:%04x found on devnum %i (%s)",
desc->idVendor, desc->idProduct, libusb_get_device_address(dev),
libusb_error_name(ret));
break;
}
if (intf->iInterface != 0)
ret = get_string_descriptor_ascii(devh,
intf->iInterface, (void *)alt_name, MAX_DESC_STR_LEN);
else
ret = -1;
if (ret < 1)
strcpy(alt_name, "UNKNOWN");
if (desc->iSerialNumber != 0) {
if (quirks & QUIRK_UTF8_SERIAL) {
ret = get_utf8_string_descriptor(devh, desc->iSerialNumber,
(void *)serial_name, MAX_DESC_STR_LEN - 1);
if (ret >= 0)
serial_name[ret] = '\0';
} else {
ret = get_string_descriptor_ascii(devh, desc->iSerialNumber,
(void *)serial_name, MAX_DESC_STR_LEN);
}
} else {
ret = -1;
}
if (ret < 1)
strcpy(serial_name, "UNKNOWN");
libusb_close(devh);
if (dfu_mode &&
match_iface_alt_name != NULL && strcmp(alt_name, match_iface_alt_name))
continue;
if (dfu_mode) {
if (match_serial_dfu != NULL && strcmp(match_serial_dfu, serial_name))
continue;
} else {
if (match_serial != NULL && strcmp(match_serial, serial_name))
continue;
}
pdfu = dfu_malloc(sizeof(*pdfu));
memset(pdfu, 0, sizeof(*pdfu));
pdfu->func_dfu = func_dfu;
pdfu->dev = libusb_ref_device(dev);
pdfu->quirks = quirks;
pdfu->vendor = desc->idVendor;
pdfu->product = desc->idProduct;
pdfu->bcdDevice = desc->bcdDevice;
pdfu->configuration = cfg->bConfigurationValue;
pdfu->interface = intf->bInterfaceNumber;
pdfu->altsetting = intf->bAlternateSetting;
pdfu->devnum = libusb_get_device_address(dev);
pdfu->busnum = libusb_get_bus_number(dev);
pdfu->alt_name = strdup(alt_name);
if (pdfu->alt_name == NULL)
errx(EX_SOFTWARE, "Out of memory");
pdfu->serial_name = strdup(serial_name);
if (pdfu->serial_name == NULL)
errx(EX_SOFTWARE, "Out of memory");
if (dfu_mode)
pdfu->flags |= DFU_IFF_DFU;
if (multiple_alt)
pdfu->flags |= DFU_IFF_ALT;
if (pdfu->quirks & QUIRK_FORCE_DFU11) {
pdfu->func_dfu.bcdDFUVersion =
libusb_cpu_to_le16(0x0110);
}
pdfu->bMaxPacketSize0 = desc->bMaxPacketSize0;
/* queue into list */
pdfu->next = dfu_root;
dfu_root = pdfu;
}
}
libusb_free_config_descriptor(cfg);
}
}
#define MAX_PATH_LEN 20
char path_buf[MAX_PATH_LEN];
char *get_path(libusb_device *dev)
{
#if (defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000102) || (defined(LIBUSBX_API_VERSION) && LIBUSBX_API_VERSION >= 0x01000102)
uint8_t path[8];
int r,j;
r = libusb_get_port_numbers(dev, path, sizeof(path));
if (r > 0) {
sprintf(path_buf,"%d-%d",libusb_get_bus_number(dev),path[0]);
for (j = 1; j < r; j++){
sprintf(path_buf+strlen(path_buf),".%d",path[j]);
};
}
return path_buf;
#else
# warning "libusb too old - building without USB path support!"
(void)dev;
return NULL;
#endif
}
void probe_devices(libusb_context *ctx)
{
libusb_device **list;
ssize_t num_devs;
ssize_t i;
num_devs = libusb_get_device_list(ctx, &list);
for (i = 0; i < num_devs; ++i) {
struct libusb_device_descriptor desc;
struct libusb_device *dev = list[i];
if (match_path != NULL && strcmp(get_path(dev),match_path) != 0)
continue;
if (libusb_get_device_descriptor(dev, &desc))
continue;
probe_configuration(dev, &desc);
}
libusb_free_device_list(list, 1);
}
void disconnect_devices(void)
{
struct dfu_if *pdfu;
struct dfu_if *prev = NULL;
for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) {
free(prev);
libusb_unref_device(pdfu->dev);
free(pdfu->alt_name);
free(pdfu->serial_name);
prev = pdfu;
}
free(prev);
dfu_root = NULL;
}
void print_dfu_if(struct dfu_if *dfu_if)
{
printf("Found %s: [%04x:%04x] ver=%04x, devnum=%u, cfg=%u, intf=%u, "
"path=\"%s\", alt=%u, name=\"%s\", serial=\"%s\"\n",
dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime",
dfu_if->vendor, dfu_if->product,
dfu_if->bcdDevice, dfu_if->devnum,
dfu_if->configuration, dfu_if->interface,
get_path(dfu_if->dev),
dfu_if->altsetting, dfu_if->alt_name,
dfu_if->serial_name);
}
/* Walk the device tree and print out DFU devices */
void list_dfu_interfaces(void)
{
struct dfu_if *pdfu;
for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next)
print_dfu_if(pdfu);
}

View File

@ -1,36 +0,0 @@
#ifndef DFU_UTIL_H
#define DFU_UTIL_H
/* USB string descriptor should contain max 126 UTF-16 characters
* but 254 would even accommodate a UTF-8 encoding + NUL terminator */
#define MAX_DESC_STR_LEN 254
enum mode {
MODE_NONE,
MODE_VERSION,
MODE_LIST,
MODE_DETACH,
MODE_UPLOAD,
MODE_DOWNLOAD
};
extern struct dfu_if *dfu_root;
extern char *match_path;
extern int match_vendor;
extern int match_product;
extern int match_vendor_dfu;
extern int match_product_dfu;
extern int match_config_index;
extern int match_iface_index;
extern int match_iface_alt_index;
extern int match_devnum;
extern const char *match_iface_alt_name;
extern const char *match_serial;
extern const char *match_serial_dfu;
void probe_devices(libusb_context *);
void disconnect_devices(void);
void print_dfu_if(struct dfu_if *);
void list_dfu_interfaces(void);
#endif /* DFU_UTIL_H */

View File

@ -1,203 +0,0 @@
/*
* Helper functions for reading the memory map of a device
* following the ST DfuSe 1.1a specification.
*
* Copyright 2011-2014 Tormod Volden <debian.tormod@gmail.com>
*
* 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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "portable.h"
#include "dfu_file.h"
#include "dfuse_mem.h"
int add_segment(struct memsegment **segment_list, struct memsegment segment)
{
struct memsegment *new_element;
new_element = dfu_malloc(sizeof(struct memsegment));
*new_element = segment;
new_element->next = NULL;
if (*segment_list == NULL)
/* list can be empty on first call */
*segment_list = new_element;
else {
struct memsegment *next_element;
/* find last element in list */
next_element = *segment_list;
while (next_element->next != NULL)
next_element = next_element->next;
next_element->next = new_element;
}
return 0;
}
struct memsegment *find_segment(struct memsegment *segment_list,
unsigned int address)
{
while (segment_list != NULL) {
if (segment_list->start <= address &&
segment_list->end >= address)
return segment_list;
segment_list = segment_list->next;
}
return NULL;
}
void free_segment_list(struct memsegment *segment_list)
{
struct memsegment *next_element;
while (segment_list->next != NULL) {
next_element = segment_list->next;
free(segment_list);
segment_list = next_element;
}
free(segment_list);
}
/* Parse memory map from interface descriptor string
* encoded as per ST document UM0424 section 4.3.2.
*/
struct memsegment *parse_memory_layout(char *intf_desc)
{
char multiplier, memtype;
unsigned int address;
int sectors, size;
char *name, *typestring;
int ret;
int count = 0;
char separator;
int scanned;
struct memsegment *segment_list = NULL;
struct memsegment segment;
name = dfu_malloc(strlen(intf_desc));
ret = sscanf(intf_desc, "@%[^/]%n", name, &scanned);
if (ret < 1) {
free(name);
warnx("Could not read name, sscanf returned %d", ret);
return NULL;
}
printf("DfuSe interface name: \"%s\"\n", name);
intf_desc += scanned;
typestring = dfu_malloc(strlen(intf_desc));
while (ret = sscanf(intf_desc, "/0x%x/%n", &address, &scanned),
ret > 0) {
intf_desc += scanned;
while (ret = sscanf(intf_desc, "%d*%d%c%[^,/]%n",
&sectors, &size, &multiplier, typestring,
&scanned), ret > 2) {
intf_desc += scanned;
count++;
memtype = 0;
if (ret == 4) {
if (strlen(typestring) == 1
&& typestring[0] != '/')
memtype = typestring[0];
else {
warnx("Parsing type identifier '%s' "
"failed for segment %i",
typestring, count);
continue;
}
}
/* Quirk for STM32F4 devices */
if (strcmp(name, "Device Feature") == 0)
memtype = 'e';
switch (multiplier) {
case 'B':
break;
case 'K':
size *= 1024;
break;
case 'M':
size *= 1024 * 1024;
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
if (!memtype) {
warnx("Non-valid multiplier '%c', "
"interpreted as type "
"identifier instead",
multiplier);
memtype = multiplier;
break;
}
/* if memtype was already set: */
/* fall-through */
default:
warnx("Non-valid multiplier '%c', "
"assuming bytes", multiplier);
}
if (!memtype) {
warnx("No valid type for segment %d\n", count);
continue;
}
segment.start = address;
segment.end = address + sectors * size - 1;
segment.pagesize = size;
segment.memtype = memtype & 7;
add_segment(&segment_list, segment);
if (verbose)
printf("Memory segment at 0x%08x %3d x %4d = "
"%5d (%s%s%s)\n",
address, sectors, size, sectors * size,
memtype & DFUSE_READABLE ? "r" : "",
memtype & DFUSE_ERASABLE ? "e" : "",
memtype & DFUSE_WRITEABLE ? "w" : "");
address += sectors * size;
separator = *intf_desc;
if (separator == ',')
intf_desc += 1;
else
break;
} /* while per segment */
} /* while per address */
free(name);
free(typestring);
return segment_list;
}

View File

@ -1,44 +0,0 @@
/* Helper functions for reading the memory map in a device
* following the ST DfuSe 1.1a specification.
*
* (C) 2011 Tormod Volden <debian.tormod@gmail.com>
*
* 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
*/
#ifndef DFUSE_MEM_H
#define DFUSE_MEM_H
#define DFUSE_READABLE 1
#define DFUSE_ERASABLE 2
#define DFUSE_WRITEABLE 4
struct memsegment {
unsigned int start;
unsigned int end;
int pagesize;
int memtype;
struct memsegment *next;
};
int add_segment(struct memsegment **list, struct memsegment new_element);
struct memsegment *find_segment(struct memsegment *list, unsigned int address);
void free_segment_list(struct memsegment *list);
struct memsegment *parse_memory_layout(char *intf_desc_str);
#endif /* DFUSE_MEM_H */

View File

@ -1,73 +0,0 @@
#ifndef PORTABLE_H
#define PORTABLE_H
#ifndef HAVE_CONFIG_H
# define PACKAGE "dfu-util"
# define PACKAGE_VERSION "0.11-msvc"
# define PACKAGE_STRING "dfu-util 0.11-msvc"
# define PACKAGE_BUGREPORT "http://sourceforge.net/p/dfu-util/tickets/"
# include <io.h>
/* FIXME if off_t is a typedef it is not a define */
# ifndef off_t
# define off_t long int
# endif
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef HAVE_NANOSLEEP
# include <time.h>
# define milli_sleep(msec) do {\
if (msec != 0) {\
struct timespec nanosleepDelay = { (msec) / 1000, ((msec) % 1000) * 1000000 };\
nanosleep(&nanosleepDelay, NULL);\
} } while (0)
#elif defined HAVE_WINDOWS_H
# define milli_sleep(msec) do {\
if (msec != 0) {\
Sleep(msec);\
} } while (0)
#else
# error "Can't get no sleep! Please report"
#endif /* HAVE_NANOSLEEP */
#ifdef HAVE_ERR
# include <err.h>
#else
# include <errno.h>
# include <string.h>
# define warnx(...) do {\
fprintf(stderr, __VA_ARGS__);\
fprintf(stderr, "\n"); } while (0)
# define errx(eval, ...) do {\
warnx(__VA_ARGS__);\
exit(eval); } while (0)
# define warn(...) do {\
fprintf(stderr, "%s: ", strerror(errno));\
warnx(__VA_ARGS__); } while (0)
# define err(eval, ...) do {\
warn(__VA_ARGS__);\
exit(eval); } while (0)
#endif /* HAVE_ERR */
#ifdef HAVE_SYSEXITS_H
# include <sysexits.h>
#else
# define EX_OK 0 /* successful termination */
# define EX_USAGE 64 /* command line usage error */
# define EX_DATAERR 65
# define EX_NOINPUT 66
# define EX_SOFTWARE 70 /* internal software error */
# define EX_CANTCREAT 73 /* input/output error */
# define EX_IOERR 74 /* input/output error */
# define EX_PROTOCOL 76 /* input/output error */
#endif /* HAVE_SYSEXITS_H */
#ifndef O_BINARY
# define O_BINARY 0
#endif
#endif /* PORTABLE_H */

View File

@ -1,127 +0,0 @@
/*
* Simple quirk system for dfu-util
*
* Copyright 2010-2017 Tormod Volden
*
* 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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "portable.h"
#include "quirks.h"
#include "dfuse_mem.h"
uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice)
{
uint16_t quirks = 0;
/* Device returns bogus bwPollTimeout values */
if ((vendor == VENDOR_OPENMOKO || vendor == VENDOR_FIC) &&
product >= PRODUCT_FREERUNNER_FIRST &&
product <= PRODUCT_FREERUNNER_LAST)
quirks |= QUIRK_POLLTIMEOUT;
if (vendor == VENDOR_VOTI &&
(product == PRODUCT_OPENPCD || product == PRODUCT_SIMTRACE ||
product == PRODUCT_OPENPICC))
quirks |= QUIRK_POLLTIMEOUT;
/* Reports wrong DFU version in DFU descriptor */
if (vendor == VENDOR_LEAFLABS &&
product == PRODUCT_MAPLE3 &&
bcdDevice == 0x0200)
quirks |= QUIRK_FORCE_DFU11;
/* old devices(bcdDevice == 0) return bogus bwPollTimeout values */
if (vendor == VENDOR_SIEMENS &&
(product == PRODUCT_PXM40 || product == PRODUCT_PXM50) &&
bcdDevice == 0)
quirks |= QUIRK_POLLTIMEOUT;
/* M-Audio Transit returns bogus bwPollTimeout values */
if (vendor == VENDOR_MIDIMAN &&
product == PRODUCT_TRANSIT)
quirks |= QUIRK_POLLTIMEOUT;
/* Some GigaDevice GD32 devices have improperly-encoded serial numbers
* and bad DfuSe descriptors which we use serial number to correct.
* They also "leave" without a DFU_GETSTATUS request */
if (vendor == VENDOR_GIGADEVICE &&
product == PRODUCT_GD32) {
quirks |= QUIRK_UTF8_SERIAL;
quirks |= QUIRK_DFUSE_LAYOUT;
quirks |= QUIRK_DFUSE_LEAVE;
}
return (quirks);
}
#define GD32VF103_FLASH_BASE 0x08000000
void fixup_dfuse_layout(struct dfu_if *dif, struct memsegment **segment_list)
{
if (dif->vendor == VENDOR_GIGADEVICE &&
dif->product == PRODUCT_GD32 &&
dif->altsetting == 0 &&
dif->serial_name &&
strlen(dif->serial_name) == 4 &&
dif->serial_name[0] == '3' &&
dif->serial_name[3] == 'J') {
struct memsegment *seg;
int count;
printf("Found GD32VF103, which reports a bad page size and "
"count for its internal memory.\n");
seg = find_segment(*segment_list, GD32VF103_FLASH_BASE);
if (!seg) {
warnx("Could not fix GD32VF103 layout because there "
"is no segment at 0x%08x", GD32VF103_FLASH_BASE);
return;
}
/* All GD32VF103 have this page size, according to Nucleisys's
* dfu-util (https://github.com/riscv-mcu/gd32-dfu-utils/). */
seg->pagesize = 1024;
/* From Tables 2-1 and 2-2 ("devices features and peripheral
* list") in the GD32VF103 Datasheet */
if (dif->serial_name[2] == 'B') {
count = 128;
} else if (dif->serial_name[2] == '8') {
count = 64;
} else if (dif->serial_name[2] == '6') {
count = 32;
} else if (dif->serial_name[2] == '4') {
count = 16;
} else {
warnx("Unknown flash size '%c' in part number; "
"defaulting to 128KB.", dif->serial_name[2]);
count = 128;
}
seg->end = seg->start + (count * seg->pagesize) - 1;
printf("Fixed layout based on part number: page size %d, "
"count %d.\n", seg->pagesize, count);
}
}

View File

@ -1,38 +0,0 @@
#ifndef DFU_QUIRKS_H
#define DFU_QUIRKS_H
#include "dfu.h"
#include "dfuse_mem.h"
#define VENDOR_OPENMOKO 0x1d50 /* Openmoko Freerunner / GTA02 */
#define VENDOR_FIC 0x1457 /* Openmoko Freerunner / GTA02 */
#define VENDOR_VOTI 0x16c0 /* OpenPCD Reader */
#define VENDOR_LEAFLABS 0x1eaf /* Maple */
#define VENDOR_SIEMENS 0x0908 /* Siemens AG */
#define VENDOR_MIDIMAN 0x0763 /* Midiman */
#define VENDOR_GIGADEVICE 0x28e9 /* GigaDevice */
#define PRODUCT_FREERUNNER_FIRST 0x5117
#define PRODUCT_FREERUNNER_LAST 0x5126
#define PRODUCT_SIMTRACE 0x0762
#define PRODUCT_OPENPCD 0x076b
#define PRODUCT_OPENPICC 0x076c
#define PRODUCT_MAPLE3 0x0003 /* rev 3 and 5 */
#define PRODUCT_PXM40 0x02c4 /* Siemens AG, PXM 40 */
#define PRODUCT_PXM50 0x02c5 /* Siemens AG, PXM 50 */
#define PRODUCT_TRANSIT 0x2806 /* M-Audio Transit (Midiman) */
#define PRODUCT_GD32 0x0189 /* GigaDevice GD32VF103 rev 1 */
#define QUIRK_POLLTIMEOUT (1<<0)
#define QUIRK_FORCE_DFU11 (1<<1)
#define QUIRK_UTF8_SERIAL (1<<2)
#define QUIRK_DFUSE_LAYOUT (1<<3)
#define QUIRK_DFUSE_LEAVE (1<<4)
/* Fallback value, works for OpenMoko */
#define DEFAULT_POLLTIMEOUT 5
uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice);
void fixup_dfuse_layout(struct dfu_if *dif, struct memsegment **segment_list);
#endif /* DFU_QUIRKS_H */

View File

@ -1,103 +0,0 @@
#ifndef USB_DFU_H
#define USB_DFU_H
/* USB Device Firmware Update Implementation for OpenPCD
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
*
* Protocol definitions for USB DFU
*
* This ought to be compliant to the USB DFU Spec 1.0 as available from
* http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
*
* 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 <stdint.h>
#define USB_DT_DFU 0x21
#ifdef _MSC_VER
# pragma pack(push)
# pragma pack(1)
#endif /* _MSC_VER */
struct usb_dfu_func_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bmAttributes;
#define USB_DFU_CAN_DOWNLOAD (1 << 0)
#define USB_DFU_CAN_UPLOAD (1 << 1)
#define USB_DFU_MANIFEST_TOL (1 << 2)
#define USB_DFU_WILL_DETACH (1 << 3)
uint16_t wDetachTimeOut;
uint16_t wTransferSize;
uint16_t bcdDFUVersion;
#ifdef _MSC_VER
};
# pragma pack(pop)
#elif defined __GNUC__
# if defined __MINGW32__
} __attribute__ ((__packed__, __gcc_struct__));
# else
} __attribute__ ((__packed__));
# endif
#else
#warning "No way to pack struct on this compiler? This will break!"
#endif /* _MSC_VER */
#define USB_DT_DFU_SIZE 9
#define USB_TYPE_DFU (LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE)
/* DFU class-specific requests (Section 3, DFU Rev 1.1) */
#define USB_REQ_DFU_DETACH 0x00
#define USB_REQ_DFU_DNLOAD 0x01
#define USB_REQ_DFU_UPLOAD 0x02
#define USB_REQ_DFU_GETSTATUS 0x03
#define USB_REQ_DFU_CLRSTATUS 0x04
#define USB_REQ_DFU_GETSTATE 0x05
#define USB_REQ_DFU_ABORT 0x06
/* DFU_GETSTATUS bStatus values (Section 6.1.2, DFU Rev 1.1) */
#define DFU_STATUS_OK 0x00
#define DFU_STATUS_errTARGET 0x01
#define DFU_STATUS_errFILE 0x02
#define DFU_STATUS_errWRITE 0x03
#define DFU_STATUS_errERASE 0x04
#define DFU_STATUS_errCHECK_ERASED 0x05
#define DFU_STATUS_errPROG 0x06
#define DFU_STATUS_errVERIFY 0x07
#define DFU_STATUS_errADDRESS 0x08
#define DFU_STATUS_errNOTDONE 0x09
#define DFU_STATUS_errFIRMWARE 0x0a
#define DFU_STATUS_errVENDOR 0x0b
#define DFU_STATUS_errUSBR 0x0c
#define DFU_STATUS_errPOR 0x0d
#define DFU_STATUS_errUNKNOWN 0x0e
#define DFU_STATUS_errSTALLEDPKT 0x0f
enum dfu_state {
DFU_STATE_appIDLE = 0,
DFU_STATE_appDETACH = 1,
DFU_STATE_dfuIDLE = 2,
DFU_STATE_dfuDNLOAD_SYNC = 3,
DFU_STATE_dfuDNBUSY = 4,
DFU_STATE_dfuDNLOAD_IDLE = 5,
DFU_STATE_dfuMANIFEST_SYNC = 6,
DFU_STATE_dfuMANIFEST = 7,
DFU_STATE_dfuMANIFEST_WAIT_RST = 8,
DFU_STATE_dfuUPLOAD_IDLE = 9,
DFU_STATE_dfuERROR = 10
};
#endif /* USB_DFU_H */