summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan Conrad <[email protected]>2019-10-31 12:23:54 -0400
committerNathan Conrad <[email protected]>2019-10-31 12:23:54 -0400
commitd35f86993fc1292c7981bf66bca2d3cae40766e3 (patch)
tree4dd77aafc3c60c7a9a8c428986589f267f1b34c2 /src
parentcef388b7bd956adbc6af4904d4d95ca4120ebb7b (diff)
parent4d329d46cc36a8df05580ea7b19f2ce7a8dc2bf7 (diff)
Merge remote-tracking branch 'origin/master' into ZLP_Request2
Diffstat (limited to 'src')
-rw-r--r--src/class/dfu/dfu_rt_device.c120
-rw-r--r--src/class/dfu/dfu_rt_device.h77
-rw-r--r--src/common/tusb_common.h44
-rw-r--r--src/common/tusb_compiler.h7
-rw-r--r--src/common/tusb_types.h2
-rw-r--r--src/common/tusb_verify.h51
-rw-r--r--src/device/dcd.h58
-rw-r--r--src/device/usbd.c168
-rw-r--r--src/device/usbd.h18
-rw-r--r--src/device/usbd_pvt.h2
-rw-r--r--src/osal/osal.h3
-rw-r--r--src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c38
-rw-r--r--src/portable/sony/cxd56/dcd_cxd56.c330
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c17
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h4
-rw-r--r--src/tusb.c78
-rw-r--r--src/tusb.h4
-rw-r--r--src/tusb_option.h9
18 files changed, 900 insertions, 130 deletions
diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c
new file mode 100644
index 000000000..59adae7ef
--- /dev/null
+++ b/src/class/dfu/dfu_rt_device.c
@@ -0,0 +1,120 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Sylvain Munaut <[email protected]>
+ *
+ * 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
diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h
new file mode 100644
index 000000000..4348a0f3a
--- /dev/null
+++ b/src/class/dfu/dfu_rt_device.h
@@ -0,0 +1,77 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Sylvain Munaut <[email protected]>
+ *
+ * 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_ */
diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h
index 57c6e2fcf..59e1fe7fd 100644
--- a/src/common/tusb_common.h
+++ b/src/common/tusb_common.h
@@ -35,7 +35,7 @@
extern "C" {
#endif
- //--------------------------------------------------------------------+
+//--------------------------------------------------------------------+
// Macros Helper
//--------------------------------------------------------------------+
#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) )
@@ -58,7 +58,7 @@
#define TU_BIT(n) (1U << (n))
//--------------------------------------------------------------------+
-// INCLUDES
+// Includes
//--------------------------------------------------------------------+
// Standard Headers
@@ -77,7 +77,7 @@
#include "tusb_types.h"
//--------------------------------------------------------------------+
-// INLINE FUNCTION
+// Inline Functions
//--------------------------------------------------------------------+
#define tu_memclr(buffer, size) memset((buffer), 0, (size))
#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var)))
@@ -203,6 +203,44 @@ static inline bool tu_bit_test (uint32_t value, uint8_t n) { return (value &
+ TU_BIN8(dlsb))
#endif
+//--------------------------------------------------------------------+
+// Debug Function
+//--------------------------------------------------------------------+
+
+// CFG_TUSB_DEBUG for debugging
+// 0 : no debug
+// 1 : print when there is error
+// 2 : print out log
+#if CFG_TUSB_DEBUG
+
+void tu_print_mem(void const *buf, uint8_t size, uint16_t count);
+
+#ifndef tu_printf
+ #define tu_printf printf
+#endif
+
+// Log with debug level 1
+#define TU_LOG1 tu_printf
+#define TU_LOG1_MEM tu_print_mem
+
+// Log with debug level 2
+#if CFG_TUSB_DEBUG > 1
+ #define TU_LOG2 TU_LOG1
+ #define TU_LOG2_MEM TU_LOG1_MEM
+#endif
+
+#endif // CFG_TUSB_DEBUG
+
+#ifndef TU_LOG1
+ #define TU_LOG1(...)
+ #define TU_LOG1_MEM(...)
+#endif
+
+#ifndef TU_LOG2
+ #define TU_LOG2(...)
+ #define TU_LOG2_MEM(...)
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h
index 58732b871..0bac3eae7 100644
--- a/src/common/tusb_compiler.h
+++ b/src/common/tusb_compiler.h
@@ -67,6 +67,7 @@
#define TU_ATTR_WEAK __attribute__ ((weak))
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
+ #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used
// Endian conversion use well-known host to network (big endian) naming
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
@@ -75,8 +76,8 @@
#define TU_BYTE_ORDER TU_BIG_ENDIAN
#endif
-#define TU_BSWAP16(u16) (__builtin_bswap16(u16))
-#define TU_BSWAP32(u32) (__builtin_bswap32(u32))
+ #define TU_BSWAP16(u16) (__builtin_bswap16(u16))
+ #define TU_BSWAP32(u32) (__builtin_bswap32(u32))
#elif defined(__TI_COMPILER_VERSION__)
#define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
@@ -86,6 +87,7 @@
#define TU_ATTR_WEAK __attribute__ ((weak))
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
+ #define TU_ATTR_USED __attribute__ ((used))
// __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian)
#if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__)
@@ -123,7 +125,6 @@
#define tu_htonl(u32) (u32)
#define tu_ntohl(u32) (u32)
-
#define tu_htole16(u16) (tu_bswap16(u16))
#define tu_le16toh(u16) (tu_bswap16(u16))
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index ad42baad7..737b17f76 100644
--- a/src/common/tusb_types.h
+++ b/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,
diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h
index fae0c88ae..e59481352 100644
--- a/src/common/tusb_verify.h
+++ b/src/common/tusb_verify.h
@@ -107,20 +107,6 @@
if ( !(_cond) ) { _handler; return _ret; } \
} while(0)
-/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/
-#define TU_VERIFY_ERR_DEF2(_error, _handler) do \
-{ \
- uint32_t _err = (uint32_t)(_error); \
- if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; } \
-} while(0)
-
-#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) do \
-{ \
- uint32_t _err = (uint32_t)(_error); \
- if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; } \
-} while(0)
-
-
/*------------------------------------------------------------------*/
/* TU_VERIFY
* - TU_VERIFY_1ARGS : return false if failed
@@ -142,28 +128,6 @@
#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__)
-
-/*------------------------------------------------------------------*/
-/* TU_VERIFY STATUS
- * - TU_VERIFY_ERR_1ARGS : return status of condition if failed
- * - TU_VERIFY_ERR_2ARGS : return provided status code if failed
- *------------------------------------------------------------------*/
-#define TU_VERIFY_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, )
-#define TU_VERIFY_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, ,_ret)
-
-#define TU_VERIFY_ERR(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_ERR_2ARGS, TU_VERIFY_ERR_1ARGS,UNUSED)(__VA_ARGS__)
-
-/*------------------------------------------------------------------*/
-/* TU_VERIFY STATUS WITH HANDLER
- * - TU_VERIFY_ERR_HDLR_2ARGS : execute handler, return status if failed
- * - TU_VERIFY_ERR_HDLR_3ARGS : execute handler, return provided error if failed
- *------------------------------------------------------------------*/
-#define TU_VERIFY_ERR_HDLR_2ARGS(_error, _handler) TU_VERIFY_ERR_DEF2(_error, _handler)
-#define TU_VERIFY_ERR_HDLR_3ARGS(_error, _handler, _ret) TU_VERIFY_ERR_DEF3(_error, _handler, _ret)
-
-#define TU_VERIFY_ERR_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_ERR_HDLR_3ARGS, TU_VERIFY_ERR_HDLR_2ARGS,UNUSED)(__VA_ARGS__)
-
-
/*------------------------------------------------------------------*/
/* ASSERT
* basically TU_VERIFY with TU_BREAKPOINT() as handler
@@ -175,6 +139,21 @@
#define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__)
+// TODO remove TU_ASSERT_ERR() later
+
+/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/
+#define TU_VERIFY_ERR_DEF2(_error, _handler) do \
+{ \
+ uint32_t _err = (uint32_t)(_error); \
+ if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; } \
+} while(0)
+
+#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) do \
+{ \
+ uint32_t _err = (uint32_t)(_error); \
+ if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; } \
+} while(0)
+
/*------------------------------------------------------------------*/
/* ASSERT Error
* basically TU_VERIFY Error with TU_BREAKPOINT() as handler
diff --git a/src/device/dcd.h b/src/device/dcd.h
index 168eb181c..9fa98c669 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -39,17 +39,20 @@
typedef enum
{
- DCD_EVENT_BUS_RESET = 1,
+ DCD_EVENT_INVALID = 0,
+ DCD_EVENT_BUS_RESET,
DCD_EVENT_UNPLUGGED,
DCD_EVENT_SOF,
- DCD_EVENT_SUSPEND,
+ DCD_EVENT_SUSPEND, // TODO LPM Sleep L1 support
DCD_EVENT_RESUME,
DCD_EVENT_SETUP_RECEIVED,
DCD_EVENT_XFER_COMPLETE,
// Not an DCD event, just a convenient way to defer ISR function
- USBD_EVENT_FUNC_CALL
+ USBD_EVENT_FUNC_CALL,
+
+ DCD_EVENT_COUNT
} dcd_eventid_t;
typedef struct TU_ATTR_ALIGNED(4)
@@ -76,7 +79,7 @@ typedef struct TU_ATTR_ALIGNED(4)
};
} dcd_event_t;
-TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
+//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
/*------------------------------------------------------------------*/
/* Device API
@@ -116,20 +119,51 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);
// clear stall, data toggle is also reset to DATA0
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);
-/*------------------------------------------------------------------*/
-/* Event Function
- * Called by DCD to notify device stack
- *------------------------------------------------------------------*/
-void dcd_event_handler(dcd_event_t const * event, bool in_isr);
+//--------------------------------------------------------------------+
+// Event API
+//--------------------------------------------------------------------+
+
+// Called by DCD to notify device stack
+extern void dcd_event_handler(dcd_event_t const * event, bool in_isr);
// helper to send bus signal event
-void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr);
+static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr);
// helper to send setup received
-void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr);
+static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr);
// helper to send transfer complete event
-void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr);
+static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr);
+
+
+//--------------------------------------------------------------------+
+// Inline helper
+//--------------------------------------------------------------------+
+
+static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
+{
+ dcd_event_t event = { .rhport = rhport, .event_id = eid, };
+ dcd_event_handler(&event, in_isr);
+}
+
+static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr)
+{
+ dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED };
+ memcpy(&event.setup_received, setup, 8);
+
+ dcd_event_handler(&event, in_isr);
+}
+
+static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
+{
+ dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE };
+
+ event.xfer_complete.ep_addr = ep_addr;
+ event.xfer_complete.len = xferred_bytes;
+ event.xfer_complete.result = result;
+
+ dcd_event_handler(&event, in_isr);
+}
#ifdef __cplusplus
}
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 14e56a9b7..46affdab4 100644
--- a/src/device/usbd.c
+++ b/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) };
@@ -192,6 +206,66 @@ void usbd_control_reset (uint8_t rhport);
bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) );
+
+//--------------------------------------------------------------------+
+// Debugging
+//--------------------------------------------------------------------+
+#if CFG_TUSB_DEBUG > 1
+static char const* const _usbd_event_str[DCD_EVENT_COUNT] =
+{
+ "INVALID" ,
+ "BUS_RESET" ,
+ "UNPLUGGED" ,
+ "SOF" ,
+ "SUSPEND" ,
+ "RESUME" ,
+ "SETUP_RECEIVED" ,
+ "XFER_COMPLETE" ,
+ "FUNC_CALL"
+};
+
+// must be same driver order as usbd_class_drivers[]
+static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] =
+{
+ #if CFG_TUD_CDC
+ "CDC",
+ #endif
+ #if CFG_TUD_MSC
+ "MSC",
+ #endif
+ #if CFG_TUD_HID
+ "HID",
+ #endif
+ #if CFG_TUD_MIDI
+ "MIDI",
+ #endif
+ #if CFG_TUD_VENDOR
+ "Vendor",
+ #endif
+ #if CFG_TUD_USBTMC
+ "USBTMC"
+ #endif
+};
+
+static char const* const _tusb_std_request_str[] =
+{
+ "Get Status" ,
+ "Clear Feature" ,
+ "Reserved" ,
+ "Set Feature" ,
+ "Reserved" ,
+ "Set Address" ,
+ "Get Descriptor" ,
+ "Set Descriptor" ,
+ "Get Configuration" ,
+ "Set Configuration" ,
+ "Get Interface" ,
+ "Set Interface" ,
+ "Synch Frame"
+};
+
+#endif
+
//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+
@@ -216,8 +290,10 @@ bool tud_remote_wakeup(void)
//--------------------------------------------------------------------+
// USBD Task
//--------------------------------------------------------------------+
-bool usbd_init (void)
+bool tud_init (void)
{
+ TU_LOG2("USBD init\r\n");
+
tu_varclr(&_usbd_dev);
// Init device queue & task
@@ -225,7 +301,11 @@ bool usbd_init (void)
TU_ASSERT(_usbd_q != NULL);
// Init class drivers
- for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) usbd_class_drivers[i].init();
+ for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++)
+ {
+ TU_LOG2("%s init\r\n", _usbd_driver_str[i]);
+ usbd_class_drivers[i].init();
+ }
// Init device controller driver
dcd_init(TUD_OPT_RHPORT);
@@ -279,6 +359,8 @@ void tud_task (void)
if ( !osal_queue_receive(_usbd_q, &event) ) return;
+ TU_LOG2("USBD: event %s\r\n", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED");
+
switch ( event.event_id )
{
case DCD_EVENT_BUS_RESET:
@@ -293,6 +375,9 @@ void tud_task (void)
break;
case DCD_EVENT_SETUP_RECEIVED:
+ TU_LOG2(" ");
+ TU_LOG2_MEM(&event.setup_received, 1, 8);
+
// Mark as connected after receiving 1st setup packet.
// But it is easier to set it every time instead of wasting time to check then set
_usbd_dev.connected = 1;
@@ -307,29 +392,30 @@ void tud_task (void)
break;
case DCD_EVENT_XFER_COMPLETE:
- // Only handle xfer callback in ready state
- // if (_usbd_dev.connected && !_usbd_dev.suspended)
- {
- // Invoke the class callback associated with the endpoint address
- uint8_t const ep_addr = event.xfer_complete.ep_addr;
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const ep_dir = tu_edpt_dir(ep_addr);
+ {
+ // Invoke the class callback associated with the endpoint address
+ uint8_t const ep_addr = event.xfer_complete.ep_addr;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const ep_dir = tu_edpt_dir(ep_addr);
- _usbd_dev.ep_status[epnum][ep_dir].busy = false;
+ TU_LOG2(" Endpoint: 0x%02X, Bytes: %ld\r\n", ep_addr, event.xfer_complete.len);
- if ( 0 == epnum )
- {
- // control transfer DATA stage callback
- usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
- }
- else
- {
- uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir];
- TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
+ _usbd_dev.ep_status[epnum][ep_dir].busy = false;
- usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
- }
+ if ( 0 == epnum )
+ {
+ // control transfer DATA stage callback
+ usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ }
+ else
+ {
+ uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir];
+ TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
+
+ TU_LOG2(" %s xfer callback\r\n", _usbd_driver_str[drv_id]);
+ usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
}
+ }
break;
case DCD_EVENT_SUSPEND:
@@ -382,6 +468,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
return tud_vendor_control_request_cb(rhport, p_request);
}
+#if CFG_TUSB_DEBUG > 1
+ if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME)
+ {
+ TU_LOG2(" %s\r\n", _tusb_std_request_str[p_request->bRequest]);
+ }
+#endif
+
switch ( p_request->bmRequestType_bit.recipient )
{
//------------- Device Requests e.g in enumeration -------------//
@@ -494,6 +587,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// GET HID REPORT DESCRIPTOR falls into this case
// stall control endpoint if driver return false
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
+ TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]);
TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL &&
usbd_class_drivers[drvid].control_request(rhport, p_request));
break;
@@ -503,6 +597,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// forward to class driver: "non-STD request to Interface"
// stall control endpoint if driver return false
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
+ TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]);
TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL &&
usbd_class_drivers[drvid].control_request(rhport, p_request));
}
@@ -570,7 +665,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// For std-type requests: non-std request codes are already discarded.
// must not call tud_control_status(), and return value will have no effect
// class driver is invoked last, so that EP already has EP stall cleared (in event of clear feature EP halt)
-
+ TU_LOG2(" %s control request\r\n", _usbd_driver_str[drv_id]);
if ( usbd_class_drivers[drv_id].control_request &&
usbd_class_drivers[drv_id].control_request(rhport, p_request))
{
@@ -627,6 +722,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
uint16_t itf_len=0;
+ TU_LOG2(" %s open\r\n", _usbd_driver_str[drv_id]);
TU_ASSERT( usbd_class_drivers[drv_id].open(rhport, desc_itf, &itf_len) );
TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) );
@@ -788,34 +884,6 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
}
}
-// helper to send bus signal event
-void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
-{
- dcd_event_t event = { .rhport = rhport, .event_id = eid, };
- dcd_event_handler(&event, in_isr);
-}
-
-// helper to send setup received
-void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr)
-{
- dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED };
- memcpy(&event.setup_received, setup, 8);
-
- dcd_event_handler(&event, in_isr);
-}
-
-// helper to send transfer complete event
-void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
-{
- dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE };
-
- event.xfer_complete.ep_addr = ep_addr;
- event.xfer_complete.len = xferred_bytes;
- event.xfer_complete.result = result;
-
- dcd_event_handler(&event, in_isr);
-}
-
//--------------------------------------------------------------------+
// Helper
//--------------------------------------------------------------------+
diff --git a/src/device/usbd.h b/src/device/usbd.h
index f0887f0db..b3665d7f2 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -41,6 +41,9 @@
// Application API
//--------------------------------------------------------------------+
+// Init device stack
+bool tud_init (void);
+
// Task function should be called in main/rtos loop
void tud_task (void);
@@ -304,6 +307,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
}
diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h
index 892680142..b9947044b 100644
--- a/src/device/usbd_pvt.h
+++ b/src/device/usbd_pvt.h
@@ -33,8 +33,6 @@
extern "C" {
#endif
-bool usbd_init (void);
-
//--------------------------------------------------------------------+
// USBD Endpoint API
//--------------------------------------------------------------------+
diff --git a/src/osal/osal.h b/src/osal/osal.h
index ea655d4f1..6b1d668a4 100644
--- a/src/osal/osal.h
+++ b/src/osal/osal.h
@@ -86,9 +86,6 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b
#define STASK_RETURN(_error) return _error;
#define STASK_INVOKE(_subtask, _status) (_status) = _subtask
-
-// Sub Task Assert
-#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR(_err)
#define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED)
#endif
diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
index 160eefb24..5b2bd83e9 100644
--- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
+++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
@@ -28,9 +28,11 @@
/* Since 2012 starting with LPC11uxx, NXP start to use common USB Device Controller with code name LPC IP3511
* for almost their new MCUs. Currently supported and tested families are
- * - LPC11Uxx
- * - LPC13xx
- * - LPC51Uxx
+ * - LPC11U68, LPC11U37
+ * - LPC1347
+ * - LPC51U68
+ * - LPC54114
+ * - LPC55s69
*
* For similar controller of other families, this file may require some minimal changes to work with.
* Previous MCUs such as LPC17xx, LPC40xx, LPC18xx, LPC43xx have their own driver implementation.
@@ -38,20 +40,23 @@
#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_LPC11UXX || \
CFG_TUSB_MCU == OPT_MCU_LPC13XX || \
+ CFG_TUSB_MCU == OPT_MCU_LPC15XX || \
CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \
CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \
CFG_TUSB_MCU == OPT_MCU_LPC55XX)
-#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX
- // LPC11Uxx and LPC13xx use lpcopen
+#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || CFG_TUSB_MCU == OPT_MCU_LPC15XX
+ // LPC 11Uxx, 13xx, 15xx use lpcopen
#include "chip.h"
#define DCD_REGS LPC_USB
#define DCD_IRQHandler USB_IRQHandler
+
#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \
CFG_TUSB_MCU == OPT_MCU_LPC55XX // TODO 55xx has dual usb controllers
#include "fsl_device_registers.h"
#define DCD_REGS USB0
#define DCD_IRQHandler USB0_IRQHandler
+
#endif
#include "device/dcd.h"
@@ -61,6 +66,9 @@
//--------------------------------------------------------------------+
// Number of endpoints
+// - 11 13 15 51 54 has 5x2 endpoints
+// - 18/43 usb0 & 55s usb1 (HS) has 6x2 endpoints
+// - 18/43 usb1 & 55s usb0 (FS) has 4x2 endpoints
#define EP_COUNT 10
// only SRAM1 & USB RAM can be used for transfer.
@@ -166,7 +174,7 @@ void dcd_init(uint8_t rhport)
DCD_REGS->INTSTAT = DCD_REGS->INTSTAT; // clear all pending interrupt
DCD_REGS->INTEN = INT_DEVICE_STATUS_MASK;
DCD_REGS->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK |
- CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK;
+ CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK;
NVIC_ClearPendingIRQ(USB0_IRQn);
}
@@ -270,7 +278,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
prepare_ep_xfer(ep_id, get_buf_offset(buffer), total_bytes);
- return true;
+ return true;
}
//--------------------------------------------------------------------+
@@ -329,7 +337,7 @@ static void process_xfer_isr(uint32_t int_status)
void DCD_IRQHandler(void)
{
- uint32_t const dev_cmd_stat = DCD_REGS->DEVCMDSTAT;
+ uint32_t const cmd_stat = DCD_REGS->DEVCMDSTAT;
uint32_t int_status = DCD_REGS->INTSTAT & DCD_REGS->INTEN;
DCD_REGS->INTSTAT = int_status; // Acknowledge handled interrupt
@@ -340,16 +348,16 @@ void DCD_IRQHandler(void)
if ( int_status & INT_DEVICE_STATUS_MASK )
{
DCD_REGS->DEVCMDSTAT |= CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK;
- if ( dev_cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset
+ if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset
{
bus_reset();
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
}
- if (dev_cmd_stat & CMDSTAT_CONNECT_CHANGE_MASK)
+ if (cmd_stat & CMDSTAT_CONNECT_CHANGE_MASK)
{
// device disconnect
- if (dev_cmd_stat & CMDSTAT_DEVICE_ADDR_MASK)
+ if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK)
{
// debouncing as this can be set when device is powering
dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
@@ -357,12 +365,12 @@ void DCD_IRQHandler(void)
}
// TODO support suspend & resume
- if (dev_cmd_stat & CMDSTAT_SUSPEND_CHANGE_MASK)
+ if (cmd_stat & CMDSTAT_SUSPEND_CHANGE_MASK)
{
- if (dev_cmd_stat & CMDSTAT_DEVICE_SUSPEND_MASK)
+ if (cmd_stat & CMDSTAT_DEVICE_SUSPEND_MASK)
{ // suspend signal, bus idle for more than 3ms
// Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration.
- if (dev_cmd_stat & CMDSTAT_DEVICE_ADDR_MASK)
+ if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK)
{
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
}
@@ -376,7 +384,7 @@ void DCD_IRQHandler(void)
}
// Setup Receive
- if ( tu_bit_test(int_status, 0) && (dev_cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) )
+ if ( tu_bit_test(int_status, 0) && (cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) )
{
// Follow UM flowchart to clear Active & Stall on both Control IN/OUT endpoints
_dcd.ep[0][0].active = _dcd.ep[1][0].active = 0;
diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c
new file mode 100644
index 000000000..638b2f979
--- /dev/null
+++ b/src/portable/sony/cxd56/dcd_cxd56.c
@@ -0,0 +1,330 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright 2019 Sony Semiconductor Solutions Corporation
+ *
+ * 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_TUSB_MCU == OPT_MCU_CXD56
+
+#include <errno.h>
+#include <nuttx/usb/usbdev.h>
+#include <nuttx/arch.h>
+
+#include "device/dcd.h"
+
+#define CXD56_EPNUM (7)
+
+struct usbdcd_driver_s
+{
+ struct usbdevclass_driver_s usbdevclass_driver;
+ FAR struct usbdev_ep_s *ep[CXD56_EPNUM];
+ FAR struct usbdev_req_s *req[CXD56_EPNUM];
+};
+
+static struct usbdcd_driver_s usbdcd_driver;
+static struct usbdev_s *usbdev;
+
+static int dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+static void dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+static int dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev,
+ FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen);
+static void dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+static void dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+
+static const struct usbdevclass_driverops_s g_driverops =
+{
+ dcd_bind, /* bind */
+ dcd_unbind, /* unbind */
+ dcd_setup, /* setup */
+ dcd_disconnect, /* disconnect */
+ dcd_suspend, /* suspend */
+ dcd_resume, /* resume */
+};
+
+static void usbdcd_ep0incomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
+{
+ (void) ep;
+
+ uint8_t ep_addr = (uint32_t)req->priv;
+
+ if (req->result || req->xfrd != req->len)
+ {
+ if (req->len)
+ {
+ dcd_event_xfer_complete(0, ep_addr, req->xfrd, XFER_RESULT_SUCCESS, true);
+ }
+ }
+ else
+ {
+ if (req->xfrd)
+ {
+ dcd_event_xfer_complete(0, ep_addr, req->xfrd, XFER_RESULT_SUCCESS, true);
+ }
+ }
+}
+
+static int dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
+{
+ (void) driver;
+
+ usbdev = dev;
+ usbdcd_driver.ep[0] = dev->ep0;
+
+ usbdcd_driver.req[0] = EP_ALLOCREQ(usbdcd_driver.ep[0]);
+ if (usbdcd_driver.req[0] != NULL)
+ {
+ usbdcd_driver.req[0]->len = 64;
+ usbdcd_driver.req[0]->buf = EP_ALLOCBUFFER(usbdcd_driver.ep[0], 64);
+ if (!usbdcd_driver.req[0]->buf)
+ {
+ EP_FREEREQ(usbdcd_driver.ep[0], usbdcd_driver.req[0]);
+ usbdcd_driver.req[0] = NULL;
+ }
+ }
+
+ usbdcd_driver.req[0]->callback = usbdcd_ep0incomplete;
+
+ DEV_CONNECT(dev);
+ return 0;
+}
+
+static void dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
+{
+ (void) driver;
+ (void) dev;
+}
+
+static int dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev,
+ FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen)
+{
+ (void) driver;
+ (void) dev;
+ (void) dataout;
+ (void) outlen;
+
+ dcd_event_setup_received(0, (uint8_t *)ctrl, true);
+
+ return 0;
+}
+
+static void dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
+{
+ (void) driver;
+
+ dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
+ DEV_CONNECT(dev);
+}
+
+static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
+{
+ (void) driver;
+ (void) dev;
+
+ dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
+}
+
+static void dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
+{
+ (void) driver;
+ (void) dev;
+
+ dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
+}
+
+void dcd_init(uint8_t rhport)
+{
+ (void) rhport;
+
+ usbdcd_driver.usbdevclass_driver.speed = USB_SPEED_HIGH;
+ usbdcd_driver.usbdevclass_driver.ops = &g_driverops;
+
+ usbdev_register(&usbdcd_driver.usbdevclass_driver);
+}
+
+// Enable device interrupt
+void dcd_int_enable(uint8_t rhport)
+{
+ (void) rhport;
+
+ up_enable_irq(CXD56_IRQ_USB_INT);
+}
+
+// Disable device interrupt
+void dcd_int_disable(uint8_t rhport)
+{
+ (void) rhport;
+
+ up_disable_irq(CXD56_IRQ_USB_INT);
+}
+
+// Receive Set Address request, mcu port must also include status IN response
+void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
+{
+ (void) rhport;
+ (void) dev_addr;
+}
+
+// Receive Set Config request
+void dcd_set_config(uint8_t rhport, uint8_t config_num)
+{
+ (void) rhport;
+ (void) config_num;
+}
+
+void dcd_remote_wakeup(uint8_t rhport)
+{
+ (void) rhport;
+
+ DEV_WAKEUP(usbdev);
+}
+
+//--------------------------------------------------------------------+
+// Endpoint API
+//--------------------------------------------------------------------+
+
+bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
+{
+ (void) rhport;
+
+ uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
+ uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
+ uint8_t xfrtype = 0;
+ struct usb_epdesc_s epdesc;
+
+ if (epnum >= CXD56_EPNUM)
+ {
+ return false;
+ }
+
+ switch (p_endpoint_desc->bmAttributes.xfer)
+ {
+ case 1:
+ xfrtype = USB_EP_ATTR_XFER_ISOC;
+ break;
+ case 2:
+ xfrtype = USB_EP_ATTR_XFER_BULK;
+ break;
+ case 3:
+ xfrtype = USB_EP_ATTR_XFER_INT;
+ break;
+ }
+
+ usbdcd_driver.ep[epnum] = DEV_ALLOCEP(usbdev, epnum, dir == TUSB_DIR_IN, xfrtype);
+ if (usbdcd_driver.ep[epnum] == NULL)
+ {
+ return false;
+ }
+
+ usbdcd_driver.req[epnum] = NULL;
+ usbdcd_driver.req[epnum] = EP_ALLOCREQ(usbdcd_driver.ep[epnum]);
+ if (usbdcd_driver.req[epnum] != NULL)
+ {
+ usbdcd_driver.req[epnum]->len = p_endpoint_desc->wMaxPacketSize.size;
+ }
+ else
+ {
+ return false;
+ }
+
+ usbdcd_driver.req[epnum]->callback = usbdcd_ep0incomplete;
+
+ epdesc.len = p_endpoint_desc->bLength;
+ epdesc.type = p_endpoint_desc->bDescriptorType;
+ epdesc.addr = p_endpoint_desc->bEndpointAddress;
+ epdesc.attr = xfrtype;
+ epdesc.mxpacketsize[0] = LSBYTE(p_endpoint_desc->wMaxPacketSize.size);
+ epdesc.mxpacketsize[1] = MSBYTE(p_endpoint_desc->wMaxPacketSize.size);
+ epdesc.interval = p_endpoint_desc->bInterval;
+
+ if (EP_CONFIGURE(usbdcd_driver.ep[epnum], &epdesc, false) < 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
+{
+ (void) rhport;
+
+ uint8_t epnum = tu_edpt_number(ep_addr);
+
+ if (epnum >= CXD56_EPNUM)
+ {
+ return false;
+ }
+
+ usbdcd_driver.req[epnum]->len = total_bytes;
+ usbdcd_driver.req[epnum]->priv = (void *)((uint32_t)ep_addr);
+ usbdcd_driver.req[epnum]->flags = 0;
+
+ if (total_bytes)
+ {
+ usbdcd_driver.req[epnum]->buf = buffer;
+ }
+ else
+ {
+ return true;
+ }
+
+ if (EP_SUBMIT(usbdcd_driver.ep[epnum], usbdcd_driver.req[epnum]) < 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ uint8_t epnum = tu_edpt_number(ep_addr);
+
+ if (epnum >= CXD56_EPNUM)
+ {
+ return;
+ }
+
+ EP_STALL(usbdcd_driver.ep[epnum]);
+}
+
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ uint8_t epnum = tu_edpt_number(ep_addr);
+
+ if (epnum >= CXD56_EPNUM)
+ {
+ return;
+ }
+
+ EP_RESUME(usbdcd_driver.ep[epnum]);
+}
+
+#endif
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index c33f9b865..ec182960e 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -261,6 +261,12 @@ void dcd_int_enable (uint8_t rhport)
NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn);
NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn);
NVIC_EnableIRQ(USBWakeUp_IRQn);
+#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
+ NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
+ NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
+ NVIC_EnableIRQ(USBWakeUp_IRQn);
+#else
+ #error Unknown arch in USB driver
#endif
}
@@ -275,9 +281,14 @@ void dcd_int_disable(uint8_t rhport)
NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn);
NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn);
NVIC_DisableIRQ(USBWakeUp_IRQn);
+#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
+ NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
+ NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
+ NVIC_DisableIRQ(USBWakeUp_IRQn);
#else
#error Unknown arch in USB driver
#endif
+
// CMSIS has a membar after disabling interrupts
}
@@ -822,7 +833,7 @@ void USB_IRQHandler(void)
dcd_fs_irqHandler();
}
-#elif (CFG_TUSB_MCU) == (OPT_MCU_STM32F1)
+#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
void USB_HP_IRQHandler(void)
{
dcd_fs_irqHandler();
@@ -854,14 +865,16 @@ void USB_LP_CAN_RX0_IRQHandler(void)
{
dcd_fs_irqHandler();
}
+
// USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB
// Suspend mode.
void USBWakeUp_IRQHandler(void)
{
dcd_fs_irqHandler();
}
+
#else
-#error Which IRQ handler do you need?
+ #error Which IRQ handler do you need?
#endif
#endif
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h
index bbaa52eae..36dca8cd8 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h
@@ -57,7 +57,9 @@
#define PMA_LENGTH (512u)
// NO internal Pull-ups
// *B, and *C: 2 x 16 bits/word
- #error The F102/F103 driver is expected not to work, but it might? Try it?
+
+ // F1 names this differently from the rest
+ #define USB_CNTR_LPMODE USB_CNTR_LP_MODE
#elif defined(STM32F302xB) || defined(STM32F302xC) || \
defined(STM32F303xB) || defined(STM32F303xC) || \
diff --git a/src/tusb.c b/src/tusb.c
index 0f8eedd57..7a1e73ec7 100644
--- a/src/tusb.c
+++ b/src/tusb.c
@@ -43,11 +43,11 @@ bool tusb_init(void)
if (_initialized) return true;
#if TUSB_OPT_HOST_ENABLED
- TU_VERIFY( usbh_init() ); // init host stack
+ TU_ASSERT( usbh_init() ); // init host stack
#endif
#if TUSB_OPT_DEVICE_ENABLED
- TU_VERIFY ( usbd_init() ); // init device stack
+ TU_ASSERT ( tud_init() ); // init device stack
#endif
_initialized = true;
@@ -64,7 +64,81 @@ bool tusb_inited(void)
/* Debug
*------------------------------------------------------------------*/
#if CFG_TUSB_DEBUG
+#include <ctype.h>
+
char const* const tusb_strerr[TUSB_ERROR_COUNT] = { ERROR_TABLE(ERROR_STRING) };
+
+static void dump_str_line(uint8_t const* buf, uint16_t count)
+{
+ // each line is 16 bytes
+ for(int i=0; i<count; i++)
+ {
+ const char ch = buf[i];
+ tu_printf("%c", isprint(ch) ? ch : '.');
+ }
+}
+
+// size : item size in bytes
+// count : number of item
+// print offet or not (handfy for dumping large memory)
+void tu_print_mem(void const *buf, uint8_t size, uint16_t count)
+{
+ if ( !buf || !count )
+ {
+ tu_printf("NULL\r\n");
+ return;
+ }
+
+ uint8_t const *buf8 = (uint8_t const *) buf;
+
+ char format[] = "%00lX";
+ format[2] += 2*size;
+
+ const uint8_t item_per_line = 16 / size;
+
+ for(uint32_t i=0; i<count; i++)
+ {
+ uint32_t value=0;
+
+ if ( i%item_per_line == 0 )
+ {
+ // Print Ascii
+ if ( i != 0 )
+ {
+ tu_printf(" | ");
+ dump_str_line(buf8-16, 16);
+ tu_printf("\r\n");
+ }
+
+ // print offset or absolute address
+ tu_printf("%03lX: ", 16*i/item_per_line);
+ }
+
+ memcpy(&value, buf8, size);
+ buf8 += size;
+
+ tu_printf(" ");
+ tu_printf(format, value);
+ }
+
+ // fill up last row to 16 for printing ascii
+ const uint16_t remain = count%16;
+ uint8_t nback = (remain ? remain : 16);
+
+ if ( remain )
+ {
+ for(int i=0; i< 16-remain; i++)
+ {
+ tu_printf(" ");
+ for(int j=0; j<2*size; j++) tu_printf(" ");
+ }
+ }
+
+ tu_printf(" | ");
+ dump_str_line(buf8-nback, nback);
+ tu_printf("\r\n");
+}
+
#endif
#endif // host or device enabled
diff --git a/src/tusb.h b/src/tusb.h
index 1a6ff0b10..bf4ad5730 100644
--- a/src/tusb.h
+++ b/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
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 76ea59758..fc509ae76 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -38,7 +38,8 @@
// LPC
#define OPT_MCU_LPC11UXX 1 ///< NXP LPC11Uxx
-#define OPT_MCU_LPC13XX 3 ///< NXP LPC13xx
+#define OPT_MCU_LPC13XX 2 ///< NXP LPC13xx
+#define OPT_MCU_LPC15XX 3 ///< NXP LPC15xx
#define OPT_MCU_LPC175X_6X 4 ///< NXP LPC175x, LPC176x
#define OPT_MCU_LPC177X_8X 5 ///< NXP LPC177x, LPC178x
#define OPT_MCU_LPC18XX 6 ///< NXP LPC18xx
@@ -67,6 +68,8 @@
#define OPT_MCU_STM32L1 308 ///< ST STM32L1
#define OPT_MCU_STM32L4 309 ///< ST STM32L4
+#define OPT_MCU_CXD56 400 ///< SONY CXD56
+
/** @} */
/** \defgroup group_supported_os Supported RTOS
@@ -185,6 +188,10 @@
#define CFG_TUD_USBTMC 0
#endif
+#ifndef CFG_TUD_DFU_RT
+ #define CFG_TUD_DFU_RT 0
+#endif
+
//--------------------------------------------------------------------
// HOST OPTIONS