diff options
author | Harald Welte <laforge@gnumonks.org> | 2017-02-26 17:00:43 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2017-02-27 09:28:34 +0100 |
commit | 7ed6f3bc375f4eddecb7ccf10e837f3068cb4e42 (patch) | |
tree | cd89e0edc25a809f43cedec582384e9067738f43 | |
parent | aa3b867abb3e5887cb3b3b5a28bcb7c0c97482be (diff) |
WIP: Introduce USB DFU code from my at91lib DFU port
-rw-r--r-- | firmware/Makefile | 7 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/common/dfu/usb_dfu.h | 81 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu.c | 49 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h | 130 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c | 124 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c | 466 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c | 189 | ||||
-rw-r--r-- | firmware/include_board/board_common.h | 8 | ||||
-rw-r--r-- | firmware/src_board/board_cstartup_gnu.c | 21 | ||||
-rw-r--r-- | firmware/src_sam3s/USBD_HAL.c | 7 | ||||
-rw-r--r-- | firmware/src_simtrace/usb.c | 33 |
11 files changed, 1104 insertions, 11 deletions
diff --git a/firmware/Makefile b/firmware/Makefile index e500bea..6092e8c 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -72,6 +72,7 @@ OBJ = obj AT91LIB_USB_COMMON_CORE_PATH = atmel_softpack_libraries/usb/common/core AT91LIB_USB_CORE_PATH = atmel_softpack_libraries/usb/device/core +AT91LIB_USB_DFU_PATH = atmel_softpack_libraries/usb/device/dfu # Tool suffix when cross-compiling CROSS_COMPILE = arm-none-eabi- @@ -91,7 +92,7 @@ TOP=.. GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers) # Flags -INCLUDES_USB = -Iatmel_softpack_libraries/usb/include +INCLUDES_USB = -Iatmel_softpack_libraries/usb/include -Iatmel_softpack_libraries INCLUDES = -Iinclude_board -Iinclude_sam3s -Iinclude -Isrc_simtrace -Iinclude_libosmocore @@ -139,13 +140,13 @@ LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-secti # Directories where source files can be found -USB_PATHS = $(AT91LIB_USB_CORE_PATH) $(AT91LIB_USB_COMMON_CORE_PATH) +USB_PATHS = $(AT91LIB_USB_CORE_PATH) $(AT91LIB_USB_DFU_PATH) $(AT91LIB_USB_COMMON_CORE_PATH) VPATH += src_board src_sam3s cmsis $(USB_PATHS) src_simtrace src_libosmocore # Objects built from C source files C_CMSIS = core_cm3.o C_LOWLEVEL = board_cstartup_gnu.o board_lowlevel.o syscalls.o exceptions.o -C_LIBLEVEL = spi.o pio.o pmc.o usart.o pio_it.o pio_capture.o uart_console.o iso7816_4.o wdt.o efc.o flashd.o led.o tc.o unique_id.o boardver_adc.o +C_LIBLEVEL = spi.o pio.o pmc.o usart.o pio_it.o pio_capture.o uart_console.o iso7816_4.o wdt.o efc.o flashd.o led.o tc.o unique_id.o boardver_adc.o dfu_desc.o dfu_runtime.o C_CCID = cciddriver.o USBD.o USBDDriver.o USBD_HAL.o USBRequests.o USBDCallbacks.o USBDescriptors.o USBDDriverCallbacks.o C_SIMTRACE = simtrace_iso7816.o usb.o ccid.o sniffer.o mitm.o ringbuffer.o host_communication.o iso7816_fidi.o tc_etu.o req_ctx.o card_emu.o mode_cardemu.o i2c.o wwan_led.o wwan_perst.o C_OSMOCORE = timer.o rbtree.o diff --git a/firmware/atmel_softpack_libraries/usb/common/dfu/usb_dfu.h b/firmware/atmel_softpack_libraries/usb/common/dfu/usb_dfu.h new file mode 100644 index 0000000..d3acb09 --- /dev/null +++ b/firmware/atmel_softpack_libraries/usb/common/dfu/usb_dfu.h @@ -0,0 +1,81 @@ +#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 + * + */ + +#include <stdint.h> + +#include <usb/include/USBRequests.h> + +#define USB_DT_DFU 0x21 + +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; +} __attribute__ ((packed)); + +#define USB_DT_DFU_SIZE 9 + +/* 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 + +struct dfu_status { + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} __attribute__((packed)); + +#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 */ diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.c new file mode 100644 index 0000000..bc6b29c --- /dev/null +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.c @@ -0,0 +1,49 @@ + +#include <usb/include/USBDescriptors.h> +#include <usb/device/dfu/dfu.h> + + +/* String 1 "SimTrace DFU Interface - Application Partition" */ +const struct USBStringDescriptor USBDFU_string1 = { + .hdr = { + .bLength = sizeof(USBGenericDescriptor) + 46 * sizeof(unsigned short), + .bDescriptorType = USBGenericDescriptor_STRING, + }, + .wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061, + 0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055, + 0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072, + 0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d, + 0x0020, 0x0041, 0x0070, 0x0070, 0x006c, 0x0069, + 0x0063, 0x0061, 0x0074, 0x0069, 0x006f, 0x006e, + 0x0020, 0x0050, 0x0061, 0x0072, 0x0074, 0x0069, + 0x0074, 0x0069, 0x006f, 0x006e, }, +}; + +/* String 2 "SimTrace DFU Interface - Bootloader Partition" */ +const struct USBStringDescriptor USBDFU_string2 = { + .hdr = { + .bLength = sizeof(USBGenericDescriptor) + 45 * sizeof(unsigned short), + .bDescriptorType = USBGenericDescriptor_STRING, + }, + .wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061, + 0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055, + 0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072, + 0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d, + 0x0020, 0x0042, 0x006f, 0x006f, 0x0074, 0x006c, + 0x006f, 0x0061, 0x0064, 0x0065, 0x0072, 0x0020, + 0x0050, 0x0061, 0x0072, 0x0074, 0x0069, 0x0074, + 0x0069, 0x006f, 0x006e, }, +}; + +/* String 3 "SimTrace DFU Interface - RAM" */ +const struct USBStringDescriptor USBDFU_string3 = { + .hdr = { + .bLength = sizeof(USBGenericDescriptor) + 28 * sizeof(unsigned short), + .bDescriptorType = USBGenericDescriptor_STRING, + }, + .wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061, + 0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055, + 0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072, + 0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d, + 0x0020, 0x0052, 0x0041, 0x004d, }, +}; diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h new file mode 100644 index 0000000..9033de6 --- /dev/null +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h @@ -0,0 +1,130 @@ +#ifndef _USB_DEV_DFU_H +#define _USB_DEV_DFU_H + +#include <stdint.h> +#include <board.h> +#include <usb/include/USBDescriptors.h> +#include <usb/include/USBDDriver.h> + +#if 0 +/* This is valid for CCID */ +#define CONFIG_DFU_NUM_APP_IF 1 +#define CONFIG_DFU_NUM_APP_STR 4 +#else +/* This is valid for CDC-Serial */ +#define CONFIG_DFU_NUM_APP_IF 2 +#define CONFIG_DFU_NUM_APP_STR 2 +#endif + +struct USBStringDescriptor { + USBGenericDescriptor hdr; + unsigned short wData[]; +} __attribute__((packed)); + + +#ifdef BOARD_USB_DFU + +#include <usb/common/dfu/usb_dfu.h> + +/* for board-specific config */ +#include <board.h> + +struct dfu_desc { + USBConfigurationDescriptor ucfg; + USBInterfaceDescriptor uif[BOARD_DFU_NUM_IF]; + struct usb_dfu_func_descriptor func_dfu; +} __attribute__ ((packed)); + +/* USB DFU functional descriptor */ +#define DFU_FUNC_DESC { \ + .bLength = USB_DT_DFU_SIZE, \ + .bDescriptorType = USB_DT_DFU, \ + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \ + .wDetachTimeOut = 0xff00, \ + .wTransferSize = BOARD_DFU_PAGE_SIZE, \ + .bcdDFUVersion = 0x0100, \ +} + +/* Number of DFU interface during runtime mode */ +#define DFURT_NUM_IF 1 + +/* to be used by the runtime as part of its USB descriptor structure + * declaration */ +#define DFURT_IF_DESCRIPTOR_STRUCT \ + USBInterfaceDescriptor dfu_rt; \ + struct usb_dfu_func_descriptor func_dfu; + +/* to be used by the runtime as part of its USB Dsecriptor structure + * definition */ +#define DFURT_IF_DESCRIPTOR(dfuIF, dfuSTR) \ + .dfu_rt = { \ + .bLength = sizeof(USBInterfaceDescriptor), \ + .bDescriptorType = USBGenericDescriptor_INTERFACE, \ + .bInterfaceNumber = dfuIF, \ + .bAlternateSetting = 0, \ + .bNumEndpoints = 0, \ + .bInterfaceClass = 0xFE, \ + .bInterfaceSubClass = 0x01, \ + .bInterfaceProtocol = 0x01, \ + .iInterface = dfuSTR, \ + }, \ + .func_dfu = DFU_FUNC_DESC \ + +/* provided by dfu_desc.c */ +extern const struct dfu_desc dfu_cfg_descriptor; +extern const USBDDriverDescriptors dfu_descriptors; + +#else /* BOARD_USB_DFU */ + +/* no DFU bootloader is being used */ +#define DFURT_NUM_IF 0 +#define DFURT_IF_DESCRIPTOR_STRUCT(a, b) +#define DFURT_IF_DESCRIPTOR + +#endif /* BOARD_USB_DFU */ + +/* magic value we use during boot to detect if we should start in DFU + * mode or runtime mode */ +#define USB_DFU_MAGIC 0xDFDFDFDF +/* RAM address for this magic value above */ +#define USB_DFU_MAGIC_ADDR IRAM_ADDR + +/* The API between the core DFU handler and the board/soc specific code */ + +struct dfudata { + uint8_t status; + uint32_t state; + int past_manifest; + unsigned int total_bytes; +}; + +extern struct dfudata g_dfu; + +void set_usb_serial_str(const uint8_t *serial_usbstr); + +void DFURT_SwitchToDFU(void); + +/* call-backs from DFU USB function driver to the board/SOC */ +extern int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, + uint8_t *data, unsigned int len); +extern int USBDFU_handle_upload(uint8_t altif, unsigned int offset, + uint8_t *data, unsigned int req_len); + +/* function to be called at end of EP0 handler during runtime */ +void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request); + +/* function to be called at end of EP0 handler during DFU mode */ +void USBDFU_DFU_RequestHandler(const USBGenericRequest *request); + +/* initialization of USB DFU driver (in DFU mode */ +void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors); + +/* USBD tells us to switch from DFU mode to application mode */ +void USBDFU_SwitchToApp(void); + +/* Return values to be used by USBDFU_handle_{dn,up}load */ +#define DFU_RET_NOTHING 0 +#define DFU_RET_ZLP 1 +#define DFU_RET_STALL 2 + +#endif diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c new file mode 100644 index 0000000..c325606 --- /dev/null +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c @@ -0,0 +1,124 @@ +/* DFU related USB Descriptors */ +/* (C) 2006-2017 Harald Welte <hwelte@hmw-consulting.de> */ + +#include <unistd.h> + +#include "board.h" + +#include <usb/include/USBDescriptors.h> + +#include <usb/include/USBDDriver.h> + +#include <usb/common/dfu/usb_dfu.h> +#include <usb/device/dfu/dfu.h> + +enum { + STR_MANUF = 1, + STR_PROD, + STR_CONFIG, + _STR_FIRST_ALT, + STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF), +}; + +static const USBDeviceDescriptor fsDevice = { + .bLength = sizeof(USBDeviceDescriptor), + .bDescriptorType = USBGenericDescriptor_DEVICE, + .bcdUSB = USBDeviceDescriptor_USB2_00, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0), + .idVendor = BOARD_USB_VENDOR, + .idProduct = BOARD_USB_PRODUCT, + .bcdDevice = BOARD_USB_RELEASE, + .iManufacturer = STR_MANUF, + .iProduct = STR_PROD, +#ifdef BOARD_USB_SERIAL + .iSerialNumber = STR_SERIAL, +#else + .iSerialNumber = 0, +#endif + .bNumConfigurations = 1, +}; + +/* Alternate Interface Descriptor, we use one per partition/memory type */ +#define DFU_IF(ALT) \ + { \ + .bLength = sizeof(USBInterfaceDescriptor), \ + .bDescriptorType = USBGenericDescriptor_INTERFACE, \ + .bInterfaceNumber = 0, \ + .bAlternateSetting = ALT, \ + .bNumEndpoints = 0, \ + .bInterfaceClass = 0xfe, \ + .bInterfaceSubClass = 1, \ + .iInterface = (_STR_FIRST_ALT+ALT), \ + .bInterfaceProtocol = 2, \ + } + +/* overall descriptor for the DFU configuration, including all + * descriptors for alternate interfaces */ +const struct dfu_desc dfu_cfg_descriptor = { + .ucfg = { + .bLength = sizeof(USBConfigurationDescriptor), + .bDescriptorType = USBGenericDescriptor_CONFIGURATION, + .wTotalLength = sizeof(USBConfigurationDescriptor) + + BOARD_DFU_NUM_IF * sizeof(USBInterfaceDescriptor) + + sizeof(struct usb_dfu_func_descriptor), + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = STR_CONFIG, + .bmAttributes = BOARD_USB_BMATTRIBUTES, + .bMaxPower = 100, + }, + .uif[0] = DFU_IF(0), +#if BOARD_DFU_NUM_IF > 1 + .uif[1] = DFU_IF(1), +#endif +#if BOARD_DFU_NUM_IF > 2 + .uif[2] = DFU_IF(2), +#endif +#if BOARD_DFU_NUM_IF > 3 + .uif[3] = DFU_IF(3), +#endif +#if BOARD_DFU_NUM_IF > 4 + .uif[4] = DFU_IF(4), +#endif + .func_dfu = DFU_FUNC_DESC +}; + +#if 0 +#include "usb_strings.h" + + +static const unsigned char *usb_strings[] = { + USB_STRINGS_GENERATED +#ifdef BOARD_USB_SERIAL + NULL +#endif +}; + +void set_usb_serial_str(const uint8_t *serial_usbstr) +{ + usb_strings[STR_SERIAL] = serial_usbstr; +} +#endif + +const USBDDriverDescriptors dfu_descriptors = { + .pFsDevice = &fsDevice, + .pFsConfiguration = &dfu_cfg_descriptor.ucfg, +//#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS) +#if 0 // DFU only supports FS for now + .pFsQualifier = , + .pFsOtherSpeed = , + .pHsDevice = , + .pHsConfiguration = , + .pHsQualifier = , + .pHsOtherSpeed = , +#else + 0, 0, 0, 0, 0, 0, +#endif +#if 0 + .pStrings = usb_strings, + .numStrings = ARRAY_SIZE(usb_strings), +#endif +}; diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c new file mode 100644 index 0000000..94bfc02 --- /dev/null +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c @@ -0,0 +1,466 @@ +/* USB Device Firmware Update Implementation for OpenPCD, OpenPICC SIMtrace + * (C) 2006-2017 by Harald Welte <hwelte@hmw-consulting.de> + * + * 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 <unistd.h> + +#include <board.h> +#include <core_cm3.h> + +#include "trace.h" + +#include <usb/include/USBDescriptors.h> +#include <usb/include/USBRequests.h> +#include <usb/include/USBD.h> +#include <usb/common/dfu/usb_dfu.h> +#include <usb/device/dfu/dfu.h> + +/* FIXME: this was used for a special ELF section which then got called + * by DFU code and Application code, across flash partitions */ +#define __dfudata +#define __dfufunc + +/// Standard device driver instance. +static USBDDriver usbdDriver; +static unsigned char if_altsettings[1]; + +__dfudata struct dfudata g_dfu = { + .state = DFU_STATE_appIDLE, + .past_manifest = 0, + .total_bytes = 0, +}; + +WEAK void dfu_drv_updatatus(void) +{ + TRACE_INFO("DFU: updstatus()\n\r"); + + /* we transition immediately from MANIFEST_SYNC to MANIFEST, + * as the flash-writing is not asynchronous in this + * implementation */ + if (g_dfu.state == DFU_STATE_dfuMANIFEST_SYNC) + g_dfu.state = DFU_STATE_dfuMANIFEST; +} + +static __dfufunc void handle_getstatus(void) +{ + /* has to be static as USBD_Write is async ? */ + static struct dfu_status dstat; + + dfu_drv_updstatus(); + + /* send status response */ + dstat.bStatus = g_dfu.status; + dstat.bState = g_dfu.state; + dstat.iString = 0; + /* FIXME: set dstat.bwPollTimeout */ + + TRACE_DEBUG("handle_getstatus(%u, %u)\n\r", dstat.bStatus, dstat.bState); + + USBD_Write(0, (char *)&dstat, sizeof(dstat), NULL, 0); +} + +static void __dfufunc handle_getstate(void) +{ + uint8_t u8 = g_dfu.state; + + TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu.state); + + USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); +} + +static void TerminateCtrlInWithNull(void *pArg, + unsigned char status, + unsigned long int transferred, + unsigned long int remaining) +{ + USBD_Write(0, // Endpoint #0 + 0, // No data buffer + 0, // No data buffer + (TransferCallback) 0, + (void *) 0); +} + +static uint8_t dfu_buf[BOARD_DFU_PAGE_SIZE]; + +/* download of a single page has completed */ +static void dnload_cb(void *arg, unsigned char status, unsigned long int transferred, + unsigned long int remaining) +{ + int rc; + + TRACE_DEBUG("COMPLETE\n\r"); + + if (status != USBD_STATUS_SUCCESS) { + TRACE_ERROR("USBD download callback status %d\n\r", status); + USBD_Stall(0); + return; + } + + rc = USBDFU_handle_dnload(if_altsettings[0], g_dfu.total_bytes, dfu_buf, transferred); + switch (rc) { + case DFU_RET_ZLP: + g_dfu.total_bytes += transferred; + g_dfu.state = DFU_STATE_dfuDNLOAD_IDLE; + TerminateCtrlInWithNull(0,0,0,0); + break; + case DFU_RET_STALL: + g_dfu.state = DFU_STATE_dfuERROR; + USBD_Stall(0); + break; + case DFU_RET_NOTHING: + break; + } + +} + +static int handle_dnload(uint16_t val, uint16_t len, int first) +{ + int rc; + + if (len > BOARD_DFU_PAGE_SIZE) { + TRACE_ERROR("DFU length exceeds flash page size\n\r"); + g_dfu.state = DFU_STATE_dfuERROR; + g_dfu.status = DFU_STATUS_errADDRESS; + return DFU_RET_STALL; + } + + if (len & 0x03) { + TRACE_ERROR("DFU length not four-byte-aligned\n\r"); + g_dfu.state = DFU_STATE_dfuERROR; + g_dfu.status = DFU_STATUS_errADDRESS; + return DFU_RET_STALL; + } + + if (first) + g_dfu.total_bytes = 0; + + if (len == 0) { + TRACE_DEBUG("zero-size write -> MANIFEST_SYNC\n\r"); + g_dfu.state = DFU_STATE_dfuMANIFEST_SYNC; + return DFU_RET_ZLP; + } + + /* else: actually read data */ + rc = USBD_Read(0, dfu_buf, len, &dnload_cb, 0); + if (rc == USBD_STATUS_SUCCESS) + return DFU_RET_NOTHING; + else + return DFU_RET_STALL; +} + +/* upload of a single page has completed */ +static void upload_cb(void *arg, unsigned char status, unsigned long int transferred, + unsigned long int remaining) +{ + int rc; + + TRACE_DEBUG("COMPLETE\n\r"); + + if (status != USBD_STATUS_SUCCESS) { + TRACE_ERROR("USBD upload callback status %d\n\r", status); + USBD_Stall(0); + return; + } + + g_dfu.total_bytes += transferred; +} + +static int handle_upload(uint16_t val, uint16_t len, int first) +{ + int rc; + + if (first) + g_dfu.total_bytes = 0; + + if (len > BOARD_DFU_PAGE_SIZE) { + TRACE_ERROR("DFU length exceeds flash page size\n\r"); + g_dfu.state = DFU_STATE_dfuERROR; + g_dfu.status = DFU_STATUS_errADDRESS; + return DFU_RET_STALL; + } + + rc = USBDFU_handle_upload(if_altsettings[0], g_dfu.total_bytes, dfu_buf, len); + if (rc < 0) { + TRACE_ERROR("application handle_upload() returned %d\n\r", rc); + return DFU_RET_STALL; + } + + if (USBD_Write(0, dfu_buf, rc, &upload_cb, 0) == USBD_STATUS_SUCCESS) + return rc; + + return DFU_RET_STALL; +} + +/* this function gets daisy-chained into processing EP0 requests */ +void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) +{ + uint8_t req = USBGenericRequest_GetRequest(request); + uint16_t len = USBGenericRequest_GetLength(request); + uint16_t val = USBGenericRequest_GetValue(request); + int rc, ret; + + TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r", + USBGenericRequest_GetType(request), + USBGenericRequest_GetRecipient(request), + val, len); + + /* check for GET_DESCRIPTOR on DFU */ + if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD && + USBGenericRequest_GetRecipient(request) == USBGenericRequest_DEVICE && + USBGenericRequest_GetRequest(request) == USBGenericRequest_GETDESCRIPTOR && + USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) { + uint16_t length = sizeof(struct usb_dfu_func_descriptor); + const USBDeviceDescriptor *pDevice; + int terminateWithNull; + + if (USBD_IsHighSpeed()) + pDevice = usbdDriver.pDescriptors->pHsDevice; + else + pDevice = usbdDriver.pDescriptors->pFsDevice; + + terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); + USBD_Write(0, &dfu_cfg_descriptor.func_dfu, length, + terminateWithNull ? TerminateCtrlInWithNull : 0, 0); + return; + } + + /* forward all non-DFU specific messages to core handler*/ + if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS || + USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) { + TRACE_DEBUG("std_ho_usbd "); + USBDDriver_RequestHandler(&usbdDriver, request); + } + + switch (g_dfu.state) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + TRACE_ERROR("Invalid DFU State reached in DFU mode\r\n"); + ret = DFU_RET_STALL; + break; + case DFU_STATE_dfuIDLE: + switch (req) { + case USB_REQ_DFU_DNLOAD: + if (len == 0) { + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + goto out; + } + g_dfu.state = DFU_STATE_dfuDNLOAD_SYNC; + ret = handle_dnload(val, len, 1); + break; + case USB_REQ_DFU_UPLOAD: + g_dfu.state = DFU_STATE_dfuUPLOAD_IDLE; + handle_upload(val, len, 1); + break; + case USB_REQ_DFU_ABORT: + /* no zlp? */ + ret = DFU_RET_ZLP; + break; + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + goto out; + break; + } + break; + case DFU_STATE_dfuDNLOAD_SYNC: + switch (req) { + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + /* FIXME: state transition depending on block completeness */ + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + goto out; + } + break; + case DFU_STATE_dfuDNBUSY: + switch (req) { + case USB_REQ_DFU_GETSTATUS: + /* FIXME: only accept getstatus if bwPollTimeout + * has elapsed */ + handle_getstatus(); + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + goto out; + } + break; + case DFU_STATE_dfuDNLOAD_IDLE: + switch (req) { + case USB_REQ_DFU_DNLOAD: + g_dfu.state = DFU_STATE_dfuDNLOAD_SYNC; + ret = handle_dnload(val, len, 0); + break; + case USB_REQ_DFU_ABORT: + g_dfu.state = DFU_STATE_dfuIDLE; + ret = DFU_RET_ZLP; + break; + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + break; + } + break; + case DFU_STATE_dfuMANIFEST_SYNC: + switch (req) { + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + break; + } + break; + case DFU_STATE_dfuMANIFEST: + switch (req) { + case USB_REQ_DFU_GETSTATUS: + /* we don't want to change to WAIT_RST, as it + * would mean that we can not support another + * DFU transaction before doing the actual + * reset. Instead, we switch to idle and note + * that we've already been through MANIFST in + * the global variable 'past_manifest'. + */ + //g_dfu.state = DFU_STATE_dfuMANIFEST_WAIT_RST; + g_dfu.state = DFU_STATE_dfuIDLE; + g_dfu.past_manifest = 1; + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + break; + } + break; + case DFU_STATE_dfuMANIFEST_WAIT_RST: + /* we should never go here */ + break; + case DFU_STATE_dfuUPLOAD_IDLE: + switch (req) { + case USB_REQ_DFU_UPLOAD: + /* state transition if less data then requested */ + rc = handle_upload(val, len, 0); + if (rc >= 0 && rc < len) + g_dfu.state = DFU_STATE_dfuIDLE; + break; + case USB_REQ_DFU_ABORT: + g_dfu.state = DFU_STATE_dfuIDLE; + /* no zlp? */ + ret = DFU_RET_ZLP; + break; + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + break; + } + break; + case DFU_STATE_dfuERROR: + switch (req) { + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + case USB_REQ_DFU_CLRSTATUS: + g_dfu.state = DFU_STATE_dfuIDLE; + g_dfu.status = DFU_STATUS_OK; + /* no zlp? */ + ret = DFU_RET_ZLP; + break; + default: + g_dfu.state = DFU_STATE_dfuERROR; + ret = DFU_RET_STALL; + break; + } + break; + } + +out: + switch (ret) { + case DFU_RET_NOTHING: + break; + case DFU_RET_ZLP: + USBD_Write(0, 0, 0, 0, 0); + break; + case DFU_RET_STALL: + USBD_Stall(0); + break; + } +} + +void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + /* We already start in DFU idle mode */ + g_dfu.state = DFU_STATE_dfuIDLE; + + USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings); + + USBD_Init(); + USBD_ConfigureSpeed(1); +} + +void USBDFU_SwitchToApp(void) +{ + /* make sure the MAGIC is not set to enter DFU again */ + *(unsigned int *)USB_DFU_MAGIC_ADDR = 0; + + /* disconnect from USB to ensure re-enumeration */ + USBD_Disconnect(); + + /* disable any interrupts during transition */ + __disable_irq(); + + /* Tell the hybrid to execute FTL JUMP! */ + //BootIntoApp(); + NVIC_SystemReset(); +} diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c new file mode 100644 index 0000000..0102650 --- /dev/null +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c @@ -0,0 +1,189 @@ +/* DFU related functions that are active at runtime, i.e. during the + * normal operation of the device firmware, *not* during DFU update mode + * (C) 2006 Harald Welte <hwelte@hmw-consulting.de> + * + * 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 <board.h> +#include <core_cm3.h> + +#include <usb/include/USBD.h> +#include <usb/device/dfu/dfu.h> + +#include "trace.h" + +#include <usb/include/USBDescriptors.h> +#include <usb/include/USBRequests.h> +#include <usb/include/USBD.h> +#include <usb/common/dfu/usb_dfu.h> +#include <usb/device/dfu/dfu.h> + +/* FIXME: this was used for a special ELF section which then got called + * by DFU code and Application code, across flash partitions */ +#define __dfudata +#define __dfufunc + +static __dfufunc void handle_getstatus(void) +{ + /* has to be static as USBD_Write is async ? */ + static struct dfu_status dstat; + + /* send status response */ + dstat.bStatus = g_dfu.status; + dstat.bState = g_dfu.state; + dstat.iString = 0; + /* FIXME: set dstat.bwPollTimeout */ + + TRACE_DEBUG("handle_getstatus(%u, %u)\n\r", dstat.bStatus, dstat.bState); + + USBD_Write(0, (char *)&dstat, sizeof(dstat), NULL, 0); +} + +static void __dfufunc handle_getstate(void) +{ + uint8_t u8 = g_dfu.state; + + TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu.state); + + USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); +} + +static void TerminateCtrlInWithNull(void *pArg, + unsigned char status, + unsigned long int transferred, + unsigned long int remaining) +{ + USBD_Write(0, // Endpoint #0 + 0, // No data buffer + 0, // No data buffer + (TransferCallback) 0, + (void *) 0); +} + +/* this function gets daisy-chained into processing EP0 requests */ +void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request) +{ + USBDDriver *usbdDriver = USBD_GetDriver(); + uint8_t req = USBGenericRequest_GetRequest(request); + uint16_t len = USBGenericRequest_GetLength(request); + uint16_t val = USBGenericRequest_GetValue(request); + int rc, ret; + + TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r", + USBGenericRequest_GetType(request), + USBGenericRequest_GetRecipient(request), + val, len); + + /* check for GET_DESCRIPTOR on DFU */ + if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD && + USBGenericRequest_GetRecipient(request) == USBGenericRequest_DEVICE && + USBGenericRequest_GetRequest(request) == USBGenericRequest_GETDESCRIPTOR && + USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) { + uint16_t length = sizeof(struct usb_dfu_func_descriptor); + const USBDeviceDescriptor *pDevice; + int terminateWithNull; + + if (USBD_IsHighSpeed()) + pDevice = usbdDriver->pDescriptors->pHsDevice; + else + pDevice = usbdDriver->pDescriptors->pFsDevice; + + terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); + USBD_Write(0, &dfu_cfg_descriptor.func_dfu, length, + terminateWithNull ? TerminateCtrlInWithNull : 0, 0); + return; + } + + /* forward all non-DFU specific messages to core handler*/ + if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS || + USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) { + TRACE_DEBUG("std_ho_usbd "); + USBDDriver_RequestHandler(usbdDriver, request); + } + + switch (g_dfu.state) { + case DFU_STATE_appIDLE: + switch (req) { + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + case USB_REQ_DFU_DETACH: + /* we switch it DETACH state, send a ZLP and + * return. The next USB reset in this state + * will then trigger DFURT_SwitchToDFU() below */ + TRACE_DEBUG("\r\n====dfu_detach\n\r"); + g_dfu.state = DFU_STATE_appDETACH; + ret = DFU_RET_ZLP; + goto out; + break; + default: + ret = DFU_RET_STALL; + } + break; + case DFU_STATE_appDETACH: + switch (req) { + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + default: + g_dfu.state = DFU_STATE_appIDLE; + ret = DFU_RET_STALL; + goto out; + break; + } + /* FIXME: implement timer to return to appIDLE */ + break; + default: + TRACE_ERROR("Invalid DFU State reached in Runtime Mode\r\n"); + ret = DFU_RET_STALL; + break; + } + +out: + switch (ret) { + case DFU_RET_NOTHING: + break; + case DFU_RET_ZLP: + USBD_Write(0, 0, 0, 0, 0); + break; + case DFU_RET_STALL: + USBD_Stall(0); + break; + } +} + +void DFURT_SwitchToDFU(void) +{ + unsigned int *dfu_except_tbl = (unsigned int *)IFLASH_ADDR; + void (*toDFU)(void) = (void *)dfu_except_tbl[1]; + + *(unsigned int *)USB_DFU_MAGIC_ADDR = USB_DFU_MAGIC; + + USBD_Disconnect(); + __disable_irq(); + + toDFU(); +} diff --git a/firmware/include_board/board_common.h b/firmware/include_board/board_common.h index 6a46d67..9943ae1 100644 --- a/firmware/include_board/board_common.h +++ b/firmware/include_board/board_common.h @@ -107,6 +107,14 @@ #define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP //#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_RWAKEUP +#define BOARD_USB_VENDOR SIMTRACE_VENDOR_ID +#define BOARD_USB_PRODUCT SIMTRACE_PRODUCT_ID +#define BOARD_USB_RELEASE 0 + +#define BOARD_USB_DFU +#define BOARD_DFU_BOOT_SIZE (16 * 1024) +#define BOARD_DFU_PAGE_SIZE 512 +#define BOARD_DFU_NUM_IF 2 extern void board_exec_dbg_cmd(int ch); extern void board_main_top(void); diff --git a/firmware/src_board/board_cstartup_gnu.c b/firmware/src_board/board_cstartup_gnu.c index 3647d5e..4255646 100644 --- a/firmware/src_board/board_cstartup_gnu.c +++ b/firmware/src_board/board_cstartup_gnu.c @@ -125,6 +125,19 @@ IntFunc exception_table[] = { IrqHandlerNotUsed /* 35 not used */
};
+#if defined (BOARD_USB_DFU) && !defined(dfu)
+static void BootIntoApp(void)
+{
+ unsigned int *pSrc;
+ void (*appReset)(void);
+
+ pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE);
+ SCB->VTOR = ((unsigned int)(pSrc)) | (0x0 << 7);
+ appReset = pSrc[1];
+ appReset();
+}
+#endif
+
/**
* \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine.
@@ -136,6 +149,11 @@ void ResetException( void ) /* Low level Initialize */
LowLevelInit() ;
+#if defined (BOARD_USB_DFU) && !defined(dfu)
+ if (*(unsigned long *)IRAM_ADDR != 0xDFDFDFDF)
+ BootIntoApp();
+#endif
+
/* Initialize the relocate segment */
pSrc = &_etext ;
pDest = &_srelocate ;
@@ -169,6 +187,9 @@ void ResetException( void ) /* Branch to main function */
main() ;
+ /* App should have disabled interrupts during the transition */
+ __enable_irq();
+
/* Infinite loop */
while ( 1 ) ;
}
diff --git a/firmware/src_sam3s/USBD_HAL.c b/firmware/src_sam3s/USBD_HAL.c index 8a2645b..7776004 100644 --- a/firmware/src_sam3s/USBD_HAL.c +++ b/firmware/src_sam3s/USBD_HAL.c @@ -52,6 +52,7 @@ #include "chip.h"
#include "USBD_HAL.h"
+#include <usb/device/dfu/dfu.h>
#include <stdbool.h>
#include <stdint.h>
@@ -1161,6 +1162,12 @@ void USBD_IrqHandler(void) else if ((status & UDP_ISR_ENDBUSRES) != 0) {
TRACE_INFO_WP("EoBRes ");
+
+#if defined(BOARD_USB_DFU) && defined(dfu)
+ if (g_dfu.past_manifest)
+ USBDFU_SwitchToApp();
+#endif
+
/* Flush and enable the Suspend interrupt */
UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP;
UDP->UDP_IER = UDP_IER_RXSUSP;
diff --git a/firmware/src_simtrace/usb.c b/firmware/src_simtrace/usb.c index f24ee05..66f1de8 100644 --- a/firmware/src_simtrace/usb.c +++ b/firmware/src_simtrace/usb.c @@ -36,6 +36,8 @@ #include "utils.h" #include <cciddriverdescriptors.h> +#include <usb/common/dfu/usb_dfu.h> +#include <usb/device/dfu/dfu.h> /*------------------------------------------------------------------------------ * USB String descriptors @@ -260,7 +262,7 @@ typedef struct _SIMTraceDriverConfigurationDescriptorSniffer { USBEndpointDescriptor sniffer_dataOut; USBEndpointDescriptor sniffer_dataIn; USBEndpointDescriptor sniffer_interruptIn; - + DFURT_IF_DESCRIPTOR_STRUCT; } __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorSniffer; static const SIMTraceDriverConfigurationDescriptorSniffer @@ -270,7 +272,7 @@ static const SIMTraceDriverConfigurationDescriptorSniffer .bLength = sizeof(USBConfigurationDescriptor), .bDescriptorType = USBGenericDescriptor_CONFIGURATION, .wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorSniffer), - .bNumInterfaces = 1, + .bNumInterfaces = 1+DFURT_NUM_IF, .bConfigurationValue = CFG_NUM_SNIFF, .iConfiguration = SNIFFER_CONF_STR, .bmAttributes = USBD_BMATTRIBUTES, @@ -326,7 +328,8 @@ static const SIMTraceDriverConfigurationDescriptorSniffer PHONE_INT), USBEndpointDescriptor_MAXINTERRUPTSIZE_FS), .bInterval = 0x10, - } + }, + DFURT_IF_DESCRIPTOR(1, 0), }; #endif /* HAVE_SNIFFER */ @@ -337,7 +340,7 @@ static const CCIDDriverConfigurationDescriptors configurationDescriptorCCID = { .bLength = sizeof(USBConfigurationDescriptor), .bDescriptorType = USBGenericDescriptor_CONFIGURATION, .wTotalLength = sizeof(CCIDDriverConfigurationDescriptors), - .bNumInterfaces = 1, + .bNumInterfaces = 1+DFURT_NUM_IF, .bConfigurationValue = CFG_NUM_CCID, .iConfiguration = CCID_CONF_STR, .bmAttributes = BOARD_USB_BMATTRIBUTES, @@ -424,6 +427,7 @@ static const CCIDDriverConfigurationDescriptors configurationDescriptorCCID = { USBEndpointDescriptor_MAXINTERRUPTSIZE_FS), .bInterval = 0x10, }, + DFURT_IF_DESCRIPTOR(1, 0), }; #endif /* HAVE_CCID */ @@ -442,6 +446,7 @@ typedef struct _SIMTraceDriverConfigurationDescriptorPhone { USBEndpointDescriptor usim2_dataIn; USBEndpointDescriptor usim2_interruptIn; #endif + DFURT_IF_DESCRIPTOR_STRUCT; } __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorPhone; static const SIMTraceDriverConfigurationDescriptorPhone @@ -452,9 +457,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone USBGenericDescriptor_CONFIGURATION, sizeof(SIMTraceDriverConfigurationDescriptorPhone), #ifdef CARDEMU_SECOND_UART - 2, + 2+DFURT_NUM_IF, #else - 1, /* There is one interface in this configuration */ + 1+DFURT_NUM_IF, /* There is one interface in this configuration */ #endif CFG_NUM_PHONE, /* configuration number */ PHONE_CONF_STR, /* string descriptor for this configuration */ @@ -553,6 +558,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone USBEndpointDescriptor_MAXINTERRUPTSIZE_FS), 0x10 }, + DFURT_IF_DESCRIPTOR(2, 0), +#else + DFURT_IF_DESCRIPTOR(1, 0), #endif }; #endif /* HAVE_CARDEM */ @@ -576,6 +584,8 @@ typedef struct _SIMTraceDriverConfigurationDescriptorMITM { USBEndpointDescriptor phone_dataIn; USBEndpointDescriptor phone_interruptIn; + DFURT_IF_DESCRIPTOR_STRUCT; + } __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorMITM; static const SIMTraceDriverConfigurationDescriptorMITM @@ -585,7 +595,7 @@ static const SIMTraceDriverConfigurationDescriptorMITM sizeof(USBConfigurationDescriptor), USBGenericDescriptor_CONFIGURATION, sizeof(SIMTraceDriverConfigurationDescriptorMITM), - 2, /* There are two interfaces in this configuration */ + 2+DFURT_NUM_IF, /* There are two interfaces in this configuration */ CFG_NUM_MITM, /* configuration number */ MITM_CONF_STR, /* string descriptor for this configuration */ USBD_BMATTRIBUTES, @@ -718,7 +728,8 @@ static const SIMTraceDriverConfigurationDescriptorMITM USBEndpointDescriptor_INTERRUPT, MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(PHONE_INT), USBEndpointDescriptor_MAXINTERRUPTSIZE_FS), - 0x10} + 0x10}, + DFURT_IF_DESCRIPTOR(2, 0), }; #endif /* HAVE_CARDEM */ @@ -810,3 +821,9 @@ void SIMtrace_USB_Initialize(void) NVIC_EnableIRQ(UDP_IRQn); } + +void USBDCallbacks_RequestReceived(const USBGenericRequest *request) +{ + /* FIXME: integration with CCID control point reqeusts */ + USBDFU_Runtime_RequestHandler(request); +} |