arduino-dfu-discovery: Use DISTFILES instead of files dir
This commit is contained in:
parent
4d4b0994e8
commit
378320abe8
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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",
|
||||
§ors, &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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
Loading…
Reference in New Issue