Hoernchen has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/17034 )
Change subject: support DFU detach to switch from fw to bootloader ...................................................................... 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 --- M sysmoOCTSIM/dfu_descriptors.h M sysmoOCTSIM/gcc/Makefile A sysmoOCTSIM/usb/class/dfu/device/dfudf.c A sysmoOCTSIM/usb/class/dfu/device/dfudf.h A sysmoOCTSIM/usb/class/dfu/device/dfudf_desc.h A sysmoOCTSIM/usb/class/dfu/usb_protocol_dfu.h M sysmoOCTSIM/usb_start.c M sysmoOCTSIM/usb_start.h 8 files changed, 658 insertions(+), 3 deletions(-) Approvals: Jenkins Builder: Verified laforge: Looks good to me, approved diff --git a/sysmoOCTSIM/dfu_descriptors.h b/sysmoOCTSIM/dfu_descriptors.h index 8cbaf23..7ef8cc9 100644 --- a/sysmoOCTSIM/dfu_descriptors.h +++ b/sysmoOCTSIM/dfu_descriptors.h @@ -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, \ } diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile index 6c0974f..9df0c01 100644 --- a/sysmoOCTSIM/gcc/Makefile +++ b/sysmoOCTSIM/gcc/Makefile @@ -7,9 +7,11 @@ 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 @@ -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 @@ 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 \ diff --git a/sysmoOCTSIM/usb/class/dfu/device/dfudf.c b/sysmoOCTSIM/usb/class/dfu/device/dfudf.c new file mode 100644 index 0000000..2b11fb4 --- /dev/null +++ b/sysmoOCTSIM/usb/class/dfu/device/dfudf.c @@ -0,0 +1,300 @@ +/** + * \file + * + * \brief USB Device Stack DFU Function Implementation. + * + * Copyright (c) 2018 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kre...@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; +} diff --git a/sysmoOCTSIM/usb/class/dfu/device/dfudf.h b/sysmoOCTSIM/usb/class/dfu/device/dfudf.h new file mode 100644 index 0000000..cee5845 --- /dev/null +++ b/sysmoOCTSIM/usb/class/dfu/device/dfudf.h @@ -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 <kre...@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_ */ diff --git a/sysmoOCTSIM/usb/class/dfu/device/dfudf_desc.h b/sysmoOCTSIM/usb/class/dfu/device/dfudf_desc.h new file mode 100644 index 0000000..50a79e4 --- /dev/null +++ b/sysmoOCTSIM/usb/class/dfu/device/dfudf_desc.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 <kre...@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_ */ diff --git a/sysmoOCTSIM/usb/class/dfu/usb_protocol_dfu.h b/sysmoOCTSIM/usb/class/dfu/usb_protocol_dfu.h new file mode 100644 index 0000000..7f82743 --- /dev/null +++ b/sysmoOCTSIM/usb/class/dfu/usb_protocol_dfu.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 <kre...@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_ diff --git a/sysmoOCTSIM/usb_start.c b/sysmoOCTSIM/usb_start.c index 08201cb..b87e79e 100644 --- a/sysmoOCTSIM/usb_start.c +++ b/sysmoOCTSIM/usb_start.c @@ -132,6 +132,8 @@ /* 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(); diff --git a/sysmoOCTSIM/usb_start.h b/sysmoOCTSIM/usb_start.h index a99d1ad..089c58d 100644 --- a/sysmoOCTSIM/usb_start.h +++ b/sysmoOCTSIM/usb_start.h @@ -15,6 +15,8 @@ #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); -- To view, visit https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/17034 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-ccid-firmware Gerrit-Branch: master Gerrit-Change-Id: I04d05054d1c0e3988b8eafd93c6524f4a0489cb7 Gerrit-Change-Number: 17034 Gerrit-PatchSet: 5 Gerrit-Owner: Hoernchen <ew...@sysmocom.de> Gerrit-Reviewer: Hoernchen <ew...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-MessageType: merged