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:
parent
e413c9efa3
commit
ec4ecfa817
|
@ -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
|
|
@ -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_ */
|
|
@ -86,6 +86,8 @@ typedef enum
|
||||||
TUSB_DESC_BOS = 0x0F,
|
TUSB_DESC_BOS = 0x0F,
|
||||||
TUSB_DESC_DEVICE_CAPABILITY = 0x10,
|
TUSB_DESC_DEVICE_CAPABILITY = 0x10,
|
||||||
|
|
||||||
|
TUSB_DESC_FUNCTIONAL = 0x21,
|
||||||
|
|
||||||
// Class Specific Descriptor
|
// Class Specific Descriptor
|
||||||
TUSB_DESC_CS_DEVICE = 0x21,
|
TUSB_DESC_CS_DEVICE = 0x21,
|
||||||
TUSB_DESC_CS_CONFIGURATION = 0x22,
|
TUSB_DESC_CS_CONFIGURATION = 0x22,
|
||||||
|
|
|
@ -167,6 +167,20 @@ static usbd_class_driver_t const usbd_class_drivers[] =
|
||||||
.sof = NULL
|
.sof = NULL
|
||||||
},
|
},
|
||||||
#endif
|
#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) };
|
enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) };
|
||||||
|
|
|
@ -304,6 +304,21 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
||||||
/* Endpoint In */\
|
/* Endpoint In */\
|
||||||
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,10 @@
|
||||||
#if CFG_TUD_USBTMC
|
#if CFG_TUD_USBTMC
|
||||||
#include "class/usbtmc/usbtmc_device.h"
|
#include "class/usbtmc/usbtmc_device.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_DFU_RT
|
||||||
|
#include "class/dfu/dfu_rt_device.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -188,6 +188,10 @@
|
||||||
#define CFG_TUD_USBTMC 0
|
#define CFG_TUD_USBTMC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CFG_TUD_DFU_RT
|
||||||
|
#define CFG_TUD_DFU_RT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// HOST OPTIONS
|
// HOST OPTIONS
|
||||||
|
|
Loading…
Reference in New Issue