support DFU detach to switch from fw to bootloader
This makes flashing a bit more convenient, because pushing the button is not required. It can be disabled using make DISABLE_DFU_DETACH=1. Change-Id: I04d05054d1c0e3988b8eafd93c6524f4a0489cb7
This commit is contained in:
parent
e7b3aa9823
commit
922aba5463
|
@ -5,13 +5,18 @@
|
|||
|
||||
#include "usb_protocol.h"
|
||||
#include "usb_dfu.h"
|
||||
#if (DISABLE_DFU_DETACH != 0)
|
||||
#define BMATT 0
|
||||
#else
|
||||
#define BMATT USB_DFU_WILL_DETACH
|
||||
#endif
|
||||
|
||||
/* 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 = 5000, \
|
||||
.bmAttributes = BMATT, \
|
||||
.wDetachTimeOut = 0, \
|
||||
.wTransferSize = FLASH_PAGE_SIZE, \
|
||||
.bcdDFUVersion = 0x0100, \
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ EXTRA_LIBS=$(SYSTEM_PREFIX)/lib/libosmocore.a
|
|||
EXTRA_CFLAGS=-I$(SYSTEM_PREFIX)/include -I../../ccid_common
|
||||
CROSS_COMPILE= arm-none-eabi-
|
||||
|
||||
DISABLE_DFU_DETACH ?= 0
|
||||
|
||||
CFLAGS_CPU=-D__SAME54N19A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16
|
||||
CFLAGS=-x c -mthumb -DDEBUG -Os -ffunction-sections -fdata-sections -mlong-calls \
|
||||
-g3 -Wall -c -std=gnu99 $(CFLAGS_CPU) -DOCTSIMFWBUILD
|
||||
-g3 -Wall -c -std=gnu99 $(CFLAGS_CPU) -DOCTSIMFWBUILD -DDISABLE_DFU_DETACH=$(DISABLE_DFU_DETACH)
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
|
@ -75,6 +77,8 @@ INC_DIRS = \
|
|||
-I"../usb/class/ccid/device" \
|
||||
-I"../usb/class/cdc" \
|
||||
-I"../usb/class/cdc/device" \
|
||||
-I"../usb/class/dfu" \
|
||||
-I"../usb/class/dfu/device" \
|
||||
-I"../usb/device" \
|
||||
$(NULL)
|
||||
|
||||
|
@ -135,6 +139,7 @@ OBJS += \
|
|||
talloc.o \
|
||||
usb/class/ccid/device/ccid_df.o \
|
||||
usb/class/cdc/device/cdcdf_acm.o \
|
||||
usb/class/dfu/device/dfudf.o \
|
||||
usb/device/usbdc.o \
|
||||
usb/usb_protocol.o \
|
||||
usb_descriptors.o \
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Stack DFU Function Implementation.
|
||||
*
|
||||
* Copyright (c) 2018 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "dfudf.h"
|
||||
#include "usb_protocol_dfu.h"
|
||||
#include "dfudf_desc.h"
|
||||
|
||||
/** USB Device DFU Function Specific Data */
|
||||
struct dfudf_func_data {
|
||||
/** DFU Interface information */
|
||||
uint8_t func_iface;
|
||||
/** DFU Enable Flag */
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static struct usbdf_driver _dfudf;
|
||||
static struct dfudf_func_data _dfudf_funcd;
|
||||
|
||||
/** USB DFU functional descriptor (with DFU attributes) */
|
||||
static const uint8_t usb_dfu_func_desc_bytes[] = {DFUD_IFACE_DESCB};
|
||||
static const usb_dfu_func_desc_t* usb_dfu_func_desc = (usb_dfu_func_desc_t*)&usb_dfu_func_desc_bytes;
|
||||
|
||||
enum usb_dfu_state dfu_state = USB_DFU_STATE_APP_IDLE;
|
||||
enum usb_dfu_status dfu_status = USB_DFU_STATUS_OK;
|
||||
|
||||
uint8_t dfu_download_data[512];
|
||||
uint16_t dfu_download_length = 0;
|
||||
size_t dfu_download_offset = 0;
|
||||
bool dfu_manifestation_complete = false;
|
||||
|
||||
/**
|
||||
* \brief Enable DFU Function
|
||||
* \param[in] drv Pointer to USB device function driver
|
||||
* \param[in] desc Pointer to USB interface descriptor
|
||||
* \return Operation status.
|
||||
*/
|
||||
static int32_t dfudf_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
|
||||
{
|
||||
struct dfudf_func_data *func_data = (struct dfudf_func_data *)(drv->func_data);
|
||||
|
||||
usb_iface_desc_t ifc_desc;
|
||||
uint8_t * ifc;
|
||||
|
||||
ifc = desc->sod;
|
||||
if (NULL == ifc) {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
ifc_desc.bInterfaceNumber = ifc[2];
|
||||
ifc_desc.bInterfaceClass = ifc[5];
|
||||
|
||||
if (USB_DFU_CLASS == ifc_desc.bInterfaceClass) {
|
||||
if (func_data->func_iface == ifc_desc.bInterfaceNumber) { // Initialized
|
||||
return ERR_ALREADY_INITIALIZED;
|
||||
} else if (func_data->func_iface != 0xFF) { // Occupied
|
||||
return ERR_NO_RESOURCE;
|
||||
} else {
|
||||
func_data->func_iface = ifc_desc.bInterfaceNumber;
|
||||
}
|
||||
} else { // Not supported by this function driver
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
// there are no endpoint to install since DFU uses only the control endpoint
|
||||
|
||||
ifc = usb_find_desc(usb_desc_next(desc->sod), desc->eod, USB_DT_INTERFACE);
|
||||
|
||||
// Installed
|
||||
_dfudf_funcd.enabled = true;
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable DFU Function
|
||||
* \param[in] drv Pointer to USB device function driver
|
||||
* \param[in] desc Pointer to USB device descriptor
|
||||
* \return Operation status.
|
||||
*/
|
||||
static int32_t dfudf_disable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
|
||||
{
|
||||
struct dfudf_func_data *func_data = (struct dfudf_func_data *)(drv->func_data);
|
||||
|
||||
usb_iface_desc_t ifc_desc;
|
||||
|
||||
if (desc) {
|
||||
ifc_desc.bInterfaceClass = desc->sod[5];
|
||||
// Check interface
|
||||
if (ifc_desc.bInterfaceClass != USB_DFU_CLASS) {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
func_data->func_iface = 0xFF;
|
||||
|
||||
_dfudf_funcd.enabled = false;
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief DFU Control Function
|
||||
* \param[in] drv Pointer to USB device function driver
|
||||
* \param[in] ctrl USB device general function control type
|
||||
* \param[in] param Parameter pointer
|
||||
* \return Operation status.
|
||||
*/
|
||||
static int32_t dfudf_ctrl(struct usbdf_driver *drv, enum usbdf_control ctrl, void *param)
|
||||
{
|
||||
switch (ctrl) {
|
||||
case USBDF_ENABLE:
|
||||
return dfudf_enable(drv, (struct usbd_descriptors *)param);
|
||||
|
||||
case USBDF_DISABLE:
|
||||
return dfudf_disable(drv, (struct usbd_descriptors *)param);
|
||||
|
||||
case USBDF_GET_IFACE:
|
||||
return ERR_UNSUPPORTED_OP;
|
||||
|
||||
default:
|
||||
return ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process the DFU IN request
|
||||
* \param[in] ep Endpoint address.
|
||||
* \param[in] req Pointer to the request.
|
||||
* \param[in] stage Stage of the request.
|
||||
* \return Operation status.
|
||||
*/
|
||||
static int32_t dfudf_in_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
|
||||
{
|
||||
if (USB_DATA_STAGE == stage) { // the data stage is only for IN data, which we sent
|
||||
return ERR_NONE; // send the IN data
|
||||
}
|
||||
|
||||
int32_t to_return = ERR_NONE;
|
||||
uint8_t response[6]; // buffer for the response to this request
|
||||
switch (req->bRequest) {
|
||||
case USB_DFU_UPLOAD: // upload firmware from flash not supported
|
||||
dfu_state = USB_DFU_STATE_DFU_ERROR; // unsupported class request
|
||||
to_return = ERR_UNSUPPORTED_OP; // stall control pipe (don't reply to the request)
|
||||
break;
|
||||
case USB_DFU_GETSTATUS: // get status
|
||||
response[0] = dfu_status; // set status
|
||||
response[1] = 10; // set poll timeout (24 bits, in milliseconds) to small value for periodical poll
|
||||
response[2] = 0; // set poll timeout (24 bits, in milliseconds) to small value for periodical poll
|
||||
response[3] = 0; // set poll timeout (24 bits, in milliseconds) to small value for periodical poll
|
||||
response[4] = dfu_state; // set state
|
||||
response[5] = 0; // string not used
|
||||
to_return = usbdc_xfer(ep, response, 6, false); // send back status
|
||||
if (USB_DFU_STATE_DFU_DNLOAD_SYNC == dfu_state) { // download has not completed
|
||||
dfu_state = USB_DFU_STATE_DFU_DNBUSY; // switch to busy state
|
||||
} else if (USB_DFU_STATE_DFU_MANIFEST_SYNC == dfu_state) {
|
||||
if (!dfu_manifestation_complete) {
|
||||
dfu_state = USB_DFU_STATE_DFU_MANIFEST; // go to manifest mode
|
||||
} else if (usb_dfu_func_desc->bmAttributes & USB_DFU_ATTRIBUTES_MANIFEST_TOLERANT) {
|
||||
dfu_state = USB_DFU_STATE_DFU_IDLE; // go back to idle mode
|
||||
} else { // this should not happen (after manifestation the state should be dfuMANIFEST-WAIT-RESET if we are not manifest tolerant)
|
||||
dfu_state = USB_DFU_STATE_DFU_MANIFEST_WAIT_RESET; // wait for reset
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_DFU_GETSTATE: // get state
|
||||
response[0] = dfu_state; // return state
|
||||
to_return = usbdc_xfer(ep, response, 1, false); // send back state
|
||||
break;
|
||||
default: // all other DFU class IN request
|
||||
dfu_state = USB_DFU_STATE_DFU_ERROR; // unknown or unsupported class request
|
||||
to_return = ERR_INVALID_ARG; // stall control pipe (don't reply to the request)
|
||||
break;
|
||||
}
|
||||
|
||||
return to_return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process the DFU OUT request
|
||||
* \param[in] ep Endpoint address.
|
||||
* \param[in] req Pointer to the request.
|
||||
* \param[in] stage Stage of the request.
|
||||
* \return Operation status.
|
||||
*/
|
||||
static int32_t dfudf_out_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
|
||||
{
|
||||
int32_t to_return = ERR_NONE;
|
||||
switch (req->bRequest) {
|
||||
case USB_DFU_DETACH: // detach makes only sense in DFU run-time/application mode
|
||||
#if (DISABLE_DFU_DETACH != 0)
|
||||
dfu_state = USB_DFU_STATE_DFU_ERROR; // unsupported class request
|
||||
to_return = ERR_UNSUPPORTED_OP; // stall control pipe (don't reply to the request)
|
||||
#else
|
||||
to_return = usbdc_xfer(ep, NULL, 0, false);
|
||||
*(uint32_t*)HSRAM_ADDR = 0x44465521;
|
||||
__disable_irq();
|
||||
delay_us(10000);
|
||||
usbdc_detach();
|
||||
delay_us(100000);
|
||||
NVIC_SystemReset();
|
||||
#endif
|
||||
break;
|
||||
case USB_DFU_CLRSTATUS: // clear status
|
||||
if (USB_DFU_STATE_DFU_ERROR == dfu_state || USB_DFU_STATUS_OK != dfu_status) { // only clear in case there is an error
|
||||
dfu_status = USB_DFU_STATUS_OK; // clear error status
|
||||
dfu_state = USB_DFU_STATE_DFU_IDLE; // put back in idle state
|
||||
}
|
||||
to_return = usbdc_xfer(ep, NULL, 0, false); // send ACK
|
||||
break;
|
||||
case USB_DFU_ABORT: // abort current operation
|
||||
dfu_download_offset = 0; // reset download progress
|
||||
dfu_state = USB_DFU_STATE_DFU_IDLE; // put back in idle state (nothing else to do)
|
||||
to_return = usbdc_xfer(ep, NULL, 0, false); // send ACK
|
||||
break;
|
||||
default: // all other DFU class OUT request
|
||||
dfu_state = USB_DFU_STATE_DFU_ERROR; // unknown class request
|
||||
to_return = ERR_INVALID_ARG; // stall control pipe (don't reply to the request)
|
||||
break;
|
||||
}
|
||||
|
||||
return to_return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process the CDC class request
|
||||
* \param[in] ep Endpoint address.
|
||||
* \param[in] req Pointer to the request.
|
||||
* \param[in] stage Stage of the request.
|
||||
* \return Operation status.
|
||||
*/
|
||||
static int32_t dfudf_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
|
||||
{
|
||||
if (0x01 != ((req->bmRequestType >> 5) & 0x03)) { // class request
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if ((req->wIndex == _dfudf_funcd.func_iface)) {
|
||||
if (req->bmRequestType & USB_EP_DIR_IN) {
|
||||
return dfudf_in_req(ep, req, stage);
|
||||
} else {
|
||||
return dfudf_out_req(ep, req, stage);
|
||||
}
|
||||
} else {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
/** USB Device DFU Handler Struct */
|
||||
static struct usbdc_handler dfudf_req_h = {NULL, (FUNC_PTR)dfudf_req};
|
||||
|
||||
/**
|
||||
* \brief Initialize the USB DFU Function Driver
|
||||
*/
|
||||
int32_t dfudf_init(void)
|
||||
{
|
||||
if (usbdc_get_state() > USBD_S_POWER) {
|
||||
return ERR_DENIED;
|
||||
}
|
||||
|
||||
_dfudf.ctrl = dfudf_ctrl;
|
||||
_dfudf.func_data = &_dfudf_funcd;
|
||||
|
||||
usbdc_register_function(&_dfudf);
|
||||
usbdc_register_handler(USBDC_HDL_REQ, &dfudf_req_h);
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief De-initialize the USB DFU Function Driver
|
||||
*/
|
||||
void dfudf_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check whether DFU Function is enabled
|
||||
*/
|
||||
bool dfudf_is_enabled(void)
|
||||
{
|
||||
return _dfudf_funcd.enabled;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Stack DFU Function Definition.
|
||||
*
|
||||
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
* Copyright (c) 2018 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip
|
||||
* software and any derivatives exclusively with Microchip products.
|
||||
* It is your responsibility to comply with third party license terms applicable
|
||||
* to your use of third party software (including open source software) that
|
||||
* may accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
|
||||
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
|
||||
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
|
||||
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
|
||||
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
|
||||
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
|
||||
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
|
||||
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
|
||||
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*/
|
||||
|
||||
#ifndef USBDF_DFU_H_
|
||||
#define USBDF_DFU_H_
|
||||
|
||||
#include "usbdc.h"
|
||||
#include "usb_protocol_dfu.h"
|
||||
|
||||
/** Current DFU state */
|
||||
extern enum usb_dfu_state dfu_state;
|
||||
/**< Current DFU status */
|
||||
extern enum usb_dfu_status dfu_status;
|
||||
|
||||
/** Downloaded data to be programmed in flash
|
||||
*
|
||||
* 512 is the flash page size of the SAM D5x/E5x
|
||||
*/
|
||||
extern uint8_t dfu_download_data[512];
|
||||
/** Length of downloaded data in bytes */
|
||||
extern uint16_t dfu_download_length;
|
||||
/** Offset of where the downloaded data should be flashed in bytes */
|
||||
extern size_t dfu_download_offset;
|
||||
/** If manifestation (firmware flash and check) is complete */
|
||||
extern bool dfu_manifestation_complete;
|
||||
|
||||
/**
|
||||
* \brief Initialize the USB DFU Function Driver
|
||||
* \return Operation status.
|
||||
*/
|
||||
int32_t dfudf_init(void);
|
||||
|
||||
/**
|
||||
* \brief Deinitialize the USB DFU Function Driver
|
||||
* \return Operation status.
|
||||
*/
|
||||
void dfudf_deinit(void);
|
||||
|
||||
/**
|
||||
* \brief Check whether DFU Function is enabled
|
||||
* \return Operation status.
|
||||
* \return true DFU Function is enabled
|
||||
* \return false DFU Function is disabled
|
||||
*/
|
||||
bool dfudf_is_enabled(void);
|
||||
|
||||
#endif /* USBDF_DFU_H_ */
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Stack DFU Function Descriptor Setting.
|
||||
*
|
||||
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
* Copyright (c) 2018 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip
|
||||
* software and any derivatives exclusively with Microchip products.
|
||||
* It is your responsibility to comply with third party license terms applicable
|
||||
* to your use of third party software (including open source software) that
|
||||
* may accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
|
||||
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
|
||||
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
|
||||
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
|
||||
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
|
||||
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
|
||||
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
|
||||
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
|
||||
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*/
|
||||
|
||||
#ifndef USBDF_DFU_DESC_H_
|
||||
#define USBDF_DFU_DESC_H_
|
||||
|
||||
#include "usb_protocol.h"
|
||||
#include "usbd_config.h"
|
||||
#include "usb_protocol_dfu.h"
|
||||
|
||||
#define DFUD_DEV_DESC \
|
||||
USB_DEV_DESC_BYTES(CONF_USB_DFUD_BCDUSB, \
|
||||
CONF_USB_DFUD_BDEVICECLASS, \
|
||||
CONF_USB_DFUD_BDEVICESUBCLASS, \
|
||||
CONF_USB_DFUD_BDEVICEPROTOCOL, \
|
||||
CONF_USB_DFUD_BMAXPKSZ0, \
|
||||
CONF_USB_OPENMOKO_IDVENDOR, \
|
||||
CONF_USB_OSMOASF4DFU_IDPRODUCT, \
|
||||
CONF_USB_DFUD_BCDDEVICE, \
|
||||
CONF_USB_DFUD_IMANUFACT, \
|
||||
CONF_USB_DFUD_IPRODUCT, \
|
||||
CONF_USB_DFUD_ISERIALNUM, \
|
||||
CONF_USB_DFUD_BNUMCONFIG)
|
||||
|
||||
#define DFUD_DEV_QUAL_DESC \
|
||||
USB_DEV_QUAL_DESC_BYTES(CONF_USB_DFUD_BCDUSB, \
|
||||
CONF_USB_DFUD_BDEVICECLASS, \
|
||||
CONF_USB_DFUD_BDEVICESUBCLASS, \
|
||||
CONF_USB_DFUD_BMAXPKSZ0, \
|
||||
CONF_USB_DFUD_BNUMCONFIG)
|
||||
|
||||
#define DFUD_CFG_DESC \
|
||||
USB_CONFIG_DESC_BYTES(CONF_USB_DFUD_WTOTALLENGTH, \
|
||||
CONF_USB_DFUD_BNUMINTERFACES, \
|
||||
CONF_USB_DFUD_BCONFIGVAL, \
|
||||
CONF_USB_DFUD_ICONFIG, \
|
||||
CONF_USB_DFUD_BMATTRI, \
|
||||
CONF_USB_DFUD_BMAXPOWER)
|
||||
|
||||
#define DFUD_OTH_SPD_CFG_DESC \
|
||||
USB_OTH_SPD_CFG_DESC_BYTES(CONF_USB_DFUD_WTOTALLENGTH, \
|
||||
CONF_USB_DFUD_BNUMINTERFACES, \
|
||||
CONF_USB_DFUD_BCONFIGVAL, \
|
||||
CONF_USB_DFUD_ICONFIG, \
|
||||
CONF_USB_DFUD_BMATTRI, \
|
||||
CONF_USB_DFUD_BMAXPOWER)
|
||||
|
||||
#define DFUD_IFACE_DESCB USB_DFU_FUNC_DESC_BYTES(USB_DFU_ATTRIBUTES_CAN_DOWNLOAD | USB_DFU_ATTRIBUTES_WILL_DETACH, \
|
||||
0, /**< detaching makes only sense in run-time mode */ \
|
||||
512, /**< transfer size corresponds to page size for optimal flash writing */ \
|
||||
0x0110 /**< DFU specification version 1.1 used */ )
|
||||
|
||||
#define DFUD_IFACE_DESCES \
|
||||
USB_IFACE_DESC_BYTES(CONF_USB_DFUD_BIFCNUM, \
|
||||
CONF_USB_DFUD_BALTSET, \
|
||||
CONF_USB_DFUD_BNUMEP, \
|
||||
USB_DFU_CLASS, \
|
||||
USB_DFU_SUBCLASS, \
|
||||
USB_DFU_PROTOCOL_DFU, \
|
||||
CONF_USB_DFUD_IINTERFACE), \
|
||||
DFUD_IFACE_DESCB
|
||||
|
||||
#define DFUD_STR_DESCES \
|
||||
CONF_USB_DFUD_LANGID_DESC \
|
||||
CONF_USB_DFUD_IMANUFACT_STR_DESC \
|
||||
CONF_USB_DFUD_IPRODUCT_STR_DESC \
|
||||
CONF_USB_DFUD_ISERIALNUM_STR_DESC \
|
||||
CONF_USB_DFUD_ICONFIG_STR_DESC \
|
||||
CONF_USB_DFUD_IINTERFACE_STR_DESC
|
||||
|
||||
/** USB Device descriptors and configuration descriptors */
|
||||
#define DFUD_DESCES_LS_FS \
|
||||
DFUD_DEV_DESC, DFUD_CFG_DESC, DFUD_IFACE_DESCES, DFUD_STR_DESCES
|
||||
|
||||
#define DFUD_HS_DESCES_LS_FS \
|
||||
DFUD_DEV_DESC, DFUD_DEV_QUAL_DESC, DFUD_CFG_DESC, DFUD_M_IFACE_DESCES, \
|
||||
DFUD_IFACE_DESCES, DFUD_OTH_SPD_CFG_DESC, \
|
||||
DFUD_IFACE_DESCES_HS, DFUD_STR_DESCES
|
||||
|
||||
#define DFUD_HS_DESCES_HS \
|
||||
DFUD_CFG_DESC, DFUD_IFACE_DESCES, DFUD_IFACE_DESCES_HS, DFUD_OTH_SPD_CFG_DESC, \
|
||||
DFUD_IFACE_DESCES
|
||||
|
||||
#endif /* USBDF_DFU_DESC_H_ */
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Firmware Upgrade (DFU) protocol definitions
|
||||
*
|
||||
* Copyright (c) 2018 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _USB_PROTOCOL_DFU_H_
|
||||
#define _USB_PROTOCOL_DFU_H_
|
||||
|
||||
#include "usb_includes.h"
|
||||
|
||||
/*
|
||||
* \ingroup usb_protocol_group
|
||||
* \defgroup dfu_protocol_group Device Firmware Upgrade Definitions
|
||||
* \implements USB Device Firmware Upgrade Specification, Revision 1.1
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \name USB DFU Subclass IDs
|
||||
*/
|
||||
//@{
|
||||
#define USB_DFU_CLASS 0xFE //!< Application Specific Class Code
|
||||
//@}
|
||||
|
||||
//! \name USB DFU Subclass IDs
|
||||
//@{
|
||||
#define USB_DFU_SUBCLASS 0x01 //!< Device Firmware Upgrade Code
|
||||
//@}
|
||||
|
||||
//! \name USB DFU Protocol IDs
|
||||
//@{
|
||||
#define USB_DFU_PROTOCOL_RUNTIME 0x01 //!< Runtime protocol
|
||||
#define USB_DFU_PROTOCOL_DFU 0x02 //!< DFU mode protocol
|
||||
//@}
|
||||
|
||||
//! \name USB DFU Attributes bits mask
|
||||
//@{
|
||||
#define USB_DFU_ATTRIBUTES_CAN_DOWNLOAD 0x01
|
||||
#define USB_DFU_ATTRIBUTES_CAN_UPLOAD 0x02
|
||||
#define USB_DFU_ATTRIBUTES_MANIFEST_TOLERANT 0x04
|
||||
#define USB_DFU_ATTRIBUTES_WILL_DETACH 0x08
|
||||
//@}
|
||||
|
||||
//! \name USB DFU Request IDs
|
||||
//@{
|
||||
#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
|
||||
//@}
|
||||
|
||||
/*
|
||||
* Need to pack structures tightly, or the compiler might insert padding
|
||||
* and violate the spec-mandated layout.
|
||||
*/
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
//! \name USB DFU Descriptors
|
||||
//@{
|
||||
|
||||
//! DFU Functional Descriptor
|
||||
typedef struct usb_dfu_func_desc {
|
||||
uint8_t bFunctionLength; /**< Size of this descriptor, in bytes (always 9) */
|
||||
uint8_t bDescriptorType; /**< DFU FUNCTIONAL descriptor type (always 0x21) */
|
||||
uint8_t bmAttributes; /**< DFU attributes bit mask */
|
||||
le16_t wDetachTimeOut; /**< Time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request */
|
||||
le16_t wTransferSize; /**< Maximum number of bytes that the device can accept per control-write transaction */
|
||||
le16_t bcdDFUVersion; /**< Numeric expression identifying the version of the DFU Specification release */
|
||||
} usb_dfu_func_desc_t;
|
||||
|
||||
#define USB_DFU_FUNC_DESC_LEN 9
|
||||
#define USB_DFU_FUNC_DESC_TYPE 0x21
|
||||
#define USB_DFU_FUNC_DESC_BYTES(bmAttributes, wDetachTimeOut, wTransferSize, bcdDFUVersion) \
|
||||
USB_DFU_FUNC_DESC_LEN, /* bFunctionLength */ \
|
||||
USB_DFU_FUNC_DESC_TYPE, /* bDescriptorType */ \
|
||||
bmAttributes, \
|
||||
LE_BYTE0(wDetachTimeOut), LE_BYTE1(wDetachTimeOut), \
|
||||
LE_BYTE0(wTransferSize), LE_BYTE1(wTransferSize), \
|
||||
LE_BYTE0(bcdDFUVersion), LE_BYTE1(bcdDFUVersion)
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
//! @}
|
||||
|
||||
//! USB DFU Request IDs
|
||||
enum usb_dfu_req {
|
||||
USB_DFU_DETACH,
|
||||
USB_DFU_DNLOAD,
|
||||
USB_DFU_UPLOAD,
|
||||
USB_DFU_GETSTATUS,
|
||||
USB_DFU_CLRSTATUS,
|
||||
USB_DFU_GETSTATE,
|
||||
USB_DFU_ABORT,
|
||||
};
|
||||
|
||||
//! USB DFU Device Status IDs
|
||||
enum usb_dfu_status {
|
||||
USB_DFU_STATUS_OK,
|
||||
USB_DFU_STATUS_ERR_TARGET,
|
||||
USB_DFU_STATUS_ERR_FILE,
|
||||
USB_DFU_STATUS_ERR_WRITE,
|
||||
USB_DFU_STATUS_ERR_ERASE,
|
||||
USB_DFU_STATUS_ERR_CHECK_ERASED,
|
||||
USB_DFU_STATUS_ERR_PROG,
|
||||
USB_DFU_STATUS_ERR_VERIFY,
|
||||
USB_DFU_STATUS_ERR_ADDRESS,
|
||||
USB_DFU_STATUS_ERR_NOTDONE,
|
||||
USB_DFU_STATUS_ERR_FIRMWARE,
|
||||
USB_DFU_STATUS_ERR_VENDOR,
|
||||
USB_DFU_STATUS_ERR_USBR,
|
||||
USB_DFU_STATUS_ERR_POR,
|
||||
USB_DFU_STATUS_ERR_UNKNOWN,
|
||||
USB_DFU_STATUS_ERR_STALLEDPKT,
|
||||
};
|
||||
|
||||
//! USB DFU Device State IDs
|
||||
enum usb_dfu_state {
|
||||
USB_DFU_STATE_APP_IDLE,
|
||||
USB_DFU_STATE_APP_DETACH,
|
||||
USB_DFU_STATE_DFU_IDLE,
|
||||
USB_DFU_STATE_DFU_DNLOAD_SYNC,
|
||||
USB_DFU_STATE_DFU_DNBUSY,
|
||||
USB_DFU_STATE_DFU_DNLOAD_IDLE,
|
||||
USB_DFU_STATE_DFU_MANIFEST_SYNC,
|
||||
USB_DFU_STATE_DFU_MANIFEST,
|
||||
USB_DFU_STATE_DFU_MANIFEST_WAIT_RESET,
|
||||
USB_DFU_STATE_DFU_UPLOAD_IDLE,
|
||||
USB_DFU_STATE_DFU_ERROR,
|
||||
};
|
||||
|
||||
#endif // _USB_PROTOCOL_DFU_H_
|
|
@ -132,6 +132,8 @@ void cdc_device_acm_init(void)
|
|||
/* usbdc_register_funcion inside */
|
||||
cdcdf_acm_init();
|
||||
|
||||
dfudf_init();
|
||||
|
||||
printf("usb_descs_size=%u\r\n", usb_descs[0].eod - usb_descs[0].sod);
|
||||
usbdc_start((struct usbd_descriptors *) usb_descs);
|
||||
usbdc_attach();
|
||||
|
|
|
@ -15,6 +15,8 @@ extern "C" {
|
|||
#include "cdcdf_acm.h"
|
||||
#include "cdcdf_acm_desc.h"
|
||||
#include "ccid_df.h"
|
||||
#include "dfudf.h"
|
||||
#include "dfudf_desc.h"
|
||||
|
||||
void usb_start(void);
|
||||
void cdc_device_acm_init(void);
|
||||
|
|
Loading…
Reference in New Issue