Просмотр исходного кода

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>
Sylvain Munaut 6 лет назад
Родитель
Сommit
ec4ecfa817
7 измененных файлов с 236 добавлено и 0 удалено
  1. 120 0
      src/class/dfu/dfu_rt_device.c
  2. 77 0
      src/class/dfu/dfu_rt_device.h
  3. 2 0
      src/common/tusb_types.h
  4. 14 0
      src/device/usbd.c
  5. 15 0
      src/device/usbd.h
  6. 4 0
      src/tusb.h
  7. 4 0
      src/tusb_option.h

+ 120 - 0
src/class/dfu/dfu_rt_device.c

@@ -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

+ 77 - 0
src/class/dfu/dfu_rt_device.h

@@ -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_ */

+ 2 - 0
src/common/tusb_types.h

@@ -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,

+ 14 - 0
src/device/usbd.c

@@ -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) };

+ 15 - 0
src/device/usbd.h

@@ -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
  }

+ 4 - 0
src/tusb.h

@@ -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
 
 

+ 4 - 0
src/tusb_option.h

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