Add support for DFU Runtime class for devices

This is really just a few descriptors and then answering to the
request from the host to reboot into DFU mode.

That latter part is delegated to the app since this is platform
specific.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2019-10-24 00:42:42 +02:00
parent e413c9efa3
commit ec4ecfa817
7 changed files with 236 additions and 0 deletions

View File

@ -0,0 +1,120 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Sylvain Munaut <tnt@246tNt.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include "tusb_option.h"
#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RT)
#include "dfu_rt_device.h"
#include "device/usbd_pvt.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef enum {
DFU_REQUEST_DETACH = 0,
DFU_REQUEST_DNLOAD = 1,
DFU_REQUEST_UPLOAD = 2,
DFU_REQUEST_GETSTATUS = 3,
DFU_REQUEST_CLRSTATUS = 4,
DFU_REQUEST_GETSTATE = 5,
DFU_REQUEST_ABORT = 6,
} dfu_requests_t;
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
void dfu_rtd_init(void)
{
}
void dfu_rtd_reset(uint8_t rhport)
{
(void) rhport;
}
bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
{
(void) rhport;
// Ensure this is DFU Runtime
TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS);
TU_ASSERT(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT);
uint8_t const * p_desc = tu_desc_next( itf_desc );
(*p_length) = sizeof(tusb_desc_interface_t);
if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) )
{
(*p_length) += p_desc[DESC_OFFSET_LEN];
p_desc = tu_desc_next(p_desc);
}
return true;
}
bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
{
(void) rhport;
//------------- Class Specific Request -------------//
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
return true;
}
bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request)
{
(void) rhport;
//------------- Class Specific Request -------------//
TU_ASSERT(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
TU_ASSERT(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
switch ( request->bRequest )
{
case DFU_REQUEST_DETACH:
tud_control_status(rhport, request);
tud_dfu_rt_reboot_to_dfu();
break;
default: return false; // stall unsupported request
}
return true;
}
bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
{
(void) rhport;
(void) ep_addr;
(void) result;
(void) xferred_bytes;
return true;
}
#endif

View File

@ -0,0 +1,77 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Sylvain Munaut <tnt@246tNt.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_DFU_RT_DEVICE_H_
#define _TUSB_DFU_RT_DEVICE_H_
#include "common/tusb_common.h"
#include "device/usbd.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// Common Definitions
//--------------------------------------------------------------------+
// DFU Protocol
typedef enum
{
DFU_PROTOCOL_RT = 1,
DFU_PROTOCOL_DFU = 2,
} dfu_protocol_type_t;
// DFU Descriptor Type
typedef enum
{
DFU_DESC_FUNCTIONAL = 0x21,
} dfu_descriptor_type_t;
//--------------------------------------------------------------------+
// Application Callback API (weak is optional)
//--------------------------------------------------------------------+
// Invoked when received new data
TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void);
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void dfu_rtd_init(void);
void dfu_rtd_reset(uint8_t rhport);
bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request);
bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request);
bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_DFU_RT_DEVICE_H_ */

View File

@ -86,6 +86,8 @@ typedef enum
TUSB_DESC_BOS = 0x0F,
TUSB_DESC_DEVICE_CAPABILITY = 0x10,
TUSB_DESC_FUNCTIONAL = 0x21,
// Class Specific Descriptor
TUSB_DESC_CS_DEVICE = 0x21,
TUSB_DESC_CS_CONFIGURATION = 0x22,

View File

@ -167,6 +167,20 @@ static usbd_class_driver_t const usbd_class_drivers[] =
.sof = NULL
},
#endif
#if CFG_TUD_DFU_RT
{
.class_code = TUD_DFU_APP_CLASS,
//.subclass_code = TUD_DFU_APP_SUBCLASS
.init = dfu_rtd_init,
.reset = dfu_rtd_reset,
.open = dfu_rtd_open,
.control_request = dfu_rtd_control_request,
.control_complete = dfu_rtd_control_complete,
.xfer_cb = dfu_rtd_xfer_cb,
.sof = NULL
},
#endif
};
enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) };

View File

@ -304,6 +304,21 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
/* Endpoint In */\
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
//------------- DFU Runtime -------------//
#define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC)
#define TUD_DFU_APP_SUBCLASS 0x01u
// Length of template descriptr: 18 bytes
#define TUD_DFU_RT_DESC_LEN (9 + 9)
// DFU runtime descriptor
// Interface number, string index, attributes, detach timeout, transfer size
#define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \
/* Interface */ \
9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \
/* Function */ \
9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101)
#ifdef __cplusplus
}

View File

@ -87,6 +87,10 @@
#if CFG_TUD_USBTMC
#include "class/usbtmc/usbtmc_device.h"
#endif
#if CFG_TUD_DFU_RT
#include "class/dfu/dfu_rt_device.h"
#endif
#endif

View File

@ -188,6 +188,10 @@
#define CFG_TUD_USBTMC 0
#endif
#ifndef CFG_TUD_DFU_RT
#define CFG_TUD_DFU_RT 0
#endif
//--------------------------------------------------------------------
// HOST OPTIONS