From c4483d244b04a6679d85376e3e686c23b9ee82af Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 27 Sep 2019 12:41:46 -0400 Subject: Fix typo of CFG_TUD_ENDOINT0_SIZE. --- src/device/usbd_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 4ec432185..eed933f68 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -124,7 +124,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result _control_state.total_transferred += xferred_bytes; _control_state.buffer += xferred_bytes; - if ( _control_state.total_len == _control_state.total_transferred || xferred_bytes < CFG_TUD_ENDOINT0_SIZE ) + if ( _control_state.total_len == _control_state.total_transferred || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE ) { // DATA stage is complete bool is_ok = true; -- cgit v1.3.1 From b0b737b42a14982a1f928e408ba7eadc3f474d04 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Wed, 2 Oct 2019 23:02:55 -0400 Subject: usbd_control.c: Decide whether a control transfer has a data stage based on setup packet wLength. --- src/device/usbd_control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index eed933f68..69ab47b4d 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -94,7 +94,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo _control_state.total_len = tu_min16(len, request->wLength); _control_state.total_transferred = 0; - if ( len ) + if ( _control_state.total_len ) { TU_ASSERT(buffer); -- cgit v1.3.1 From a01b0a73c13ca771e77440d040b0e1e3c5ecbcf7 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 3 Oct 2019 23:58:24 -0400 Subject: Remove accidentally-commited debug var. --- src/device/usbd_control.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 070ff504b..e1e9b9f01 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -116,7 +116,6 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo return true; } -volatile int dummy = 0; // callback when a transaction complete on DATA stage of control endpoint bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -133,13 +132,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result _control_state.total_transferred += xferred_bytes; _control_state.buffer = ((uint8_t*)_control_state.buffer) + xferred_bytes; - if((_control_state.total_transferred >= 144)) - { - dummy = 1; - } - if ( (_control_state.requested_len == _control_state.total_transferred) || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE ) - { // DATA stage is complete bool is_ok = true; -- cgit v1.3.1 From f6a65720e563a5edc69fdb5e2c1aa320e206a059 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Oct 2019 16:25:32 +0700 Subject: should fix #184 only response up to EP0 size with get device descriptor if not addressed. --- src/device/usbd.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f2becab95..5c6fc3748 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -44,6 +44,7 @@ typedef struct { struct TU_ATTR_PACKED { volatile uint8_t connected : 1; + volatile uint8_t addressed : 1; volatile uint8_t configured : 1; volatile uint8_t suspended : 1; @@ -478,6 +479,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Depending on mcu, status phase could be sent either before or after changing device address // Therefore DCD must include zero-length status response dcd_set_address(rhport, (uint8_t) p_request->wValue); + _usbd_dev.addressed = 1; return true; // skip status break; @@ -752,7 +754,17 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const switch(desc_type) { case TUSB_DESC_DEVICE: - return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), sizeof(tusb_desc_device_t)); + { + uint16_t len = sizeof(tusb_desc_device_t); + + // Only send up to EP0 Packet Size if not addressed + if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed) + { + len = CFG_TUD_ENDPOINT0_SIZE; + } + + return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), len); + } break; case TUSB_DESC_BOS: @@ -820,6 +832,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) case DCD_EVENT_UNPLUGGED: _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; _usbd_dev.configured = 0; _usbd_dev.suspended = 0; osal_queue_send(_usbd_q, event, in_isr); -- cgit v1.3.1 From 1b51b78eafb1a078aa7fc8caf57d01d92b84ca0f Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 3 Nov 2019 00:17:17 +0700 Subject: hack the request length for the first get device descriptor if EP0 size =8 or 16 to prevent usbd control send out ZLP --- src/device/usbd.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 8661717f5..360881f34 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -771,9 +771,13 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const uint16_t len = sizeof(tusb_desc_device_t); // Only send up to EP0 Packet Size if not addressed + // This only happens with the very first get device descriptor and EP0 size = 8 or 16. if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed) { len = CFG_TUD_ENDPOINT0_SIZE; + + // Hack here: we modify the request length to prevent usbd_control response with zlp + ((tusb_control_request_t*) p_request)->wLength = CFG_TUD_ENDPOINT0_SIZE; } return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), len); -- cgit v1.3.1 From 65e96e5d525ea02e0ca7f265a4d62b4f428cc821 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 3 Nov 2019 18:00:07 +0700 Subject: added optional dcd_control_status_complete() --- src/device/dcd.h | 4 ++++ src/device/usbd_control.c | 1 + test/test/device/usbd/test_usbd.c | 2 ++ 3 files changed, 7 insertions(+) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 9fa98c669..c88465cbb 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -119,6 +119,10 @@ 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); +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_control_status_complete(uint8_t rhport) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Event API //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f41614ef1..d37e9ec2a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -129,6 +129,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) { TU_ASSERT(0 == xferred_bytes); + if (dcd_control_status_complete) dcd_control_status_complete(rhport); return true; } diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index add947b3d..a4063a488 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -231,5 +231,7 @@ void test_usbd_control_in_zlp(void) dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); + dcd_control_status_complete_Expect(rhport); + tud_task(); } -- cgit v1.3.1 From b6b9fe42af1828c2ed8f794a930999ecb4da2902 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2020 16:43:44 +0700 Subject: more log for debugging --- src/class/cdc/cdc_device.c | 11 ++++++++++- src/device/usbd_control.c | 14 +++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index c0de0cadd..f63418dae 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -335,25 +335,34 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: + TU_LOG2(" Set Line Coding\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_GET_LINE_CODING: + TU_LOG2(" Get Line Coding\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: + { // CDC PSTN v1.2 section 6.3.12 // Bit 0: Indicates if DTE is present or not. // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) // Bit 1: Carrier control for half-duplex modems. // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + bool const dtr = tu_bit_test(request->wValue, 0); + bool const rts = tu_bit_test(request->wValue, 1); + p_cdc->line_state = (uint8_t) request->wValue; + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\n", dtr, rts); + tud_control_status(rhport, request); // Invoke callback - if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, tu_bit_test(request->wValue, 0), tu_bit_test(request->wValue, 1)); + if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts); + } break; default: return false; // stall unsupported request diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index e6d1caf4b..5a0ba412f 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -51,8 +51,8 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; - +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; //--------------------------------------------------------------------+ // Application API @@ -60,8 +60,14 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_EN static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) { + // Opposite to endpoint in Data Phase + uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; + + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", ep_addr, 0); + // status direction is reversed to one in the setup packet - return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0); + // Note: Status must always be DATA1 + return dcd_edpt_xfer(rhport, ep_addr, NULL, 0); } // Status phase @@ -106,6 +112,8 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // Data stage TU_ASSERT( _data_stage_xact(rhport) ); + + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); }else { // Status stage -- cgit v1.3.1 From b8ea0f0a6b11bff6a4bb3f63f09485b2445969de Mon Sep 17 00:00:00 2001 From: Chang Feng Date: Wed, 26 Feb 2020 13:07:15 +0800 Subject: Add langid support to descriptor string callback. Signed-off-by: Chang Feng --- src/device/usbd.c | 2 +- src/device/usbd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 16670b944..68c5c5160 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -809,7 +809,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const return false; }else { - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index); + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); TU_ASSERT(desc_str); // first byte of descriptor is its size diff --git a/src/device/usbd.h b/src/device/usbd.h index 847251caa..d80abf17c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -91,7 +91,7 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index); +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); // Invoked when device is mounted (configured) TU_ATTR_WEAK void tud_mount_cb(void); -- cgit v1.3.1 From fee79d746604f671483f5872337ea366f2d2c1a2 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:15:01 -0600 Subject: add CDC-ECM/RNDIS/CDC-EEM network device class with example --- .gitmodules | 5 +- examples/device/lwip_webserver/Makefile | 57 ++++ examples/device/lwip_webserver/src/arch/cc.h | 75 +++++ examples/device/lwip_webserver/src/lwipopts.h | 57 ++++ examples/device/lwip_webserver/src/main.c | 214 +++++++++++++ examples/device/lwip_webserver/src/tusb_config.h | 90 ++++++ .../device/lwip_webserver/src/usb_descriptors.c | 199 ++++++++++++ .../device/lwip_webserver/src/usb_descriptors.h | 28 ++ examples/rules.mk | 1 + lib/lwip | 1 + lib/networking/dhserver.c | 347 +++++++++++++++++++++ lib/networking/dhserver.h | 63 ++++ lib/networking/dnserver.c | 200 ++++++++++++ lib/networking/dnserver.h | 47 +++ lib/networking/ndis.h | 266 ++++++++++++++++ lib/networking/rndis_protocol.h | 307 ++++++++++++++++++ lib/networking/rndis_reports.c | 303 ++++++++++++++++++ src/class/net/net_device.c | 345 ++++++++++++++++++++ src/class/net/net_device.h | 84 +++++ src/device/usbd.c | 18 ++ src/device/usbd.h | 84 +++++ src/tusb.h | 4 + src/tusb_option.h | 12 + 23 files changed, 2806 insertions(+), 1 deletion(-) create mode 100644 examples/device/lwip_webserver/Makefile create mode 100644 examples/device/lwip_webserver/src/arch/cc.h create mode 100644 examples/device/lwip_webserver/src/lwipopts.h create mode 100644 examples/device/lwip_webserver/src/main.c create mode 100644 examples/device/lwip_webserver/src/tusb_config.h create mode 100644 examples/device/lwip_webserver/src/usb_descriptors.c create mode 100644 examples/device/lwip_webserver/src/usb_descriptors.h create mode 160000 lib/lwip create mode 100644 lib/networking/dhserver.c create mode 100644 lib/networking/dhserver.h create mode 100644 lib/networking/dnserver.c create mode 100644 lib/networking/dnserver.h create mode 100644 lib/networking/ndis.h create mode 100644 lib/networking/rndis_protocol.h create mode 100644 lib/networking/rndis_reports.c create mode 100644 src/class/net/net_device.c create mode 100644 src/class/net/net_device.h (limited to 'src/device') diff --git a/.gitmodules b/.gitmodules index 18b627bcf..0dda17d64 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,4 +21,7 @@ url = https://github.com/hathach/microchip_driver.git [submodule "hw/mcu/nuvoton"] path = hw/mcu/nuvoton - url = https://github.com/majbthrd/nuc_driver.git \ No newline at end of file + url = https://github.com/majbthrd/nuc_driver.git +[submodule "lib/lwip"] + path = lib/lwip + url = https://git.savannah.nongnu.org/git/lwip.git diff --git a/examples/device/lwip_webserver/Makefile b/examples/device/lwip_webserver/Makefile new file mode 100644 index 000000000..a153c30be --- /dev/null +++ b/examples/device/lwip_webserver/Makefile @@ -0,0 +1,57 @@ +include ../../../tools/top.mk +include ../../make.mk + +CFLAGS += \ + -DPBUF_POOL_SIZE=2 \ + -DTCP_WND=2*TCP_MSS \ + -DHTTPD_USE_CUSTOM_FSDATA=0 + +INC += \ + src \ + $(TOP)/hw \ + $(TOP)/lib/lwip/src/include \ + $(TOP)/lib/lwip/src/include/ipv4 \ + $(TOP)/lib/lwip/src/include/lwip/apps \ + $(TOP)/lib/networking + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += \ + lib/lwip/src/core/altcp.c \ + lib/lwip/src/core/altcp_alloc.c \ + lib/lwip/src/core/altcp_tcp.c \ + lib/lwip/src/core/def.c \ + lib/lwip/src/core/dns.c \ + lib/lwip/src/core/inet_chksum.c \ + lib/lwip/src/core/init.c \ + lib/lwip/src/core/ip.c \ + lib/lwip/src/core/mem.c \ + lib/lwip/src/core/memp.c \ + lib/lwip/src/core/netif.c \ + lib/lwip/src/core/pbuf.c \ + lib/lwip/src/core/raw.c \ + lib/lwip/src/core/stats.c \ + lib/lwip/src/core/sys.c \ + lib/lwip/src/core/tcp.c \ + lib/lwip/src/core/tcp_in.c \ + lib/lwip/src/core/tcp_out.c \ + lib/lwip/src/core/timeouts.c \ + lib/lwip/src/core/udp.c \ + lib/lwip/src/core/ipv4/autoip.c \ + lib/lwip/src/core/ipv4/dhcp.c \ + lib/lwip/src/core/ipv4/etharp.c \ + lib/lwip/src/core/ipv4/icmp.c \ + lib/lwip/src/core/ipv4/igmp.c \ + lib/lwip/src/core/ipv4/ip4.c \ + lib/lwip/src/core/ipv4/ip4_addr.c \ + lib/lwip/src/core/ipv4/ip4_frag.c \ + lib/lwip/src/netif/ethernet.c \ + lib/lwip/src/netif/slipif.c \ + lib/lwip/src/apps/http/httpd.c \ + lib/lwip/src/apps/http/fs.c \ + lib/networking/dhserver.c \ + lib/networking/dnserver.c \ + lib/networking/rndis_reports.c + +include ../../rules.mk diff --git a/examples/device/lwip_webserver/src/arch/cc.h b/examples/device/lwip_webserver/src/arch/cc.h new file mode 100644 index 000000000..56a0cacf7 --- /dev/null +++ b/examples/device/lwip_webserver/src/arch/cc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +//#include "cpu.h" + +typedef int sys_prot_t; + + + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/examples/device/lwip_webserver/src/lwipopts.h b/examples/device/lwip_webserver/src/lwipopts.h new file mode 100644 index 000000000..23319592d --- /dev/null +++ b/examples/device/lwip_webserver/src/lwipopts.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ +#define NO_SYS 1 +#define MEM_ALIGNMENT 4 +#define LWIP_RAW 1 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define LWIP_DHCP 0 +#define LWIP_ICMP 1 +#define LWIP_UDP 1 +#define LWIP_TCP 1 +#define ETH_PAD_SIZE 0 +#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) + +#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) +#define TCP_SND_BUF (2 * TCP_MSS) + +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 + +#define LWIP_HTTPD_CGI 0 +#define LWIP_HTTPD_SSI 0 +#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 + +#endif /* __LWIPOPTS_H__ */ diff --git a/examples/device/lwip_webserver/src/main.c b/examples/device/lwip_webserver/src/main.c new file mode 100644 index 000000000..364a26788 --- /dev/null +++ b/examples/device/lwip_webserver/src/main.c @@ -0,0 +1,214 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * + * influenced by lrndis https://github.com/fetisov/lrndis + * + * 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. + * + */ + +/* +depending on the value of CFG_TUD_NET (tusb_config.h), this can be a CDC-ECM, RNDIS, or CDC-EEM USB virtual network adapter + +CDC-ECM should be valid on Linux and MacOS hosts +RNDIS should be valid on Linux and Windows hosts +CDC-EEM should be valid on Linux hosts + +You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network adapters to emulate. + +The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. +*/ + +#include "bsp/board.h" +#include "tusb.h" + +#include "dhserver.h" +#include "dnserver.h" +#include "lwip/init.h" +#include "httpd.h" + +/* lwip context */ +static struct netif netif_data; + +/* shared between network_recv_callback() and service_traffic() */ +static struct pbuf *received_frame; + +/* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ +/* ideally speaking, this should be generated from the hardware's unique ID (if available) */ +const uint8_t network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; + +/* network parameters of this MCU */ +static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); +static const ip_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); +static const ip_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); + +/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ +static dhcp_entry_t entries[] = +{ + /* mac ip address subnet mask lease time */ + { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, + { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, + { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } +}; + +/* DHCP configuration parameters, leveraging "entries" above */ +static const dhcp_config_t dhcp_config = +{ + {192, 168, 7, 1}, 67, /* server address (self), port */ + {192, 168, 7, 1}, /* dns server (self) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* number of entries */ + entries /* pointer to entries */ +}; + +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) +{ + (void)netif; + + for (;;) + { + /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ + if (!tud_ready()) + return ERR_USE; + + /* if the network driver can accept another packet, we make it happen */ + if (network_can_xmit()) + { + network_xmit(p); + return ERR_OK; + } + + /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ + tud_task(); + } +} + +static err_t output_fn(struct netif *netif, struct pbuf *p, const ip_addr_t *addr) +{ + return etharp_output(netif, p, addr); +} + +static err_t netif_init_cb(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + netif->mtu = CFG_TUD_NET_MTU; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif->state = NULL; + netif->name[0] = 'E'; + netif->name[1] = 'X'; + netif->linkoutput = linkoutput_fn; + netif->output = output_fn; + return ERR_OK; +} + +static void init_lwip(void) +{ + struct netif *netif = &netif_data; + + lwip_init(); + netif->hwaddr_len = sizeof(network_mac_address); + memcpy(netif->hwaddr, network_mac_address, sizeof(network_mac_address)); + + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + netif_set_default(netif); +} + +/* handle any DNS requests from dns-server */ +bool dns_query_proc(const char *name, ip_addr_t *addr) +{ + if (0 == strcmp(name, "tiny.usb")) + { + *addr = ipaddr; + return true; + } + return false; +} + +bool network_recv_callback(struct pbuf *p) +{ + /* this shouldn't happen, but if we get another packet before + parsing the previous, we must signal our inability to accept it */ + if (received_frame) return false; + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + return true; +} + +static void service_traffic(void) +{ + /* handle any packet received by network_recv_callback() */ + if (received_frame) + { + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + network_recv_renew(); + } +} + +void network_init_callback(void) +{ + /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ + if (received_frame) + { + pbuf_free(received_frame); + received_frame = NULL; + } +} + +int main(void) +{ + /* initialize TinyUSB */ + board_init(); + tusb_init(); + + /* initialize lwip, dhcp-server, dns-server, and http */ + init_lwip(); + while (!netif_is_up(&netif_data)); + while (dhserv_init(&dhcp_config) != ERR_OK); + while (dnserv_init(&ipaddr, 53, dns_query_proc) != ERR_OK); + httpd_init(); + + while (1) + { + tud_task(); + service_traffic(); + } + + return 0; +} + +/* lwip has provision for using a mutex, when applicable */ +sys_prot_t sys_arch_protect(void) +{ + return 0; +} +void sys_arch_unprotect(sys_prot_t pval) +{ + (void)pval; +} + +/* lwip needs a millisecond time source, and the TinyUSB board support code has one available */ +uint32_t sys_now(void) +{ + return board_millis(); +} diff --git a/examples/device/lwip_webserver/src/tusb_config.h b/examples/device/lwip_webserver/src/tusb_config.h new file mode 100644 index 000000000..329fc80b9 --- /dev/null +++ b/examples/device/lwip_webserver/src/tusb_config.h @@ -0,0 +1,90 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#endif + +#define CFG_TUSB_OS OPT_OS_NONE + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 +//#define CFG_TUD_NET OPT_NET_ECM +#define CFG_TUD_NET OPT_NET_RNDIS +//#define CFG_TUD_NET OPT_NET_EEM + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/lwip_webserver/src/usb_descriptors.c b/examples/device/lwip_webserver/src/usb_descriptors.c new file mode 100644 index 000000000..803c99c02 --- /dev/null +++ b/examples/device/lwip_webserver/src/usb_descriptors.c @@ -0,0 +1,199 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + */ + +#include "tusb.h" +#include "usb_descriptors.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] NET1:NET0 | VENDOR | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(NET, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + .bDeviceClass = TUSB_CLASS_UNSPECIFIED, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_TOTAL +}; + +enum +{ + STR_LANGID = 0, + STR_MANUFACTURER, + STR_PRODUCT, + STR_ITFNAME, + STR_MAC, +}; + +#if CFG_TUD_NET == OPT_NET_ECM +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) +#elif CFG_TUD_NET == OPT_NET_RNDIS +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) +#elif CFG_TUD_NET == OPT_NET_EEM +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_CDC 2 +#else + #define EPNUM_CDC 2 +#endif + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), + +#if CFG_TUD_NET == OPT_NET_ECM + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STR_ITFNAME, STR_MAC, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), +#elif CFG_TUD_NET == OPT_NET_RNDIS + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STR_ITFNAME, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), +#elif CFG_TUD_NET == OPT_NET_EEM + // Interface number, description string index, EP data address (out, in) and size. + TUD_CDC_EEM_DESCRIPTOR(ITF_NUM_CDC, STR_ITFNAME, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), +#endif +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + [STR_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) + [STR_MANUFACTURER] = "TinyUSB", // Manufacturer + [STR_PRODUCT] = "TinyUSB Device", // Product + [STR_ITFNAME] = // CDC-ECM Interface +#if CFG_TUD_NET == OPT_NET_ECM + "TinyUSB CDC-ECM", +#elif CFG_TUD_NET == OPT_NET_RNDIS + "TinyUSB RNDIS", +#elif CFG_TUD_NET == OPT_NET_EEM + "TinyUSB CDC-EEM", +#endif +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void)langid; + + unsigned chr_count = 0; + + if (STR_LANGID == index) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } + else if (STR_MAC == index) + { + // Convert MAC address into UTF-16 + + for (unsigned i=0; i> 4) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(network_mac_address[i] >> 0) & 0xf]; + } + } + else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1; + + for (unsigned i=0; i + * + * 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. + */ + +#include "dhserver.h" + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/* DHCP options */ +enum DHCP_OPTIONS +{ + DHCP_PAD = 0, + DHCP_SUBNETMASK = 1, + DHCP_ROUTER = 3, + DHCP_DNSSERVER = 6, + DHCP_HOSTNAME = 12, + DHCP_DNSDOMAIN = 15, + DHCP_MTU = 26, + DHCP_BROADCAST = 28, + DHCP_PERFORMROUTERDISC = 31, + DHCP_STATICROUTE = 33, + DHCP_NISDOMAIN = 40, + DHCP_NISSERVER = 41, + DHCP_NTPSERVER = 42, + DHCP_VENDOR = 43, + DHCP_IPADDRESS = 50, + DHCP_LEASETIME = 51, + DHCP_OPTIONSOVERLOADED = 52, + DHCP_MESSAGETYPE = 53, + DHCP_SERVERID = 54, + DHCP_PARAMETERREQUESTLIST = 55, + DHCP_MESSAGE = 56, + DHCP_MAXMESSAGESIZE = 57, + DHCP_RENEWALTIME = 58, + DHCP_REBINDTIME = 59, + DHCP_CLASSID = 60, + DHCP_CLIENTID = 61, + DHCP_USERCLASS = 77, /* RFC 3004 */ + DHCP_FQDN = 81, + DHCP_DNSSEARCH = 119, /* RFC 3397 */ + DHCP_CSR = 121, /* RFC 3442 */ + DHCP_MSCSR = 249, /* MS code for RFC 3442 */ + DHCP_END = 255 +}; + +typedef struct +{ + uint8_t dp_op; /* packet opcode type */ + uint8_t dp_htype; /* hardware addr type */ + uint8_t dp_hlen; /* hardware addr length */ + uint8_t dp_hops; /* gateway hops */ + uint32_t dp_xid; /* transaction ID */ + uint16_t dp_secs; /* seconds since boot began */ + uint16_t dp_flags; + uint8_t dp_ciaddr[4]; /* client IP address */ + uint8_t dp_yiaddr[4]; /* 'your' IP address */ + uint8_t dp_siaddr[4]; /* server IP address */ + uint8_t dp_giaddr[4]; /* gateway IP address */ + uint8_t dp_chaddr[16]; /* client hardware address */ + uint8_t dp_legacy[192]; + uint8_t dp_magic[4]; + uint8_t dp_options[275]; /* options area */ +} DHCP_TYPE; + +DHCP_TYPE dhcp_data; +static struct udp_pcb *pcb = NULL; +static const dhcp_config_t *config = NULL; + +char magic_cookie[] = {0x63,0x82,0x53,0x63}; + +static uint32_t get_ip(const uint8_t *pnt) +{ + uint32_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static void set_ip(uint8_t *pnt, uint32_t value) +{ + memcpy(pnt, &value, sizeof(value)); +} + +static dhcp_entry_t *entry_by_ip(uint32_t ip) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (get_ip(config->entries[i].addr) == ip) + return &config->entries[i]; + return NULL; +} + +static dhcp_entry_t *entry_by_mac(uint8_t *mac) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (memcmp(config->entries[i].mac, mac, 6) == 0) + return &config->entries[i]; + return NULL; +} + +static __inline bool is_vacant(dhcp_entry_t *entry) +{ + return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; +} + +static dhcp_entry_t *vacant_address(void) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (is_vacant(config->entries + i)) + return config->entries + i; + return NULL; +} + +static __inline void free_entry(dhcp_entry_t *entry) +{ + memset(entry->mac, 0, 6); +} + +uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) +{ + int i = 0; + while ((i + 1) < size) + { + int next = i + attrs[i + 1] + 2; + if (next > size) return NULL; + if (attrs[i] == attr) + return attrs + i; + i = next; + } + return NULL; +} + +int fill_options(void *dest, + uint8_t msg_type, + const char *domain, + uint32_t dns, + int lease_time, + uint32_t serverid, + uint32_t router, + uint32_t subnet) +{ + uint8_t *ptr = (uint8_t *)dest; + /* ACK message type */ + *ptr++ = 53; + *ptr++ = 1; + *ptr++ = msg_type; + + /* dhcp server identifier */ + *ptr++ = DHCP_SERVERID; + *ptr++ = 4; + set_ip(ptr, serverid); + ptr += 4; + + /* lease time */ + *ptr++ = DHCP_LEASETIME; + *ptr++ = 4; + *ptr++ = (lease_time >> 24) & 0xFF; + *ptr++ = (lease_time >> 16) & 0xFF; + *ptr++ = (lease_time >> 8) & 0xFF; + *ptr++ = (lease_time >> 0) & 0xFF; + + /* subnet mask */ + *ptr++ = DHCP_SUBNETMASK; + *ptr++ = 4; + set_ip(ptr, subnet); + ptr += 4; + + /* router */ + if (router != 0) + { + *ptr++ = DHCP_ROUTER; + *ptr++ = 4; + set_ip(ptr, router); + ptr += 4; + } + + /* domain name */ + if (domain != NULL) + { + int len = strlen(domain); + *ptr++ = DHCP_DNSDOMAIN; + *ptr++ = len; + memcpy(ptr, domain, len); + ptr += len; + } + + /* domain name server (DNS) */ + if (dns != 0) + { + *ptr++ = DHCP_DNSSERVER; + *ptr++ = 4; + set_ip(ptr, dns); + ptr += 4; + } + + /* end */ + *ptr++ = DHCP_END; + return ptr - (uint8_t *)dest; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + uint8_t *ptr; + dhcp_entry_t *entry; + struct pbuf *pp; + + (void)arg; + (void)addr; + + unsigned n = p->len; + if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); + memcpy(&dhcp_data, p->payload, n); + switch (dhcp_data.dp_options[2]) + { + case DHCP_DISCOVER: + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry == NULL) entry = vacant_address(); + if (entry == NULL) break; + + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + set_ip(dhcp_data.dp_yiaddr, get_ip(entry->addr)); + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_OFFER, + config->domain, + get_ip(config->dns), + entry->lease, + get_ip(config->addr), + get_ip(config->addr), + get_ip(entry->subnet)); + + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + case DHCP_REQUEST: + /* 1. find requested ipaddr in option list */ + ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); + if (ptr == NULL) break; + if (ptr[1] != 4) break; + ptr += 2; + + /* 2. does hw-address registered? */ + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry != NULL) free_entry(entry); + + /* 3. find requested ipaddr */ + entry = entry_by_ip(get_ip(ptr)); + if (entry == NULL) break; + if (!is_vacant(entry)) break; + + /* 4. fill struct fields */ + memcpy(dhcp_data.dp_yiaddr, ptr, 4); + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + /* 5. fill options */ + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_ACK, + config->domain, + get_ip(config->dns), + entry->lease, + get_ip(config->addr), + get_ip(config->addr), + get_ip(entry->subnet)); + + /* 6. send ACK */ + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(entry->mac, dhcp_data.dp_chaddr, 6); + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + default: + break; + } + pbuf_free(p); +} + +err_t dhserv_init(const dhcp_config_t *c) +{ + err_t err; + udp_init(); + dhserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, IP_ADDR_ANY, c->port); + if (err != ERR_OK) + { + dhserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + config = c; + return ERR_OK; +} + +void dhserv_free(void) +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/lib/networking/dhserver.h b/lib/networking/dhserver.h new file mode 100644 index 000000000..901f6e351 --- /dev/null +++ b/lib/networking/dhserver.h @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dhcp ipv4 server using lwip (pcb) + * ref: https://lists.gnu.org/archive/html/lwip-users/2012-12/msg00016.html + */ + +#ifndef DHSERVER_H +#define DHSERVER_H + +#include +#include +#include +#include +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef struct dhcp_entry +{ + uint8_t mac[6]; + uint8_t addr[4]; + uint8_t subnet[4]; + uint32_t lease; +} dhcp_entry_t; + +typedef struct dhcp_config +{ + uint8_t addr[4]; + uint16_t port; + uint8_t dns[4]; + const char *domain; + int num_entry; + dhcp_entry_t *entries; +} dhcp_config_t; + +err_t dhserv_init(const dhcp_config_t *config); +void dhserv_free(void); + +#endif /* DHSERVER_H */ diff --git a/lib/networking/dnserver.c b/lib/networking/dnserver.c new file mode 100644 index 000000000..6df0bd0c4 --- /dev/null +++ b/lib/networking/dnserver.c @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#include "dnserver.h" + +#define DNS_MAX_HOST_NAME_LEN 128 + +static struct udp_pcb *pcb = NULL; +dns_query_proc_t query_proc = NULL; + +#pragma pack(push, 1) +typedef struct +{ +#if BYTE_ORDER == LITTLE_ENDIAN + uint8_t rd: 1, /* Recursion Desired */ + tc: 1, /* Truncation Flag */ + aa: 1, /* Authoritative Answer Flag */ + opcode: 4, /* Operation code */ + qr: 1; /* Query/Response Flag */ + uint8_t rcode: 4, /* Response Code */ + z: 3, /* Zero */ + ra: 1; /* Recursion Available */ +#else + uint8_t qr: 1, /* Query/Response Flag */ + opcode: 4, /* Operation code */ + aa: 1, /* Authoritative Answer Flag */ + tc: 1, /* Truncation Flag */ + rd: 1; /* Recursion Desired */ + uint8_t ra: 1, /* Recursion Available */ + z: 3, /* Zero */ + rcode: 4; /* Response Code */ +#endif +} dns_header_flags_t; + +typedef struct +{ + uint16_t id; + dns_header_flags_t flags; + uint16_t n_record[4]; +} dns_header_t; + +typedef struct dns_answer +{ + uint16_t name; + uint16_t type; + uint16_t Class; + uint32_t ttl; + uint16_t len; + uint32_t addr; +} dns_answer_t; +#pragma pack(pop) + +typedef struct dns_query +{ + char name[DNS_MAX_HOST_NAME_LEN]; + uint16_t type; + uint16_t Class; +} dns_query_t; + +static uint16_t get_uint16(const uint8_t *pnt) +{ + uint16_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static int parse_next_query(void *data, int size, dns_query_t *query) +{ + int len; + int lables; + uint8_t *ptr; + + len = 0; + lables = 0; + ptr = (uint8_t *)data; + + while (true) + { + uint8_t lable_len; + if (size <= 0) return -1; + lable_len = *ptr++; + size--; + if (lable_len == 0) break; + if (lables > 0) + { + if (len == DNS_MAX_HOST_NAME_LEN) return -2; + query->name[len++] = '.'; + } + if (lable_len > size) return -1; + if (len + lable_len >= DNS_MAX_HOST_NAME_LEN) return -2; + memcpy(&query->name[len], ptr, lable_len); + len += lable_len; + ptr += lable_len; + size -= lable_len; + lables++; + } + + if (size < 4) return -1; + query->name[len] = 0; + query->type = get_uint16(ptr); + ptr += 2; + query->Class = get_uint16(ptr); + ptr += 2; + return ptr - (uint8_t *)data; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + int len; + dns_header_t *header; + static dns_query_t query; + struct pbuf *out; + ip_addr_t host_addr; + dns_answer_t *answer; + + (void)arg; + + if (p->len <= sizeof(dns_header_t)) goto error; + header = (dns_header_t *)p->payload; + if (header->flags.qr != 0) goto error; + if (ntohs(header->n_record[0]) != 1) goto error; + + len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query); + if (len < 0) goto error; + if (!query_proc(query.name, &host_addr)) goto error; + + len += sizeof(dns_header_t); + out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL); + if (out == NULL) goto error; + + memcpy(out->payload, p->payload, len); + header = (dns_header_t *)out->payload; + header->flags.qr = 1; + header->n_record[1] = htons(1); + answer = (struct dns_answer *)((uint8_t *)out->payload + len); + answer->name = htons(0xC00C); + answer->type = htons(1); + answer->Class = htons(1); + answer->ttl = htonl(32); + answer->len = htons(4); + answer->addr = host_addr.addr; + + udp_sendto(upcb, out, addr, port); + pbuf_free(out); + +error: + pbuf_free(p); +} + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t qp) +{ + err_t err; + udp_init(); + dnserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, bind, port); + if (err != ERR_OK) + { + dnserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + query_proc = qp; + return ERR_OK; +} + +void dnserv_free() +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/lib/networking/dnserver.h b/lib/networking/dnserver.h new file mode 100644 index 000000000..130991f5f --- /dev/null +++ b/lib/networking/dnserver.h @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#ifndef DNSERVER +#define DNSERVER + +#include +#include +#include +#include +#include "lwip/def.h" +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef bool (*dns_query_proc_t)(const char *name, ip_addr_t *addr); + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc); +void dnserv_free(void); + +#endif diff --git a/lib/networking/ndis.h b/lib/networking/ndis.h new file mode 100644 index 000000000..1c737574c --- /dev/null +++ b/lib/networking/ndis.h @@ -0,0 +1,266 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ndis.h *************************************************************** + * + * \brief + * This file contains the possible external configuration of the USB. + * + * \addtogroup usbstick + * + * + ******************************************************************************/ + +/** + \ingroup usbstick + \defgroup RNDIS RNDIS Support + @{ + */ + +/* + * ndis.h + * + * Modified by Colin O'Flynn + * ntddndis.h modified by Benedikt Spranger + * + * Thanks to the cygwin development team, + * espacially to Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef _LINUX_NDIS_H +#define _LINUX_NDIS_H + + +#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 +#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A +#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B + +/* from drivers/net/sk98lin/h/skgepnmi.h */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + +enum NDIS_DEVICE_POWER_STATE { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +}; + +struct NDIS_PM_WAKE_UP_CAPABILITIES { + enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +}; + +/* NDIS_PNP_CAPABILITIES.Flags constants */ +#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 +#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 +#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +/* +struct NDIS_PNP_CAPABILITIES { + __le32 Flags; + struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +}; + +struct NDIS_PM_PACKET_PATTERN { + __le32 Priority; + __le32 Reserved; + __le32 MaskSize; + __le32 PatternOffset; + __le32 PatternSize; + __le32 PatternFlags; +}; +*/ + +/* Required Object IDs (OIDs) */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 +#define OID_GEN_MACHINE_NAME 0x0001021A +#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B +#define OID_GEN_VLAN_ID 0x0001021C + +/* Optional OIDs */ +#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Required statistics OIDs */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional statistics OIDs */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +#define OID_GEN_NETCARD_LOAD 0x00020211 +#define OID_GEN_DEVICE_PROFILE 0x00020212 +#define OID_GEN_INIT_TIME_MS 0x00020213 +#define OID_GEN_RESET_COUNTS 0x00020214 +#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 +#define OID_GEN_FRIENDLY_NAME 0x00020216 +#define OID_GEN_MINIPORT_INFO 0x00020217 +#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 + +/* IEEE 802.3 (Ethernet) OIDs */ +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* Wireless LAN OIDs */ +/* Mandatory */ +#define OID_802_11_BSSID 0x0D010101 /* Q S */ +#define OID_802_11_SSID 0x0D010102 /* Q S */ +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */ +#define OID_802_11_RSSI 0x0D010206 /* Q I */ +#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */ +#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */ +#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */ +#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */ +#define OID_802_11_ADD_WEP 0x0D010113 /* S */ +#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */ +#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */ +#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */ +#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */ +#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */ + + + +/* OID_GEN_MINIPORT_INFO constants */ +#define NDIS_MINIPORT_BUS_MASTER 0x00000001 +#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 +#define NDIS_MINIPORT_SG_LIST 0x00000004 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 +#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 +#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 +#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 +#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 +#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 +#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 +#define NDIS_MINIPORT_IS_CO 0x00000400 +#define NDIS_MINIPORT_DESERIALIZE 0x00000800 +#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 +#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 +#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 +#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 +#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 +#define NDIS_MINIPORT_HIDDEN 0x00040000 +#define NDIS_MINIPORT_SWENUM 0x00080000 +#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 +#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 +#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 +#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 +#define NDIS_MINIPORT_64BITS_DMA 0x01000000 + +#define NDIS_MEDIUM_802_3 0x00000000 +#define NDIS_MEDIUM_802_5 0x00000001 +#define NDIS_MEDIUM_FDDI 0x00000002 +#define NDIS_MEDIUM_WAN 0x00000003 +#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 +#define NDIS_MEDIUM_DIX 0x00000005 +#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 +#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 +#define NDIS_MEDIUM_ATM 0x00000008 +#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 +#define NDIS_MEDIUM_IRDA 0x0000000A +#define NDIS_MEDIUM_BPC 0x0000000B +#define NDIS_MEDIUM_CO_WAN 0x0000000C +#define NDIS_MEDIUM_1394 0x0000000D + +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00000100 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 + +#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 +#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 + +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +#endif /* _LINUX_NDIS_H */ + +/** @} */ diff --git a/lib/networking/rndis_protocol.h b/lib/networking/rndis_protocol.h new file mode 100644 index 000000000..b45860eeb --- /dev/null +++ b/lib/networking/rndis_protocol.h @@ -0,0 +1,307 @@ +/** + * \file rndis_protocol.h + * RNDIS Defines + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ + +/* Copyright (c) 2008 Colin O'Flynn + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _RNDIS_H +#define _RNDIS_H + +/** + \addtogroup RNDIS + @{ + */ + +#include + +#define RNDIS_MAJOR_VERSION 1 +#define RNDIS_MINOR_VERSION 0 + +#define RNDIS_STATUS_SUCCESS 0X00000000 +#define RNDIS_STATUS_FAILURE 0XC0000001 +#define RNDIS_STATUS_INVALID_DATA 0XC0010015 +#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB +#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B +#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C + + +/* Message set for Connectionless (802.3) Devices */ +#define REMOTE_NDIS_PACKET_MSG 0x00000001 +#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002 +#define REMOTE_NDIS_HALT_MSG 0X00000003 +#define REMOTE_NDIS_QUERY_MSG 0X00000004 +#define REMOTE_NDIS_SET_MSG 0X00000005 +#define REMOTE_NDIS_RESET_MSG 0X00000006 +#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007 +#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008 +#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002 +#define REMOTE_NDIS_QUERY_CMPLT 0X80000004 +#define REMOTE_NDIS_SET_CMPLT 0X80000005 +#define REMOTE_NDIS_RESET_CMPLT 0X80000006 +#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008 + +typedef uint32_t rndis_MessageType_t; +typedef uint32_t rndis_MessageLength_t; +typedef uint32_t rndis_RequestId_t; +typedef uint32_t rndis_MajorVersion_t; +typedef uint32_t rndis_MinorVersion_t; +typedef uint32_t rndis_MaxTransferSize_t; +typedef uint32_t rndis_Status_t; + + +/* Device Flags */ +#define RNDIS_DF_CONNECTIONLESS 0x00000001 +#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 +typedef uint32_t rndis_DeviceFlags_t; + +/* Mediums */ +#define RNDIS_MEDIUM_802_3 0x00000000 +typedef uint32_t rndis_Medium_t; + + +typedef uint32_t rndis_MaxPacketsPerTransfer_t; +typedef uint32_t rndis_PacketAlignmentFactor_t; +typedef uint32_t rndis_AfListOffset_t; +typedef uint32_t rndis_AfListSize_t; + +/*** Remote NDIS Generic Message type ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + } rndis_generic_msg_t; + + +/*** Remote NDIS Initialize Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_MaxTransferSize_t MaxTransferSize; + } rndis_initialize_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_DeviceFlags_t DeviceFlags; + rndis_Medium_t Medium; + rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer; + rndis_MaxTransferSize_t MaxTransferSize; + rndis_PacketAlignmentFactor_t PacketAlignmentFactor; + rndis_AfListOffset_t AfListOffset; + rndis_AfListSize_t AfListSize; + } rndis_initialize_cmplt_t; + + +/*** Remote NDIS Halt Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + } rndis_halt_msg_t; + +typedef uint32_t rndis_Oid_t; +typedef uint32_t rndis_InformationBufferLength_t; +typedef uint32_t rndis_InformationBufferOffset_t; +typedef uint32_t rndis_DeviceVcHandle_t; + +/*** Remote NDIS Query Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_query_msg_t; + +/* Response: */ + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + } rndis_query_cmplt_t; + +/*** Remote NDIS Set Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_set_msg_t; + +/* Response */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_set_cmplt_t; + +/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */ +typedef uint32_t rndis_ParameterNameOffset_t; +typedef uint32_t rndis_ParameterNameLength_t; +typedef uint32_t rndis_ParameterType_t; +typedef uint32_t rndis_ParameterValueOffset_t; +typedef uint32_t rndis_ParameterValueLength_t; + +#define PARAMETER_TYPE_STRING 2 +#define PARAMETER_TYPE_NUMERICAL 0 + +typedef struct{ + rndis_ParameterNameOffset_t ParameterNameOffset; + rndis_ParameterNameLength_t ParameterNameLength; + rndis_ParameterType_t ParameterType; + rndis_ParameterValueOffset_t ParameterValueOffset; + rndis_ParameterValueLength_t ParameterValueLength; + }rndis_config_parameter_t; + +typedef uint32_t rndis_Reserved_t; + +/*** Remote NDIS Soft Reset Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Reserved_t Reserved; + } rndis_reset_msg_t; + +typedef uint32_t rndis_AddressingReset_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_AddressingReset_t AddressingReset; + } rndis_reset_cmplt_t; + +/*** Remote NDIS Indicate Status Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_Status_t StatusBufferLength; + rndis_Status_t StatusBufferOffset; + } rndis_indicate_status_t; + +typedef uint32_t rndis_DiagStatus_t; +typedef uint32_t rndis_ErrorOffset_t; + +typedef struct { + rndis_DiagStatus_t DiagStatus; + rndis_ErrorOffset_t ErrorOffset; + }rndis_diagnostic_info_t; + +/*** Remote NDIS Keepalive Message */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + }rndis_keepalive_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_keepalive_cmplt_t; + +/*** Remote NDIS Data Packet ***/ + +typedef uint32_t rndis_DataOffset_t; +typedef uint32_t rndis_DataLength_t; +typedef uint32_t rndis_OOBDataOffset_t; +typedef uint32_t rndis_OOBDataLength_t; +typedef uint32_t rndis_NumOOBDataElements_t; +typedef uint32_t rndis_PerPacketInfoOffset_t; +typedef uint32_t rndis_PerPacketInfoLength_t; + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_DataOffset_t DataOffset; + rndis_DataLength_t DataLength; + rndis_OOBDataOffset_t OOBDataOffset; + rndis_OOBDataLength_t OOBDataLength; + rndis_NumOOBDataElements_t NumOOBDataElements; + rndis_PerPacketInfoOffset_t PerPacketInfoOffset; + rndis_PerPacketInfoLength_t PerPacketInfoLength; + rndis_DeviceVcHandle_t DeviceVcHandle; + rndis_Reserved_t Reserved; + }rndis_data_packet_t; + +typedef uint32_t rndis_ClassInformationOffset_t; +typedef uint32_t rndis_Size_t; +typedef uint32_t rndis_Type_t; + +typedef struct{ + rndis_Size_t Size; + rndis_Type_t Type; + rndis_ClassInformationOffset_t ClassInformationType; + }rndis_OOB_packet_t; + +#include "ndis.h" + +typedef enum rnids_state_e { + rndis_uninitialized, + rndis_initialized, + rndis_data_initialized + } rndis_state_t; + +typedef struct { + uint32_t txok; + uint32_t rxok; + uint32_t txbad; + uint32_t rxbad; +} usb_eth_stat_t; + +#endif /* _RNDIS_H */ + +/** @} */ diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c new file mode 100644 index 000000000..535bdf851 --- /dev/null +++ b/lib/networking/rndis_reports.c @@ -0,0 +1,303 @@ +/* + The original version of this code was lrndis/usbd_rndis_core.c from https://github.com/fetisov/lrndis + It has since been overhauled to suit this application +*/ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +#include +#include +#include "class/net/net_device.h" +#include "rndis_protocol.h" +#include "netif/ethernet.h" + +#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ +#define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ + +static const uint8_t *const station_hwaddr = network_mac_address; +static const uint8_t *const permanent_hwaddr = network_mac_address; + +static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; +static uint32_t oid_packet_filter = 0x0000000; +static rndis_state_t rndis_state; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + +static const uint32_t OIDSupportedList[] = +{ + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_MAC_OPTIONS, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_MAC_OPTIONS +}; + +#define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) +#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) + +static uint8_t *encapsulated_buffer; + +static void rndis_report(void) +{ + netd_report(ndis_report, sizeof(ndis_report)); +} + +static void rndis_query_cmplt32(int status, uint32_t data) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + 4; + c->InformationBufferLength = 4; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, &data, sizeof(data)); + rndis_report(); +} + +static void rndis_query_cmplt(int status, const void *data, int size) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + size; + c->InformationBufferLength = size; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, data, size); + rndis_report(); +} + +#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \ + NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \ + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \ + NDIS_MAC_OPTION_NO_LOOPBACK + +static const char *rndis_vendor = RNDIS_VENDOR; + +static void rndis_query(void) +{ + switch (((rndis_query_msg_t *)encapsulated_buffer)->Oid) + { + case OID_GEN_SUPPORTED_LIST: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return; + case OID_GEN_VENDOR_DRIVER_VERSION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00001000); return; + case OID_802_3_CURRENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, &station_hwaddr, 6); return; + case OID_802_3_PERMANENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, &permanent_hwaddr, 6); return; + case OID_GEN_MEDIA_SUPPORTED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_MEDIA_IN_USE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_PHYSICAL_MEDIUM: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_HARDWARE_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_LINK_SPEED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return; + case OID_GEN_VENDOR_ID: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return; + case OID_GEN_VENDOR_DESCRIPTION: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return; + case OID_GEN_CURRENT_PACKET_FILTER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, oid_packet_filter); return; + case OID_GEN_MAXIMUM_FRAME_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU - SIZEOF_ETH_HDR); return; + case OID_GEN_MAXIMUM_TOTAL_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_TRANSMIT_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_RECEIVE_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_MEDIA_CONNECT_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIA_STATE_CONNECTED); return; + case OID_GEN_RNDIS_CONFIG_PARAMETER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_MAXIMUM_LIST_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 1); return; + case OID_802_3_MULTICAST_LIST: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_802_3_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_GEN_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, /*MAC_OPT*/ 0); return; + case OID_802_3_RCV_ERROR_ALIGNMENT: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_ONE_COLLISION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_MORE_COLLISIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_XMIT_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txok); return; + case OID_GEN_RCV_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxok); return; + case OID_GEN_RCV_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxbad); return; + case OID_GEN_XMIT_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txbad); return; + case OID_GEN_RCV_NO_BUFFER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + default: rndis_query_cmplt(RNDIS_STATUS_FAILURE, NULL, 0); return; + } +} + +#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset)) + +static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) +{ + (void)data; + (void)keyoffset; + (void)valoffset; + (void)keylen; + (void)vallen; +} + +static void rndis_packetFilter(uint32_t newfilter) +{ + (void)newfilter; +} + +static void rndis_handle_set_msg(void) +{ + rndis_set_cmplt_t *c; + rndis_set_msg_t *m; + rndis_Oid_t oid; + + c = (rndis_set_cmplt_t *)encapsulated_buffer; + m = (rndis_set_msg_t *)encapsulated_buffer; + + oid = m->Oid; + c->MessageType = REMOTE_NDIS_SET_CMPLT; + c->MessageLength = sizeof(rndis_set_cmplt_t); + c->Status = RNDIS_STATUS_SUCCESS; + + switch (oid) + { + /* Parameters set up in 'Advanced' tab */ + case OID_GEN_RNDIS_CONFIG_PARAMETER: + { + rndis_config_parameter_t *p; + char *ptr = (char *)m; + ptr += sizeof(rndis_generic_msg_t); + ptr += m->InformationBufferOffset; + p = (rndis_config_parameter_t *)ptr; + rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); + } + break; + + /* Mandatory general OIDs */ + case OID_GEN_CURRENT_PACKET_FILTER: + oid_packet_filter = *INFBUF; + if (oid_packet_filter) + { + rndis_packetFilter(oid_packet_filter); + rndis_state = rndis_data_initialized; + } + else + { + rndis_state = rndis_initialized; + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + break; + + case OID_GEN_PROTOCOL_OPTIONS: + break; + + /* Mandatory 802_3 OIDs */ + case OID_802_3_MULTICAST_LIST: + break; + + /* Power Managment: fails for now */ + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + case OID_PNP_ENABLE_WAKE_UP: + default: + c->Status = RNDIS_STATUS_FAILURE; + break; + } + + /* c->MessageID is same as before */ + rndis_report(); + return; +} + +void rndis_class_set_handler(uint8_t *data, int size) +{ + encapsulated_buffer = data; + (void)size; + + switch (((rndis_generic_msg_t *)data)->MessageType) + { + case REMOTE_NDIS_INITIALIZE_MSG: + { + rndis_initialize_cmplt_t *m; + m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); + /* m->MessageID is same as before */ + m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; + m->MessageLength = sizeof(rndis_initialize_cmplt_t); + m->MajorVersion = RNDIS_MAJOR_VERSION; + m->MinorVersion = RNDIS_MINOR_VERSION; + m->Status = RNDIS_STATUS_SUCCESS; + m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; + m->Medium = RNDIS_MEDIUM_802_3; + m->MaxPacketsPerTransfer = 1; + m->MaxTransferSize = CFG_TUD_NET_MTU + sizeof(rndis_data_packet_t); + m->PacketAlignmentFactor = 0; + m->AfListOffset = 0; + m->AfListSize = 0; + rndis_state = rndis_initialized; + rndis_report(); + } + break; + + case REMOTE_NDIS_QUERY_MSG: + rndis_query(); + break; + + case REMOTE_NDIS_SET_MSG: + rndis_handle_set_msg(); + break; + + case REMOTE_NDIS_RESET_MSG: + { + rndis_reset_cmplt_t * m; + m = ((rndis_reset_cmplt_t *)encapsulated_buffer); + rndis_state = rndis_uninitialized; + m->MessageType = REMOTE_NDIS_RESET_CMPLT; + m->MessageLength = sizeof(rndis_reset_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + m->AddressingReset = 1; /* Make it look like we did something */ + /* m->AddressingReset = 0; - Windows halts if set to 1 for some reason */ + rndis_report(); + } + break; + + case REMOTE_NDIS_KEEPALIVE_MSG: + { + rndis_keepalive_cmplt_t * m; + m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; + m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; + m->MessageLength = sizeof(rndis_keepalive_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + } + /* We have data to send back */ + rndis_report(); + break; + + default: + break; + } +} diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c new file mode 100644 index 000000000..422d435c6 --- /dev/null +++ b/src/class/net/net_device.c @@ -0,0 +1,345 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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_NET != OPT_NET_NONE) ) + +#include "net_device.h" +#include "device/usbd_pvt.h" +#include "rndis_protocol.h" + +void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; +} netd_interface_t; + +#if CFG_TUD_NET == OPT_NET_ECM + #define CFG_TUD_NET_PACKET_PREFIX_LEN 0 + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 + #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL +#elif CFG_TUD_NET == OPT_NET_RNDIS + #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 + #define CFG_TUD_NET_INTERFACESUBCLASS TUD_RNDIS_ITF_SUBCLASS +#elif CFG_TUD_NET == OPT_NET_EEM + #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 + #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL +#endif + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; + +#if CFG_TUD_NET == OPT_NET_RNDIS + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[128]; +#endif + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; + +static bool can_xmit; + +void network_recv_renew(void) +{ + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); +} + +static void do_in_xfer(uint8_t *buf, uint16_t len) +{ + can_xmit = false; + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_in, buf, len); +} + +void netd_report(uint8_t *buf, uint16_t len) +{ + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void netd_init(void) +{ + tu_memclr(&_netd_itf, sizeof(_netd_itf)); +} + +void netd_reset(uint8_t rhport) +{ + (void) rhport; + + netd_init(); +} + +bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + // sanity check the descriptor + TU_ASSERT (CFG_TUD_NET_INTERFACESUBCLASS == itf_desc->bInterfaceSubClass); + + // confirm interface hasn't already been allocated + TU_ASSERT(0 == _netd_itf.ep_in); + + //------------- first Interface -------------// + _netd_itf.itf_num = itf_desc->bInterfaceNumber; + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + (*p_length) = sizeof(tusb_desc_interface_t); + +#if CFG_TUD_NET != OPT_NET_EEM + // Communication Functional Descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + { + (*p_length) += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // notification endpoint (if any) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + + _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + (*p_length) += p_desc[DESC_OFFSET_LEN]; + p_desc = tu_desc_next(p_desc); + } + + //------------- second Interface -------------// + if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + { + // next to endpoint descriptor + p_desc = tu_desc_next(p_desc); + (*p_length) += sizeof(tusb_desc_interface_t); + } +#endif + + if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + { + // Open endpoint pair + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + (*p_length) += 2*sizeof(tusb_desc_endpoint_t); + } + + network_init_callback(); + + // we are ready to transmit a packet + can_xmit = true; + + // prepare for incoming packets + network_recv_renew(); + + return true; +} + +// Invoked when class request DATA stage is finished. +// return false to stall control endpoint (e.g Host send nonsense DATA) +bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + // Handle class request only + TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + +#if CFG_TUD_NET == OPT_NET_RNDIS + if (request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + rndis_class_set_handler(rndis_buf, request->wLength); + } +#endif + + return true; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) +{ + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + +#if CFG_TUD_NET == OPT_NET_RNDIS + tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); +#else + (void)rhport; +#endif + + return true; +} + +struct cdc_eem_packet_header +{ + uint16_t length:14; + uint16_t bmCRC:1; + uint16_t bmType:1; +}; + +static void handle_incoming_packet(uint32_t len) +{ + uint8_t *pnt = received; + uint32_t size = 0; + +#if CFG_TUD_NET == OPT_NET_ECM + size = len; +#elif CFG_TUD_NET == OPT_NET_RNDIS + rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; + if (len >= sizeof(rndis_data_packet_t)) + if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) + if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) + { + pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; + size = r->DataLength; + } +#elif CFG_TUD_NET == OPT_NET_EEM + struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; + + (void)len; + + if (hdr->bmType) + { + /* EEM Control Packet: discard it */ + network_recv_renew(); + } + else + { + /* EEM Data Packet */ + pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; + size = hdr->length - 4; /* discard the unused CRC-32 */ + } +#endif + + if (size) + { + struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); + bool accepted = true; + + if (p) + { + memcpy(p->payload, pnt, size); + p->len = size; + accepted = network_recv_callback(p); + } + + if (!p || !accepted) + { + /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */ + network_recv_renew(); + } + } +} + +bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) result; + + /* new packet received */ + if ( ep_addr == _netd_itf.ep_out ) + { + handle_incoming_packet(xferred_bytes); + } + + /* data transmission finished */ + if ( ep_addr == _netd_itf.ep_in ) + { + /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ + + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) + { + do_in_xfer(NULL, 0); /* a ZLP is needed */ + } + else + { + /* we're finally finished */ + can_xmit = true; + } + } + + return true; +} + +bool network_can_xmit(void) +{ + return can_xmit; +} + +void network_xmit(struct pbuf *p) +{ + struct pbuf *q; + uint8_t *data; + uint16_t len; + + if (!can_xmit) + return; + + len = CFG_TUD_NET_PACKET_PREFIX_LEN; + data = transmitted + len; + + for(q = p; q != NULL; q = q->next) + { + memcpy(data, (char *)q->payload, q->len); + data += q->len; + len += q->len; + } + +#if CFG_TUD_NET == OPT_NET_RNDIS + rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); + hdr->DataLength = len - sizeof(rndis_data_packet_t); +#elif CFG_TUD_NET == OPT_NET_EEM + struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted; + /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */ + data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; + /* adjust length to reflect added fake CRC-32 */ + len += 4; + hdr->bmType = 0; /* EEM Data Packet */ + hdr->length = len - sizeof(struct cdc_eem_packet_header); + hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */ +#endif + + do_in_xfer(transmitted, len); +} + +#endif diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h new file mode 100644 index 000000000..c61efc86c --- /dev/null +++ b/src/class/net/net_device.h @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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_NET_DEVICE_H_ +#define _TUSB_NET_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "class/cdc/cdc.h" +#include "lwip/pbuf.h" +#include "netif/ethernet.h" + +/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ +#define CFG_TUD_NET_ENDPOINT_SIZE ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) + +/* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ +#define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR) + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// client must provide this: initialize any network state back to the beginning +void network_init_callback(void); + +// client must provide this: return false if the packet buffer was not accepted +bool network_recv_callback(struct pbuf *p); + +// client must provide this: 48-bit MAC address +extern const uint8_t network_mac_address[6]; + +// indicate to network driver that client has finished with the packet provided to network_recv_callback() +void network_recv_renew(void); + +// poll network driver for its ability to accept another packet to transmit +bool network_can_xmit(void); + +// if network_can_xmit() returns true, network_xmit() can be called once +void network_xmit(struct pbuf *p); + +//--------------------------------------------------------------------+ +// INTERNAL USBD-CLASS DRIVER API +//--------------------------------------------------------------------+ +void netd_init (void); +void netd_reset (uint8_t rhport); +bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 68c5c5160..32a89889e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -181,6 +181,24 @@ static usbd_class_driver_t const _usbd_driver[] = .sof = NULL }, #endif + + #if CFG_TUD_NET + { + .class_code = +#if CFG_TUD_NET == OPT_NET_RNDIS + TUD_RNDIS_ITF_CLASS, +#else + TUSB_CLASS_CDC, +#endif + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_request = netd_control_request, + .control_complete = netd_control_complete, + .xfer_cb = netd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index d80abf17c..07163a013 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -326,6 +326,90 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +//------------- CDC-ECM -------------// + +// Length of template descriptor: 62 bytes +#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+7+7) + +// CDC-ECM Descriptor Template +// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. +#define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-ECM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + +//------------- RNDIS -------------// + +#if 0 + /* Windows XP */ + #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC + #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL + #define TUD_RNDIS_ITF_PROTOCOL CDC_COMM_PROTOCOL_MICROSOFT_RNDIS +#else + /* Windows 7+ */ + #define TUD_RNDIS_ITF_CLASS 0xE0 + #define TUD_RNDIS_ITF_SUBCLASS 0x01 + #define TUD_RNDIS_ITF_PROTOCOL 0x03 +#endif + +// Length of template descriptor: 66 bytes +#define TUD_RNDIS_DESC_LEN (8+9+5+5+4+5+7+9+7+7) + +// RNDIS Descriptor Template +// Interface number, string index, EP notification address and size, EP data address (out, in) and size. +#define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + +//------------- CDC-EEM -------------// + +// Length of template descriptor: 23 bytes +#define TUD_CDC_EEM_DESC_LEN (9+7+7) + +// CDC-EEM Descriptor Template +// Interface number, description string index, EP data address (out, in) and size. +#define TUD_CDC_EEM_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ + /* EEM Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL, CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL, _stridx,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + #ifdef __cplusplus } #endif diff --git a/src/tusb.h b/src/tusb.h index 7dcddf645..55c105121 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -91,6 +91,10 @@ #if CFG_TUD_DFU_RT #include "class/dfu/dfu_rt_device.h" #endif + + #if CFG_TUD_NET + #include "class/net/net_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 97f14532f..00d4a39dc 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -117,6 +117,15 @@ #define OPT_MODE_HIGH_SPEED 0x10 ///< High speed /** @} */ +/** \defgroup group_supported_netif Supported Network Interface + * \ref CFG_TUD_NET must be defined to one of these + * @{ */ +#define OPT_NET_NONE 0 ///< No network interface +#define OPT_NET_ECM 1 ///< CDC-ECM +#define OPT_NET_RNDIS 2 ///< RNDIS +#define OPT_NET_EEM 3 ///< CDC-EEM +/** @} */ + #ifndef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif @@ -204,6 +213,9 @@ #define CFG_TUD_DFU_RT 0 #endif +#ifndef CFG_TUD_NET + #define CFG_TUD_NET 0 +#endif //-------------------------------------------------------------------- // HOST OPTIONS -- cgit v1.3.1 From 7aa5a53652270a06dc60e6293393755350bf7c85 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 8 Mar 2020 13:26:36 +0700 Subject: fix log printf --- src/device/usbd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 32a89889e..335c68e8e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -264,6 +264,9 @@ static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] = #if CFG_TUD_USBTMC "USBTMC" #endif + #if CFG_TUD_NET + "NET" + #endif }; static char const* const _tusb_std_request_str[] = -- cgit v1.3.1 From c8247f0907040eb86c301e8bff8bb322fc9cb566 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 8 Mar 2020 14:20:28 +0700 Subject: fix zlp for nrf52840 --- src/device/usbd_control.c | 6 ++++-- src/portable/nordic/nrf5x/dcd_nrf5x.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 5a0ba412f..f0a4cf84a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -96,6 +96,8 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } + TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\n", ep_addr, xact_len); + return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -110,10 +112,10 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo { TU_ASSERT(buffer); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); + // Data stage TU_ASSERT( _data_stage_xact(rhport) ); - - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); }else { // Status stage diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 59c2f36aa..2ce288d6c 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -276,8 +276,10 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->actual_len = 0; - // Control endpoint with zero-length packet --> status stage - if ( epnum == 0 && total_bytes == 0 ) + // Control endpoint with zero-length packet and opposite direction to 1st request byte --> status stage + bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE)); + + if ( control_status ) { // Status Phase also require Easy DMA has to be free as well !!!! edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS); -- cgit v1.3.1 From 7f6316dbe1c98d2f00ded0913176a85e871353fa Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Mar 2020 14:22:08 -0400 Subject: Use CRLF on UART. --- examples/device/board_test/src/main.c | 2 +- src/class/cdc/cdc_device.c | 6 +++--- src/class/msc/msc_device.c | 6 +++--- src/common/tusb_common.h | 2 +- src/common/tusb_verify.h | 4 ++-- src/device/usbd_control.c | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index 865821745..584ff799d 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -42,7 +42,7 @@ enum { BLINK_UNPRESSED = 1000 }; -#define HELLO_STR "Hello from TinyUSB\n" +#define HELLO_STR "Hello from TinyUSB\r\n" int main(void) { diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f63418dae..14b9a3153 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -335,12 +335,12 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: - TU_LOG2(" Set Line Coding\n"); + TU_LOG2(" Set Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_GET_LINE_CODING: - TU_LOG2(" Get Line Coding\n"); + TU_LOG2(" Get Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; @@ -356,7 +356,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request p_cdc->line_state = (uint8_t) request->wValue; - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\n", dtr, rts); + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); tud_control_status(rhport, request); diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3ff0eba92..06cc9dbb6 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -407,7 +407,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + TU_LOG2(" SCSI Command: %s\r\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; @@ -480,7 +480,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_DATA: - TU_LOG2(" SCSI Data\n"); + TU_LOG2(" SCSI Data\r\n"); //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2); // OUT transfer, invoke callback if needed @@ -577,7 +577,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG2(" SCSI Status: %u\n", p_csw->status); + TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); // TU_LOG2_MEM(p_csw, xferred_bytes, 2); // Move to default CMD stage diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 5e6a8bb10..ef232a593 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -222,7 +222,7 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); // Log with debug level 1 #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem -#define TU_LOG1_LOCATION() tu_printf("%s: %d:\n", __PRETTY_FUNCTION__, __LINE__) +#define TU_LOG1_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) // Log with debug level 2 #if CFG_TUSB_DEBUG > 1 diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 1ad6d3fb0..74150d6c5 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -76,8 +76,8 @@ #if CFG_TUSB_DEBUG #include - #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\n", __func__, __LINE__, tusb_strerr[_err]) - #define _MESS_FAILED() printf("%s %d: assert failed\n", __func__, __LINE__) + #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) + #define _MESS_FAILED() printf("%s %d: assert failed\r\n", __func__, __LINE__) #else #define _MESS_ERR(_err) #define _MESS_FAILED() diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f0a4cf84a..7c35fe768 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -63,7 +63,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", ep_addr, 0); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, 0); // status direction is reversed to one in the setup packet // Note: Status must always be DATA1 @@ -96,7 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\n", ep_addr, xact_len); + TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\r\n", ep_addr, xact_len); return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -112,7 +112,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo { TU_ASSERT(buffer); - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); -- cgit v1.3.1 From 6606cf289661909cfe238787bef7b91112d40f0d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 27 Mar 2020 15:30:40 -0400 Subject: USBD: Use tud_control_xfer only for data --- src/device/usbd_control.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 4fd40c440..c61606f18 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -101,22 +101,29 @@ static bool _data_stage_xact(uint8_t rhport) return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } +// Transmit data to/from the control endpoint. +// +// If the request's wLength is zero, a status packet is sent instead. bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) { _ctrl_xfer.request = (*request); _ctrl_xfer.buffer = (uint8_t*) buffer; - _ctrl_xfer.total_xferred = 0; + _ctrl_xfer.total_xferred = 0U; _ctrl_xfer.data_len = tu_min16(len, request->wLength); - - if ( _ctrl_xfer.data_len ) + + if (request->wLength > 0U) { - TU_ASSERT(buffer); + if(_ctrl_xfer.data_len > 0U) + { + TU_ASSERT(buffer); + } TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); - }else + } + else { // Status stage TU_ASSERT( _status_stage_xact(rhport, request) ); -- cgit v1.3.1 From 87f313da48aa1df4fb0566d9ad26036f06418422 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 30 Mar 2020 13:34:56 -0500 Subject: add provision for multiple configurations --- examples/device/cdc_dual_ports/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc_freertos/src/usb_descriptors.c | 4 ++-- examples/device/dfu_rt/src/usb_descriptors.c | 4 ++-- examples/device/hid_composite/src/usb_descriptors.c | 4 ++-- examples/device/hid_generic_inout/src/usb_descriptors.c | 4 ++-- examples/device/midi_test/src/usb_descriptors.c | 4 ++-- examples/device/msc_dual_lun/src/usb_descriptors.c | 4 ++-- examples/device/net_lwip_webserver/src/usb_descriptors.c | 4 ++-- examples/device/usbtmc/src/usb_descriptors.c | 4 ++-- examples/device/webusb_serial/src/usb_descriptors.c | 4 ++-- src/device/usbd.h | 6 +++--- test/test/device/msc/test_msc_device.c | 4 ++-- test/test/device/usbd/test_usbd.c | 8 ++++---- 14 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src/device') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index 1b1d171b1..b59f55d1b 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -93,8 +93,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 127008227..373928e2f 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 127008227..373928e2f 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/dfu_rt/src/usb_descriptors.c b/examples/device/dfu_rt/src/usb_descriptors.c index 17b3fe87d..f96684b91 100644 --- a/examples/device/dfu_rt/src/usb_descriptors.c +++ b/examples/device/dfu_rt/src/usb_descriptors.c @@ -141,8 +141,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 19689c90b..a75bc5274 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -101,8 +101,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 87611a432..8adb336a0 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -99,8 +99,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 949404826..3c2848e56 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -90,8 +90,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP Out & EP In address, EP size TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index 3b2615fd4..90f7083d2 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -98,8 +98,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index a4eba205f..e398a5d4b 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -107,8 +107,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100, 1), #if CFG_TUD_NET == OPT_NET_ECM // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 92b1dce61..e22665706 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -165,8 +165,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index 2925a66c4..386ca7458 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -95,8 +95,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/src/device/usbd.h b/src/device/usbd.h index 07163a013..71829322b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -156,9 +156,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- Configuration -------------// #define TUD_CONFIG_DESC_LEN (9) -// Interface count, string index, total length, attribute, power in mA -#define TUD_CONFIG_DESCRIPTOR(_itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, 1, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 +// Interface count, string index, total length, attribute, power in mA, config number +#define TUD_CONFIG_DESCRIPTOR(_itfcount, _stridx, _total_len, _attribute, _power_ma, config_num) \ + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 43a8e7438..8f807183f 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -62,8 +62,8 @@ enum uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EDPT_MSC_OUT, EDPT_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index af30aaf8f..96afd8b43 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -73,8 +73,8 @@ tusb_desc_device_t const data_desc_device = uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), }; tusb_control_request_t const req_get_desc_device = @@ -211,8 +211,8 @@ void test_usbd_control_in_zlp(void) // ZLP must be return uint8_t zlp_desc_configuration[CFG_TUD_ENDOINT0_SIZE*2] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), }; desc_configuration = zlp_desc_configuration; -- cgit v1.3.1 From 794212d44e38a05d8b747e43942595d214ee5b0b Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 31 Mar 2020 10:53:47 -0500 Subject: revise argument order for TUD_CONFIG_DESCRIPTOR macro --- examples/device/cdc_dual_ports/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc_freertos/src/usb_descriptors.c | 4 ++-- examples/device/dfu_rt/src/usb_descriptors.c | 4 ++-- examples/device/hid_composite/src/usb_descriptors.c | 4 ++-- examples/device/hid_generic_inout/src/usb_descriptors.c | 4 ++-- examples/device/midi_test/src/usb_descriptors.c | 4 ++-- examples/device/msc_dual_lun/src/usb_descriptors.c | 4 ++-- examples/device/net_lwip_webserver/src/usb_descriptors.c | 4 ++-- examples/device/usbtmc/src/usb_descriptors.c | 4 ++-- examples/device/webusb_serial/src/usb_descriptors.c | 4 ++-- src/device/usbd.h | 4 ++-- test/test/device/msc/test_msc_device.c | 4 ++-- test/test/device/usbd/test_usbd.c | 8 ++++---- 14 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src/device') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index b59f55d1b..03800d693 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -93,8 +93,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 373928e2f..7b22d46a7 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 373928e2f..7b22d46a7 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/dfu_rt/src/usb_descriptors.c b/examples/device/dfu_rt/src/usb_descriptors.c index f96684b91..5cd661b2b 100644 --- a/examples/device/dfu_rt/src/usb_descriptors.c +++ b/examples/device/dfu_rt/src/usb_descriptors.c @@ -141,8 +141,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index a75bc5274..6bde2ff7a 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -101,8 +101,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 8adb336a0..5c769c9c9 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -99,8 +99,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 3c2848e56..72ab1416c 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -90,8 +90,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index 90f7083d2..9128c4f75 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -98,8 +98,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index e398a5d4b..6ce36cfef 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -107,8 +107,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), #if CFG_TUD_NET == OPT_NET_ECM // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index e22665706..675140260 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -165,8 +165,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index 386ca7458..1a2df76ca 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -95,8 +95,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/src/device/usbd.h b/src/device/usbd.h index 71829322b..beeec7e1c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -156,8 +156,8 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- Configuration -------------// #define TUD_CONFIG_DESC_LEN (9) -// Interface count, string index, total length, attribute, power in mA, config number -#define TUD_CONFIG_DESCRIPTOR(_itfcount, _stridx, _total_len, _attribute, _power_ma, config_num) \ +// Config number, interface count, string index, total length, attribute, power in mA +#define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 8f807183f..095c28170 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -62,8 +62,8 @@ enum uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EDPT_MSC_OUT, EDPT_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index 96afd8b43..06372b2e4 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -73,8 +73,8 @@ tusb_desc_device_t const data_desc_device = uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), }; tusb_control_request_t const req_get_desc_device = @@ -211,8 +211,8 @@ void test_usbd_control_in_zlp(void) // ZLP must be return uint8_t zlp_desc_configuration[CFG_TUD_ENDOINT0_SIZE*2] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), }; desc_configuration = zlp_desc_configuration; -- cgit v1.3.1 From 2d6d298302be2d39374c36e7889341dee944d542 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 14:11:45 +0700 Subject: move irqhandler to application tud_isr() must be called by application to forward the irqhandle to the stack --- examples/device/board_test/Makefile | 6 +++ .../circuitplayground_express.c | 10 ++++ hw/bsp/ea4088qs/ea4088qs.c | 32 +++++++------ hw/bsp/feather_m0_express/feather_m0_express.c | 8 ++++ hw/bsp/feather_m4_express/feather_m4_express.c | 23 +++++++++ .../feather_nrf52840_express.c | 1 + hw/bsp/itsybitsy_m0/itsybitsy_m0.c | 8 ++++ hw/bsp/itsybitsy_m4/itsybitsy_m4.c | 23 +++++++++ hw/bsp/metro_m0_express/metro_m0_express.c | 8 ++++ hw/bsp/metro_m4_express/metro_m4_express.c | 23 +++++++++ hw/bsp/seeeduino_xiao/seeeduino_xiao.c | 8 ++++ src/device/dcd.h | 2 +- src/portable/microchip/samd/dcd_samd.c | 54 +--------------------- 13 files changed, 138 insertions(+), 68 deletions(-) (limited to 'src/device') diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index 5a455078e..ce34c7ccd 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -9,4 +9,10 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +# board_test example is special example that doesn't enable device or host stack +# This can cause some TinyUSB API missing, this hack to allow us to fill those API +# to pass the compilation process +CFLAGS += \ + -D"tud_isr(x)= " \ + include ../../rules.mk diff --git a/hw/bsp/circuitplayground_express/circuitplayground_express.c b/hw/bsp/circuitplayground_express/circuitplayground_express.c index cdd75580a..5ddf1c624 100644 --- a/hw/bsp/circuitplayground_express/circuitplayground_express.c +++ b/hw/bsp/circuitplayground_express/circuitplayground_express.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -134,6 +142,7 @@ int board_uart_write(void const * buf, int len) } #if CFG_TUSB_OS == OPT_OS_NONE + volatile uint32_t system_ticks = 0; void SysTick_Handler (void) { @@ -144,4 +153,5 @@ uint32_t board_millis(void) { return system_ticks; } + #endif diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 83b2d6b1e..3d4ce0367 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -27,6 +27,23 @@ #include "chip.h" #include "../board.h" +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST + tuh_isr(0); + #endif + + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE + tud_isr(0); + #endif +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ #define LED_PORT 2 #define LED_PIN 19 @@ -113,21 +130,6 @@ void board_init(void) LPC_USB->StCtrl = 0x3; } -//--------------------------------------------------------------------+ -// USB Interrupt Handler -//--------------------------------------------------------------------+ -void USB_IRQHandler(void) -{ - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); - #endif - - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); - #endif -} - - //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_m0_express/feather_m0_express.c b/hw/bsp/feather_m0_express/feather_m0_express.c index df81940f2..b373b829e 100644 --- a/hw/bsp/feather_m0_express/feather_m0_express.c +++ b/hw/bsp/feather_m0_express/feather_m0_express.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_m4_express/feather_m4_express.c b/hw/bsp/feather_m4_express/feather_m4_express.c index 60939c99b..be8cc810b 100644 --- a/hw/bsp/feather_m4_express/feather_m4_express.c +++ b/hw/bsp/feather_m4_express/feather_m4_express.c @@ -32,6 +32,29 @@ #include "hpl/gclk/hpl_gclk_base.h" #include "hpl_mclk_config.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler (void) +{ + tud_isr(0); +} + +void USB_1_Handler (void) +{ + tud_isr(0); +} + +void USB_2_Handler (void) +{ + tud_isr(0); +} + +void USB_3_Handler (void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c index 5dc3a4c40..a790b125d 100644 --- a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c +++ b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c @@ -92,6 +92,7 @@ void board_init(void) nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler); + //------------- USB -------------// #if TUSB_OPT_DEVICE_ENABLED // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice // 2 is highest for application diff --git a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c index dd7d4da04..ba31493ee 100644 --- a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c +++ b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c index 43432d3e3..0b9cc89e0 100644 --- a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c +++ b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c @@ -32,6 +32,29 @@ #include "hpl/gclk/hpl_gclk_base.h" #include "hpl_mclk_config.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler (void) +{ + tud_isr(0); +} + +void USB_1_Handler (void) +{ + tud_isr(0); +} + +void USB_2_Handler (void) +{ + tud_isr(0); +} + +void USB_3_Handler (void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m0_express/metro_m0_express.c b/hw/bsp/metro_m0_express/metro_m0_express.c index df81940f2..b373b829e 100644 --- a/hw/bsp/metro_m0_express/metro_m0_express.c +++ b/hw/bsp/metro_m0_express/metro_m0_express.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m4_express/metro_m4_express.c b/hw/bsp/metro_m4_express/metro_m4_express.c index 11a95b408..c735fa64d 100644 --- a/hw/bsp/metro_m4_express/metro_m4_express.c +++ b/hw/bsp/metro_m4_express/metro_m4_express.c @@ -32,6 +32,29 @@ #include "hpl/gclk/hpl_gclk_base.h" #include "hpl_mclk_config.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler (void) +{ + tud_isr(0); +} + +void USB_1_Handler (void) +{ + tud_isr(0); +} + +void USB_2_Handler (void) +{ + tud_isr(0); +} + +void USB_3_Handler (void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c index a3602d66e..799c56261 100644 --- a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c +++ b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/src/device/dcd.h b/src/device/dcd.h index 143a2de34..5e1181d1b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_isr (uint8_t rhport); +void dcd_isr (uint8_t rhport) TU_ATTR_USED; // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 148995520..9f91e3f96 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -324,7 +324,7 @@ void dcd_isr (uint8_t rhport) uint32_t int_status = USB->DEVICE.INTFLAG.reg & USB->DEVICE.INTENSET.reg; - /*------------- Interrupt Processing -------------*/ + // Start of Frame if ( int_status & USB_DEVICE_INTFLAG_SOF ) { USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; @@ -357,6 +357,7 @@ void dcd_isr (uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } + // Enable of Reset if ( int_status & USB_DEVICE_INTFLAG_EORST ) { USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; @@ -381,55 +382,4 @@ void dcd_isr (uint8_t rhport) maybe_transfer_complete(); } -#if CFG_TUSB_MCU == OPT_MCU_SAMD51 - -/* - *------------------------------------------------------------------*/ -/* USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, -USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, -USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, -USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, -USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, -USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, -USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, -USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, -USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, -USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, -USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, -USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, -USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, -USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */ -void USB_0_Handler(void) { - dcd_isr(0); -} - -/* USB_SOF_HSOF */ -void USB_1_Handler(void) { - dcd_isr(0); -} - -// Bank zero is for OUT and SETUP transactions. -/* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, -USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, -USB_TRCPT0_6, USB_TRCPT0_7 */ -void USB_2_Handler(void) { - dcd_isr(0); -} - -// Bank one is used for IN transactions. -/* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, -USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, -USB_TRCPT1_6, USB_TRCPT1_7 */ -void USB_3_Handler(void) { - dcd_isr(0); -} - -#elif CFG_TUSB_MCU == OPT_MCU_SAMD21 - -void USB_Handler(void) { - dcd_isr(0); -} - -#endif - #endif -- cgit v1.3.1 From c026236824e95d9409136cd48481b69e2cea56dc Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 16:33:04 +0700 Subject: house keeping --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index ddd99d7f1..125aa351c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -421,7 +421,7 @@ void tud_task (void) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Endpoint: 0x%02X, Bytes: %ld\r\n", ep_addr, event.xfer_complete.len); + TU_LOG2(" Endpoint: 0x%02X, Bytes: %lu\r\n", ep_addr, event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; -- cgit v1.3.1 From dc4bf02dcb8198c9647e13bc0f5b4e5fcdeef618 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 17:04:49 +0700 Subject: mass rename tud_isr to tud_irq_handler --- examples/device/board_test/Makefile | 2 +- hw/bsp/circuitplayground_express/circuitplayground_express.c | 2 +- hw/bsp/ea4088qs/ea4088qs.c | 2 +- hw/bsp/ea4357/ea4357.c | 4 ++-- hw/bsp/feather_m0_express/feather_m0_express.c | 2 +- hw/bsp/feather_m4_express/feather_m4_express.c | 8 ++++---- hw/bsp/itsybitsy_m0/itsybitsy_m0.c | 2 +- hw/bsp/itsybitsy_m4/itsybitsy_m4.c | 8 ++++---- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/mbed1768/mbed1768.c | 2 +- hw/bsp/mcb1800/mcb1800.c | 4 ++-- hw/bsp/metro_m0_express/metro_m0_express.c | 2 +- hw/bsp/metro_m4_express/metro_m4_express.c | 8 ++++---- hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c | 2 +- hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c | 2 +- hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c | 2 +- hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c | 4 ++-- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 4 ++-- hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c | 4 ++-- hw/bsp/ngx4330/ngx4330.c | 4 ++-- hw/bsp/samg55xplained/samg55xplained.c | 2 +- hw/bsp/seeeduino_xiao/seeeduino_xiao.c | 2 +- hw/bsp/teensy_40/teensy40.c | 4 ++-- src/device/usbd.h | 2 +- 24 files changed, 40 insertions(+), 40 deletions(-) (limited to 'src/device') diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index ce34c7ccd..66d8571cf 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -13,6 +13,6 @@ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) # This can cause some TinyUSB API missing, this hack to allow us to fill those API # to pass the compilation process CFLAGS += \ - -D"tud_isr(x)= " \ + -D"tud_irq_handler(x)= " \ include ../../rules.mk diff --git a/hw/bsp/circuitplayground_express/circuitplayground_express.c b/hw/bsp/circuitplayground_express/circuitplayground_express.c index 5ddf1c624..0e2583383 100644 --- a/hw/bsp/circuitplayground_express/circuitplayground_express.c +++ b/hw/bsp/circuitplayground_express/circuitplayground_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 3d4ce0367..756c9d384 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -37,7 +37,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index f5d2a199e..87b19260e 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -240,7 +240,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -251,7 +251,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/feather_m0_express/feather_m0_express.c b/hw/bsp/feather_m0_express/feather_m0_express.c index b373b829e..83b20793e 100644 --- a/hw/bsp/feather_m0_express/feather_m0_express.c +++ b/hw/bsp/feather_m0_express/feather_m0_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_m4_express/feather_m4_express.c b/hw/bsp/feather_m4_express/feather_m4_express.c index be8cc810b..8b4764cd0 100644 --- a/hw/bsp/feather_m4_express/feather_m4_express.c +++ b/hw/bsp/feather_m4_express/feather_m4_express.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_1_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_2_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_3_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c index ba31493ee..93661b899 100644 --- a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c +++ b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c index 0b9cc89e0..3ae9565c9 100644 --- a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c +++ b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_1_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_2_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_3_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 76755e89f..9d955a763 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -153,7 +153,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index 66cf44a0e..cda508803 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -145,7 +145,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 6d5284869..e172bbfb0 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -182,7 +182,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -193,7 +193,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m0_express/metro_m0_express.c b/hw/bsp/metro_m0_express/metro_m0_express.c index b373b829e..83b20793e 100644 --- a/hw/bsp/metro_m0_express/metro_m0_express.c +++ b/hw/bsp/metro_m0_express/metro_m0_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m4_express/metro_m4_express.c b/hw/bsp/metro_m4_express/metro_m4_express.c index c735fa64d..61b270de0 100644 --- a/hw/bsp/metro_m4_express/metro_m4_express.c +++ b/hw/bsp/metro_m4_express/metro_m4_express.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_1_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_2_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_3_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c index a76e2d9b6..d061c0e04 100644 --- a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c +++ b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c index 955344884..874e4517e 100644 --- a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c +++ b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c index 708397f7f..17727c0ab 100644 --- a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c +++ b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c @@ -124,7 +124,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c index a21dcdbfc..ed29be4d3 100644 --- a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c +++ b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index a21dcdbfc..ed29be4d3 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c index a21dcdbfc..ed29be4d3 100644 --- a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c +++ b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index e1bafff8d..a789a8819 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -229,7 +229,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -240,7 +240,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/samg55xplained/samg55xplained.c b/hw/bsp/samg55xplained/samg55xplained.c index 1eb5105b9..4f894a2bc 100644 --- a/hw/bsp/samg55xplained/samg55xplained.c +++ b/hw/bsp/samg55xplained/samg55xplained.c @@ -100,7 +100,7 @@ void board_init(void) void UDP_Handler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c index 799c56261..d8dbd2b1c 100644 --- a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c +++ b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index 7c2bee539..9e49ed19c 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -129,7 +129,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -140,7 +140,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/src/device/usbd.h b/src/device/usbd.h index beeec7e1c..683366f98 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -48,7 +48,7 @@ bool tud_init (void); void tud_task (void); // Interrupt handler, name alias to DCD -#define tud_isr dcd_isr +#define tud_irq_handler dcd_isr // Check if device is connected and configured bool tud_mounted(void); -- cgit v1.3.1 From fb05451a26ebafd67de27271fd22b85d36fa3c62 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 17:24:22 +0700 Subject: mass rename dcd_isr() to dcd_irq_handler() --- src/device/dcd.h | 2 +- src/device/usbd.h | 2 +- src/portable/microchip/samd/dcd_samd.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 2 +- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 2 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- src/portable/nxp/transdimension/dcd_transdimension.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 5e1181d1b..7e976e0ed 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_isr (uint8_t rhport) TU_ATTR_USED; +void dcd_irq_handler (uint8_t rhport) TU_ATTR_USED; // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/device/usbd.h b/src/device/usbd.h index 683366f98..2bb9821ed 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -48,7 +48,7 @@ bool tud_init (void); void tud_task (void); // Interrupt handler, name alias to DCD -#define tud_irq_handler dcd_isr +#define tud_irq_handler dcd_irq_handler // Check if device is connected and configured bool tud_mounted(void); diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 9f91e3f96..420526bfa 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -318,7 +318,7 @@ void maybe_transfer_complete(void) { } -void dcd_isr (uint8_t rhport) +void dcd_irq_handler (uint8_t rhport) { (void) rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 882072521..93d9029d6 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -333,7 +333,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { uint32_t const intr_mask = UDP->UDP_IMR; uint32_t const intr_status = UDP->UDP_ISR & intr_mask; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 4e1db24a4..f85af6d1e 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -424,7 +424,7 @@ void USBD_IRQHandler(void) USBD->INTSTS = status & enabled_irqs; } -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { (void) rhport; USBD_IRQHandler(); diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 25d723d96..fbc2361a8 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -440,7 +440,7 @@ void USBD_IRQHandler(void) USBD->INTSTS = status & enabled_irqs; } -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { (void) rhport; USBD_IRQHandler(); diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 8457e686b..c448577ae 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -641,7 +641,7 @@ void USBD_IRQHandler(void) } } -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { (void) rhport; USBD_IRQHandler(); diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 89a4ba3f8..884260f31 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -495,7 +495,7 @@ static void dd_complete_isr(uint8_t rhport, uint8_t ep_id) } // main USB IRQ handler -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { uint32_t const dev_int_status = LPC_USB->DevIntSt & LPC_USB->DevIntEn; LPC_USB->DevIntClr = dev_int_status;// Acknowledge handled interrupt diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index d400a30e3..2872f1435 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -492,7 +492,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs; -- cgit v1.3.1 From 4179334aca5b4085912f895ac2e5e8586efefd67 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 17:35:11 +0700 Subject: call tud_irq_handler() for all nrf5x board --- hw/bsp/adafruit_clue/adafruit_clue.c | 9 +++++++++ hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c | 8 ++++++++ hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c | 8 ++++++++ hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c | 8 ++++++++ hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c | 8 ++++++++ hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c | 8 ++++++++ hw/bsp/pca10056/pca10056.c | 8 ++++++++ hw/bsp/pca10059/pca10059.c | 8 ++++++++ hw/bsp/pca10100/pca10100.c | 8 ++++++++ hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c | 8 ++++++++ src/device/dcd.h | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 +++- 12 files changed, 85 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/hw/bsp/adafruit_clue/adafruit_clue.c b/hw/bsp/adafruit_clue/adafruit_clue.c index 67b5ffda4..7b090dd45 100644 --- a/hw/bsp/adafruit_clue/adafruit_clue.c +++ b/hw/bsp/adafruit_clue/adafruit_clue.c @@ -35,6 +35,15 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c index 941716c2f..a3ab49a5d 100644 --- a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c +++ b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c index 30742ab9f..17e619704 100644 --- a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c +++ b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c index a790b125d..e36615ee1 100644 --- a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c +++ b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c index 473abc2d1..fb4ef9af2 100644 --- a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c +++ b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c index 86f02d3e7..99db842ac 100644 --- a/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c +++ b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10056/pca10056.c b/hw/bsp/pca10056/pca10056.c index 8d9764c3a..ec34dbb9e 100644 --- a/hw/bsp/pca10056/pca10056.c +++ b/hw/bsp/pca10056/pca10056.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10059/pca10059.c b/hw/bsp/pca10059/pca10059.c index e0f4bc930..72a85a9fa 100644 --- a/hw/bsp/pca10059/pca10059.c +++ b/hw/bsp/pca10059/pca10059.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10100/pca10100.c b/hw/bsp/pca10100/pca10100.c index 8d9764c3a..ec34dbb9e 100644 --- a/hw/bsp/pca10100/pca10100.c +++ b/hw/bsp/pca10100/pca10100.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c index 8bb5a1739..62e6fa045 100644 --- a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c +++ b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/src/device/dcd.h b/src/device/dcd.h index 7e976e0ed..dbdc19dd3 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_irq_handler (uint8_t rhport) TU_ATTR_USED; +void dcd_irq_handler(uint8_t rhport) TU_ATTR_USED; // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 2ce288d6c..e54f475ec 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -359,8 +359,10 @@ void bus_reset(void) _dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE; } -void USBD_IRQHandler(void) +void dcd_irq_handler(uint8_t rhport) { + (void) rhport; + uint32_t const inten = NRF_USBD->INTEN; uint32_t int_status = 0; -- cgit v1.3.1 From 11201f1a06396d4ab8302f2bb5ce579cb4ae7a6c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 Apr 2020 11:42:42 +0700 Subject: adding dcd_connect/disconnect --- src/device/dcd.h | 6 ++++++ src/device/usbd.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 143a2de34..487ddb3b6 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -106,6 +106,12 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num); // Wake up host void dcd_remote_wakeup(uint8_t rhport); +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index beeec7e1c..817af20e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -65,6 +65,20 @@ static inline bool tud_ready(void) // Remote wake up host, only if suspended and enabled by host bool tud_remote_wakeup(void); +static inline bool tud_disconnect(void) +{ + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; +} + +static inline bool tud_connect(void) +{ + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; +} + // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only // - If len > wLength : it will be truncated -- cgit v1.3.1 From 715c4dbbf8fe7c6bb83013df626a201928704b30 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 8 Apr 2020 11:51:33 -0400 Subject: stm32fsdev: Implement dcd_connect. --- docs/porting.md | 6 ++++++ src/device/dcd.h | 8 ++++---- src/device/usbd.c | 1 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 24 ++++++++++++++++++------ src/portable/template/dcd_template.c | 14 ++++++++++++++ test/test/device/msc/test_msc_device.c | 1 + test/test/device/usbd/test_usbd.c | 1 + 7 files changed, 45 insertions(+), 10 deletions(-) (limited to 'src/device') diff --git a/docs/porting.md b/docs/porting.md index deb1b9efb..7d7d4cdb1 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -62,6 +62,8 @@ All of the code for the low-level device API is in `src/portable//CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); + + // Data-line pull-up is left disconnected. +} - // And finally enable pull-up, which may trigger the RESET IRQ if the host is connected. - // (if this MCU has an internal pullup) +// Define only on MCU with internal pull-up so BSP can override (needed on MCU without internal pull-up) #if defined(USB_BCDR_DPPU) - USB->BCDR |= USB_BCDR_DPPU; -#else - // FIXME: callback to the user to ask them to twiddle a GPIO to disable/enable D+??? -#endif +TU_ATTR_WEAK +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB->BCDR &= ~(USB_BCDR_DPPU); +} + +TU_ATTR_WEAK +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB->BCDR |= USB_BCDR_DPPU; } +#endif + // Enable device interrupt void dcd_int_enable (uint8_t rhport) { diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 102910509..d29c98e55 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -45,6 +45,20 @@ void dcd_init (uint8_t rhport) (void) rhport; } +#if HAS_INTERNAL_PULLUP +// Enable internal D+/D- pullup +void dcd_connect(uint8_t rhport) TU_ATTR_WEAK +{ + (void) rhport; +} + +// Disable internal D+/D- pullup +void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK +{ + (void) rhport; +} +#endif + // Enable device interrupt void dcd_int_enable (uint8_t rhport) { diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 095c28170..62a36d3e3 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -199,6 +199,7 @@ void setUp(void) if ( !tusb_inited() ) { dcd_init_Expect(rhport); + dcd_connect_Expect(rhport); tusb_init(); } diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index 06372b2e4..1bb32c1e5 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -127,6 +127,7 @@ void setUp(void) { mscd_init_Expect(); dcd_init_Expect(rhport); + dcd_connect_Expect(rhport); tusb_init(); } } -- cgit v1.3.1 From 1b3d1b52c9351391f62dea374345c8de7f985b0f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 13:54:50 +0700 Subject: fix uint32_t format with log --- src/device/usbd.c | 2 +- src/tusb.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 125aa351c..397a681ed 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -421,7 +421,7 @@ void tud_task (void) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Endpoint: 0x%02X, Bytes: %lu\r\n", ep_addr, event.xfer_complete.len); + TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; diff --git a/src/tusb.c b/src/tusb.c index 8e0022f4d..8f234455f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -96,9 +96,9 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent) char format[] = "%00lX"; format[2] += 2*size; - const uint8_t item_per_line = 16 / size; + const uint8_t item_per_line = 16 / size; - for(uint32_t i=0; i Date: Fri, 10 Apr 2020 10:23:56 -0400 Subject: stm32fsdev: set dcd_connect API definitions to strong, Modify documentation. --- docs/porting.md | 4 ++-- src/device/dcd.h | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/device') diff --git a/docs/porting.md b/docs/porting.md index 7d7d4cdb1..d3408aebd 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -62,7 +62,7 @@ All of the code for the low-level device API is in `src/portable//BCDR &= ~(USB_BCDR_DPPU); } -TU_ATTR_WEAK +// Enable internal D+ PU void dcd_connect(uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From bb3bbcc00bfa641d285b28931ceb8bd04c3f7651 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 12 Apr 2020 15:41:18 -0500 Subject: usbnet: OS-agnostic (Windows/Linux/macOS) network driver --- examples/device/net_lwip_webserver/src/main.c | 11 +- .../device/net_lwip_webserver/src/tusb_config.h | 3 +- .../net_lwip_webserver/src/usb_descriptors.c | 61 ++++-- src/class/net/net_device.c | 218 ++++++++++++++------- src/class/net/net_device.h | 2 + src/device/usbd.c | 38 +++- src/device/usbd.h | 12 +- src/tusb_option.h | 5 +- 8 files changed, 237 insertions(+), 113 deletions(-) (limited to 'src/device') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index fe904e8e8..c6af96ea8 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -26,13 +26,14 @@ */ /* -depending on the value of CFG_TUD_NET (tusb_config.h), this can be a CDC-ECM, RNDIS, or CDC-EEM USB virtual network adapter +depending on the value of CFG_TUD_NET (tusb_config.h), this can be a RNDIS+CDC-ECM or CDC-EEM USB virtual network adapter -CDC-ECM should be valid on Linux and MacOS hosts -RNDIS should be valid on Linux and Windows hosts -CDC-EEM should be valid on Linux hosts +OPT_NET_RNDIS_ECM : RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and MacOS hosts +OPT_NET_EEM : CDC-EEM should be valid on Linux hosts -You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network adapters to emulate. +OPT_NET_RNDIS_ECM should be the best choice, as it makes for a hopefully universal solution. + +You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network option. The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. */ diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 0b40fefab..d8c750d5c 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -79,8 +79,7 @@ #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -//#define CFG_TUD_NET OPT_NET_ECM -#define CFG_TUD_NET OPT_NET_RNDIS +#define CFG_TUD_NET OPT_NET_RNDIS_ECM //#define CFG_TUD_NET OPT_NET_EEM #ifdef __cplusplus diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 6ce36cfef..39c542eca 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -63,13 +63,17 @@ tusb_desc_device_t const desc_device = .idVendor = 0xCafe, .idProduct = USB_PID, - .bcdDevice = 0x0100, + .bcdDevice = 0x0101, .iManufacturer = STRID_MANUFACTURER, .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, +#if CFG_TUD_NET == OPT_NET_EEM .bNumConfigurations = 0x01 +#else + .bNumConfigurations = 0x02 +#endif }; // Invoked when received GET DEVICE DESCRIPTOR @@ -85,16 +89,23 @@ uint8_t const * tud_descriptor_device_cb(void) enum { ITF_NUM_CDC = 0, +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM ITF_NUM_CDC_DATA, +#endif ITF_NUM_TOTAL }; -#if CFG_TUD_NET == OPT_NET_ECM - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) -#elif CFG_TUD_NET == OPT_NET_RNDIS - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) -#elif CFG_TUD_NET == OPT_NET_EEM - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) +enum +{ + CONFIG_NUM_DEFAULT = 1, + CONFIG_NUM_ALTERNATE = 2, +}; + +#if CFG_TUD_NET == OPT_NET_EEM + #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) +#else + #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) + #define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) #endif #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX @@ -105,30 +116,42 @@ enum #define EPNUM_CDC 2 #endif -uint8_t const desc_configuration[] = +static uint8_t const main_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), + TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_DEFAULT, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), -#if CFG_TUD_NET == OPT_NET_ECM - // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), -#elif CFG_TUD_NET == OPT_NET_RNDIS - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM // Interface number, description string index, EP data address (out, in) and size. TUD_CDC_EEM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), +#else + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), #endif }; +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM +static uint8_t const alt_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_ALTERNATE, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), + + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { +#if CFG_TUD_NET == OPT_NET_EEM (void) index; // for multiple configurations - return desc_configuration; + return main_configuration; +#else + return (0 == index) ? main_configuration : alt_configuration; +#endif } //--------------------------------------------------------------------+ @@ -141,8 +164,8 @@ static char const* string_desc_arr [] = [STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) [STRID_MANUFACTURER] = "TinyUSB", // Manufacturer [STRID_PRODUCT] = "TinyUSB Device", // Product - [STRID_SERIAL] = "123456", // Serials - [STRID_INTERFACE] = "TinyUSB Network Interface" // CDC-ECM Interface + [STRID_SERIAL] = "123456", // Serial + [STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description // STRID_MAC index is handled separately }; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 68520625a..19bc5d2d6 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -41,39 +41,57 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ typedef struct { uint8_t itf_num; +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM uint8_t ep_notif; + bool ecm_mode; +#endif uint8_t ep_in; uint8_t ep_out; } netd_interface_t; -#if CFG_TUD_NET == OPT_NET_ECM - #define CFG_TUD_NET_PACKET_PREFIX_LEN 0 - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL -#elif CFG_TUD_NET == OPT_NET_RNDIS - #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - #define CFG_TUD_NET_INTERFACESUBCLASS TUD_RNDIS_ITF_SUBCLASS -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 - #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL +#else + #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 #endif CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; -#if CFG_TUD_NET == OPT_NET_ECM - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static tusb_control_request_t notify = - { - .bmRequestType = 0x21, - .bRequest = 0 /* NETWORK_CONNECTION */, +struct ecm_notify_struct +{ + tusb_control_request_t header; + uint32_t downlink, uplink; +}; + +static const struct ecm_notify_struct ecm_notify_nc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, .wValue = 1 /* Connected */, .wLength = 0, - }; -#elif CFG_TUD_NET == OPT_NET_RNDIS - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[120]; -#endif + }, +}; + +static const struct ecm_notify_struct ecm_notify_csc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, + .wLength = 8, + }, + .downlink = 9728000, + .uplink = 9728000, +}; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union +{ + uint8_t rndis_buf[120]; + struct ecm_notify_struct ecm_buf; +} notify; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -95,7 +113,9 @@ static void do_in_xfer(uint8_t *buf, uint16_t len) void netd_report(uint8_t *buf, uint16_t len) { +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); +#endif } //--------------------------------------------------------------------+ @@ -106,6 +126,10 @@ void netd_init(void) tu_memclr(&_netd_itf, sizeof(_netd_itf)); } +void netd_init_data(void) +{ +} + void netd_reset(uint8_t rhport) { (void) rhport; @@ -113,21 +137,26 @@ void netd_reset(uint8_t rhport) netd_init(); } +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { // sanity check the descriptor - TU_ASSERT (CFG_TUD_NET_INTERFACESUBCLASS == itf_desc->bInterfaceSubClass); +#if CFG_TUD_NET == OPT_NET_EEM + TU_VERIFY (CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL == itf_desc->bInterfaceSubClass); +#else + _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); +#endif // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); + TU_ASSERT(0 == _netd_itf.ep_notif); - //------------- first Interface -------------// + //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); -#if CFG_TUD_NET != OPT_NET_EEM // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) { @@ -143,18 +172,28 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = tu_desc_next(p_desc); } - //------------- second Interface -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + return true; +} +#endif + +bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + // confirm interface hasn't already been allocated + TU_ASSERT(0 == _netd_itf.ep_in); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + (*p_length) = sizeof(tusb_desc_interface_t); + + //------------- Data Interface -------------// + while ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor p_desc = tu_desc_next(p_desc); (*p_length) += sizeof(tusb_desc_interface_t); } -#endif if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { @@ -184,18 +223,25 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques // Handle class request only TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_OUT) + if ( !_netd_itf.ecm_mode && (request->bmRequestType_bit.direction == TUSB_DIR_OUT) ) { - rndis_class_set_handler(rndis_buf, request->wLength); + rndis_class_set_handler(notify.rndis_buf, request->wLength); } #endif return true; } +static void ecm_report(bool nc) +{ + notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; + notify.ecm_buf.header.wIndex = _netd_itf.itf_num; + netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); +} + // Handle class control request // return false to stall control endpoint (e.g unsupported request) bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) @@ -205,28 +251,32 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_ECM - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - notify.wIndex = request->wIndex; - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, (uint8_t *)¬ify, sizeof(notify)); - } -#elif CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) +#if CFG_TUD_NET == OPT_NET_EEM + (void)rhport; +#else + if (_netd_itf.ecm_mode) { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)rndis_buf; - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(rndis_buf)); - tud_control_xfer(rhport, request, rndis_buf, msglen); + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } } else { - tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } } -#else - (void)rhport; #endif return true; @@ -244,18 +294,7 @@ static void handle_incoming_packet(uint32_t len) uint8_t *pnt = received; uint32_t size = 0; -#if CFG_TUD_NET == OPT_NET_ECM - size = len; -#elif CFG_TUD_NET == OPT_NET_RNDIS - rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; - if (len >= sizeof(rndis_data_packet_t)) - if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) - if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) - { - pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; - size = r->DataLength; - } -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; (void)len; @@ -271,26 +310,45 @@ static void handle_incoming_packet(uint32_t len) pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; size = hdr->length - 4; /* discard the unused CRC-32 */ } +#else + if (_netd_itf.ecm_mode) + { + size = len; + } + else + { + rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; + if (len >= sizeof(rndis_data_packet_t)) + if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) + if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) + { + pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; + size = r->DataLength; + } + } #endif + bool accepted = false; + if (size) { struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - bool accepted = true; if (p) { memcpy(p->payload, pnt, size); p->len = size; accepted = tud_network_recv_cb(p); - } - if (!p || !accepted) - { - /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */ - tud_network_recv_renew(); + if (!accepted) pbuf_free(p); } } + + if (!accepted) + { + /* if a buffer was never handled by user code, we must renew on the user's behalf */ + tud_network_recv_renew(); + } } bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -320,6 +378,13 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM + if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) + { + if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); + } +#endif + return true; } @@ -337,7 +402,11 @@ void tud_network_xmit(struct pbuf *p) if (!can_xmit) return; +#if CFG_TUD_NET == OPT_NET_EEM len = CFG_TUD_NET_PACKET_PREFIX_LEN; +#else + len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; +#endif data = transmitted + len; for(q = p; q != NULL; q = q->next) @@ -347,14 +416,7 @@ void tud_network_xmit(struct pbuf *p) len += q->len; } -#if CFG_TUD_NET == OPT_NET_RNDIS - rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; - memset(hdr, 0, sizeof(rndis_data_packet_t)); - hdr->MessageType = REMOTE_NDIS_PACKET_MSG; - hdr->MessageLength = len; - hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); - hdr->DataLength = len - sizeof(rndis_data_packet_t); -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted; /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */ data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; @@ -363,6 +425,16 @@ void tud_network_xmit(struct pbuf *p) hdr->bmType = 0; /* EEM Data Packet */ hdr->length = len - sizeof(struct cdc_eem_packet_header); hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */ +#else + if (!_netd_itf.ecm_mode) + { + rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); + hdr->DataLength = len - sizeof(rndis_data_packet_t); + } #endif do_in_xfer(transmitted, len); diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 67cd99933..6914ed050 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,8 +73,10 @@ void tud_network_xmit(struct pbuf *p); // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void netd_init (void); +void netd_init_data (void); void netd_reset (uint8_t rhport); bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool netd_open_data (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 2adac429c..9d15ea4a4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -184,21 +184,47 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET +#if CFG_TUD_NET != OPT_NET_EEM + /* RNDIS management interface */ { - .class_code = -#if CFG_TUD_NET == OPT_NET_RNDIS - TUD_RNDIS_ITF_CLASS, -#else - TUSB_CLASS_CDC, + .class_code = TUD_RNDIS_ITF_CLASS, + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_request = netd_control_request, + .control_complete = netd_control_complete, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, #endif + /* CDC-ECM management interface; CDC-EEM data interface */ + { + .class_code = TUSB_CLASS_CDC, .init = netd_init, .reset = netd_reset, +#if CFG_TUD_NET == OPT_NET_EEM + .open = netd_open_data, +#else .open = netd_open, +#endif .control_request = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, - .sof = NULL + .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ +#if CFG_TUD_NET != OPT_NET_EEM + { + .class_code = TUSB_CLASS_CDC_DATA, + .init = netd_init_data, + .reset = NULL, + .open = netd_open_data, + .control_request = NULL, + .control_complete = NULL, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, +#endif #endif }; diff --git a/src/device/usbd.h b/src/device/usbd.h index 817af20e3..756f5b161 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -342,8 +342,8 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- CDC-ECM -------------// -// Length of template descriptor: 62 bytes -#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+7+7) +// Length of template descriptor: 71 bytes +#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+9+7+7) // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. @@ -358,8 +358,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ /* Endpoint Notification */\ 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ /* Endpoint Out */\ @@ -372,7 +374,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Windows XP */ #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL - #define TUD_RNDIS_ITF_PROTOCOL CDC_COMM_PROTOCOL_MICROSOFT_RNDIS + #define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ #else /* Windows 7+ */ #define TUD_RNDIS_ITF_CLASS 0xE0 diff --git a/src/tusb_option.h b/src/tusb_option.h index 6e2a2f125..c2394880f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -128,9 +128,8 @@ * \ref CFG_TUD_NET must be defined to one of these * @{ */ #define OPT_NET_NONE 0 ///< No network interface -#define OPT_NET_ECM 1 ///< CDC-ECM -#define OPT_NET_RNDIS 2 ///< RNDIS -#define OPT_NET_EEM 3 ///< CDC-EEM +#define OPT_NET_RNDIS_ECM 1 ///< RNDIS+CDC-ECM +#define OPT_NET_EEM 2 ///< CDC-EEM /** @} */ #ifndef CFG_TUSB_RHPORT0_MODE -- cgit v1.3.1 From 0eeaccaf46c28444cc0830895559652cf5638c60 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 12 Apr 2020 21:07:17 -0400 Subject: Skeleton, and initial stm32fsdev implementation (that leaks memory) --- docs/porting.md | 7 +++ src/device/dcd.h | 6 ++- src/device/usbd.c | 61 +++++++++++++++++++++++++++ src/device/usbd.h | 2 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 37 +++++++++++++++- 5 files changed, 111 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/docs/porting.md b/docs/porting.md index ccafa7999..de300c080 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -119,6 +119,13 @@ Opening an endpoint is done for all non-control endpoints once the host picks a Also make sure to enable endpoint specific interrupts. +##### dcd_edpt_close + +Close an endpoint. After calling this, the device should not respond to any packets directed towards this endpoint. Implementation is optional, and is to be called from USBD in a non-interrupt context. +This function is used for implementing alternate settings. + +When called, this function need to abort any transfers in progress through this endpoint, before returning. + ##### dcd_edpt_xfer `dcd_edpt_xfer` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral. diff --git a/src/device/dcd.h b/src/device/dcd.h index 487ddb3b6..f48530227 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -66,7 +66,7 @@ typedef struct TU_ATTR_ALIGNED(4) // USBD_EVT_XFER_COMPLETE struct { - uint8_t ep_addr; + uint8_t ep_addr; ///< 0xFF signifies that the transfer was aborted. uint8_t result; uint32_t len; }xfer_complete; @@ -123,6 +123,10 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +// Close an endpoint. +// Since it is weak, caller must TU_ASSERT this function's existence before calling it. +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 397a681ed..e46532567 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -420,6 +420,11 @@ void tud_task (void) 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); + + if(ep_addr == 0xFF) // aborted transfer + { + break; + } TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); @@ -1036,4 +1041,60 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) return _usbd_dev.ep_status[epnum][dir].stalled; } +/** + * Remove queued xfer complete messages from event queue, + * for a particular ep. + */ +static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) +{ + dcd_event_t ev_sentinal = + { + .event_id = DCD_EVENT_COUNT, ///< This is an invalid event ID. + }; + dcd_event_t event; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + dcd_int_disable(rhport); + // Queue sentinal element + TU_ASSERT(osal_queue_send(_usbd_q, &ev_sentinal, true), /**/); + + TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); + + while(event.event_id != DCD_EVENT_COUNT) + { + if((event.rhport == rhport) && (event.event_id == DCD_EVENT_XFER_COMPLETE) + && (event.xfer_complete.ep_addr == ep_addr)) + { + _usbd_dev.ep_status[epnum][ep_dir].busy = false; + event.xfer_complete.ep_addr = 0xFF; // Mark transfer as invalid + } + TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); + TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); + } + + dcd_int_enable(rhport); +} + +/** + * tud_edpt_close will disable an endpoint, and clear all pending transfers + * through the particular endpoint. + * + * It must be called from the usb task (i.e. from the control request + * handler while handling SET_ALTERNATE). + */ +void tud_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + + TU_ASSERT(dcd_edpt_close, /**/); + TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); + + dcd_edpt_close(rhport, ep_addr); + + /* Now, in progress transfers have to be expunged */ + usbd_abort_transfers(rhport, ep_addr); + + return; +} + #endif diff --git a/src/device/usbd.h b/src/device/usbd.h index 817af20e3..2447c2082 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -79,6 +79,8 @@ static inline bool tud_connect(void) return true; } +void tud_edpt_close(uint8_t rhport, uint8_t ep_addr); + // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only // - If len > wLength : it will be truncated diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index f962a4bee..fa044e2d6 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -69,7 +69,6 @@ * - Endpoint index is the ID of the endpoint * - This means that priority is given to endpoints with lower ID numbers * - Code is mixing up EP IX with EP ID. Everywhere. - * - No way to close endpoints; Can a device be reconfigured without a reset? * - Packet buffer memory is copied in the interrupt. * - This is better for performance, but means interrupts are disabled for longer * - DMA may be the best choice, but it could also be pushed to the USBD task. @@ -623,6 +622,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc if(dir == TUSB_DIR_IN) { + // FIXME: use pma_alloc to allocate memory dynamically *pcd_ep_tx_address_ptr(USB, epnum) = ep_buf_ptr; pcd_set_ep_tx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_tx_dtog(USB, epnum); @@ -630,6 +630,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc } else { + // FIXME: use pma_alloc to allocate memory dynamically *pcd_ep_rx_address_ptr(USB, epnum) = ep_buf_ptr; pcd_set_ep_rx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_rx_dtog(USB, epnum); @@ -642,6 +643,40 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc return true; } +/** + * Close an endpoint. + * + * This function should be called with interrupts enabled, though + * this implementation should be valid with them disabled, too. + * This also clears transfers in progress, should there be any. + */ +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + uint32_t const epnum = tu_edpt_number(ep_addr); + uint32_t const dir = tu_edpt_dir(ep_addr); + +#ifndef NDEBUG + TU_ASSERT(epnum < MAX_EP_COUNT, /**/); +#endif + + //uint16_t memptr; + + if(dir == TUSB_DIR_IN) + { + pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS); + //memptr = *pcd_ep_tx_address_ptr(USB, epnum); + } + else + { + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_DIS); + //memptr = *pcd_ep_rx_address_ptr(USB, epnum); + } + + // FIXME: Free memory + // pma_free(memptr); +} + // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) -- cgit v1.3.1 From f4df82939955d86f6c2e826e1bc9f4b5bb713df8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 13 Apr 2020 17:04:18 +0700 Subject: lpc17xx move set configdevice into set address for removing dcd_set_config() --- src/device/usbd.c | 2 -- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 2adac429c..55d6aa7eb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -542,8 +542,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { uint8_t const cfg_num = (uint8_t) p_request->wValue; - dcd_set_config(rhport, cfg_num); - if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); _usbd_dev.configured = cfg_num ? 1 : 0; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 884260f31..1d755ce63 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -205,13 +205,15 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); sie_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable + + // Also Set Configure Device to enable non-control endpoint response + sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); } void dcd_set_config(uint8_t rhport, uint8_t config_num) { (void) rhport; (void) config_num; - sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); } void dcd_remote_wakeup(uint8_t rhport) @@ -273,6 +275,7 @@ static uint8_t control_ep_read(void * buffer, uint8_t len) //--------------------------------------------------------------------+ // DCD Endpoint Port //--------------------------------------------------------------------+ + bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { (void) rhport; -- cgit v1.3.1 From f8e7487355c1d48517211a2316fbbc8566a1532d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 13 Apr 2020 09:25:16 -0400 Subject: edpt_close: Updated based on feedback. --- docs/porting.md | 7 ++-- src/device/usbd.c | 10 +++-- src/device/usbd.h | 2 - src/device/usbd_pvt.h | 1 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 60 ++++++++++++++++++--------- 5 files changed, 52 insertions(+), 28 deletions(-) (limited to 'src/device') diff --git a/docs/porting.md b/docs/porting.md index de300c080..9561dfaf7 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -121,10 +121,11 @@ Also make sure to enable endpoint specific interrupts. ##### dcd_edpt_close -Close an endpoint. After calling this, the device should not respond to any packets directed towards this endpoint. Implementation is optional, and is to be called from USBD in a non-interrupt context. -This function is used for implementing alternate settings. +Close an endpoint. his function is used for implementing alternate settings. -When called, this function need to abort any transfers in progress through this endpoint, before returning. +After calling this, the device should not respond to any packets directed towards this endpoint. When called, this function must abort any transfers in progress through this endpoint, before returning. + +Implementation is optional. Must be called from the USB task. Interrupts could be disabled or enabled during the call. ##### dcd_edpt_xfer diff --git a/src/device/usbd.c b/src/device/usbd.c index e46532567..71f5454ee 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1044,6 +1044,8 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) /** * Remove queued xfer complete messages from event queue, * for a particular ep. + * + * Must be called with interrupts enabled. */ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) { @@ -1077,13 +1079,13 @@ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) } /** - * tud_edpt_close will disable an endpoint, and clear all pending transfers + * usbd_edpt_close will disable an endpoint, and clear all pending transfers * through the particular endpoint. * - * It must be called from the usb task (i.e. from the control request - * handler while handling SET_ALTERNATE). + * It must be called from the usb task (e.g. from the control request + * handler while handling SET_ALTERNATE), with interrupts enabled. */ -void tud_edpt_close(uint8_t rhport, uint8_t ep_addr) +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { TU_ASSERT(dcd_edpt_close, /**/); diff --git a/src/device/usbd.h b/src/device/usbd.h index 2447c2082..817af20e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -79,8 +79,6 @@ static inline bool tud_connect(void) return true; } -void tud_edpt_close(uint8_t rhport, uint8_t ep_addr); - // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only // - If len > wLength : it will be truncated diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index b9947044b..26b9700e8 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -38,6 +38,7 @@ //--------------------------------------------------------------------+ //bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index fa044e2d6..13e54443f 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -63,8 +63,10 @@ * Current driver limitations (i.e., a list of features for you to add): * - STALL handled, but not tested. * - Does it work? No clue. - * - All EP BTABLE buffers are created as max 64 bytes. - * - Smaller can be requested, but it has to be an even number. + * - All EP BTABLE buffers are created as fixed 64 bytes. + * - Smaller can be requested: + * - Must be a multiple of 8 bytes + * - All EP must have identical buffer size. * - No isochronous endpoints * - Endpoint index is the ID of the endpoint * - This means that priority is given to endpoints with lower ID numbers @@ -130,21 +132,29 @@ * Configuration *****************************************************/ -// HW supports max of 8 endpoints, but this can be reduced to save RAM +// HW supports max of 8 bidirectional endpoints, but this can be reduced to save RAM +// (8u here would mean 8 IN and 8 OUT) #ifndef MAX_EP_COUNT -# define MAX_EP_COUNT 8u +# if (PMA_LENGTH == 512U) +# define MAX_EP_COUNT 4U +# else +# define MAX_EP_COUNT 8U +# endif #endif // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // Both of these MUST be a multiple of 2, and are in byte units. #ifndef DCD_STM32_BTABLE_BASE -# define DCD_STM32_BTABLE_BASE 0u +# define DCD_STM32_BTABLE_BASE 0U #endif #ifndef DCD_STM32_BTABLE_LENGTH # define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE) #endif +// Below is used by the static PMA allocator +#define DCD_STM32_PMA_ALLOC_SIZE 64U + /*************************************************** * Checks, structs, defines, function definitions, etc. */ @@ -156,6 +166,11 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LEN TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); +// With static allocation of 64 bytes per endpoint, ensure there is enough packet buffer space +TU_VERIFY_STATIC(((MAX_EP_COUNT*2u*DCD_STM32_PMA_ALLOC_SIZE) <= DCD_STM32_BTABLE_LENGTH), "Packed buffer not long enough for count of endpoints"); + +TU_VERIFY_STATIC((DCD_STM32_PMA_ALLOC_SIZE % 8) == 0, "Packet buffer allocation must be a multiple of 8 bytes"); + // One of these for every EP IN & OUT, uses a bit of RAM.... typedef struct { @@ -178,7 +193,6 @@ static uint8_t remoteWakeCountdown; // When wake is requested // EP Buffers assigned from end of memory location, to minimize their chance of crashing // into the stack. -static uint16_t ep_buf_ptr; static void dcd_handle_bus_reset(void); static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes); static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); @@ -355,7 +369,6 @@ static void dcd_handle_bus_reset(void) pcd_set_endpoint(USB,i,0u); } - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each) dcd_edpt_open (0, &ep0OUT_desc); dcd_edpt_open (0, &ep0IN_desc); @@ -577,6 +590,22 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re } } +/*** + * Allocate a section of PMA + * Currently statitically allocates 64 bytes for each EP. + * + * stm32fsdev have 512 or 1024 bytes of packet RAM, and support 16 EP (8 in and 8 out), + * Static checks above have verified that there is enough packet memory space, so + * this should NEVER fail. + */ +static uint16_t dcd_pma_alloc(uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + return ((2*epnum + dir) * DCD_STM32_PMA_ALLOC_SIZE); +} + // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, // so I'm using the #define from HAL here, instead. @@ -590,6 +619,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); TU_ASSERT(epnum < MAX_EP_COUNT); + TU_ASSERT(epMaxPktSize <= DCD_STM32_PMA_ALLOC_SIZE); // Set type switch(p_endpoint_desc->bmAttributes.xfer) { @@ -623,7 +653,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc if(dir == TUSB_DIR_IN) { // FIXME: use pma_alloc to allocate memory dynamically - *pcd_ep_tx_address_ptr(USB, epnum) = ep_buf_ptr; + *pcd_ep_tx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress); pcd_set_ep_tx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_tx_dtog(USB, epnum); pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_NAK); @@ -631,14 +661,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc else { // FIXME: use pma_alloc to allocate memory dynamically - *pcd_ep_rx_address_ptr(USB, epnum) = ep_buf_ptr; + *pcd_ep_rx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress); pcd_set_ep_rx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_rx_dtog(USB, epnum); pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK); } xfer_ctl_ptr(epnum, dir)->max_packet_size = epMaxPktSize; - ep_buf_ptr = (uint16_t)(ep_buf_ptr + p_endpoint_desc->wMaxPacketSize.size); // increment buffer pointer return true; } @@ -646,8 +675,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc /** * Close an endpoint. * - * This function should be called with interrupts enabled, though - * this implementation should be valid with them disabled, too. + * This function may be called with interrupts enabled or disabled. + * * This also clears transfers in progress, should there be any. */ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) @@ -660,21 +689,14 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ASSERT(epnum < MAX_EP_COUNT, /**/); #endif - //uint16_t memptr; - if(dir == TUSB_DIR_IN) { pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS); - //memptr = *pcd_ep_tx_address_ptr(USB, epnum); } else { pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_DIS); - //memptr = *pcd_ep_rx_address_ptr(USB, epnum); } - - // FIXME: Free memory - // pma_free(memptr); } // Currently, single-buffered, and only 64 bytes at a time (max) -- cgit v1.3.1 From de208b31cf648c03670f34ff615a0f7ac6b566f3 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 13 Apr 2020 11:05:34 -0400 Subject: edpt_close: Remove item from queue instead of modifying it. --- src/device/dcd.h | 2 +- src/device/usbd.c | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index f48530227..99e623358 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -66,7 +66,7 @@ typedef struct TU_ATTR_ALIGNED(4) // USBD_EVT_XFER_COMPLETE struct { - uint8_t ep_addr; ///< 0xFF signifies that the transfer was aborted. + uint8_t ep_addr; uint8_t result; uint32_t len; }xfer_complete; diff --git a/src/device/usbd.c b/src/device/usbd.c index 71f5454ee..386401d9a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -420,11 +420,6 @@ void tud_task (void) 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); - - if(ep_addr == 0xFF) // aborted transfer - { - break; - } TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); @@ -1069,9 +1064,11 @@ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) && (event.xfer_complete.ep_addr == ep_addr)) { _usbd_dev.ep_status[epnum][ep_dir].busy = false; - event.xfer_complete.ep_addr = 0xFF; // Mark transfer as invalid } - TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); + else + { + TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); + } TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); } @@ -1087,7 +1084,6 @@ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - TU_ASSERT(dcd_edpt_close, /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); -- cgit v1.3.1 From 593fe154eca8e70b02beb0e5a2872e690ae74296 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Apr 2020 18:00:59 +0700 Subject: adding subclass & protocol to class driver structure --- src/common/tusb_types.h | 7 +++++++ src/device/usbd.c | 56 +++++++++++++++++++++++++++++++++++++------------ src/device/usbd.h | 14 ++++++------- 3 files changed, 57 insertions(+), 20 deletions(-) (limited to 'src/device') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index c37c19bad..70d0db942 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -139,6 +139,7 @@ typedef enum TUSB_REQ_RCPT_OTHER } tusb_request_recipient_t; +// https://www.usb.org/defined-class-codes typedef enum { TUSB_CLASS_UNSPECIFIED = 0 , @@ -176,6 +177,12 @@ typedef enum MISC_PROTOCOL_IAD = 1 }misc_protocol_type_t; +typedef enum +{ + APP_SUBCLASS_USBTMC = 0x03, + APP_SUBCLASS_DFU_RUNTIME = 0x01 +} app_subclass_type_t; + typedef enum { DEVICE_CAPABILITY_WIRELESS_USB = 0x01, diff --git a/src/device/usbd.c b/src/device/usbd.c index 9d15ea4a4..06fe1f23c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -73,8 +73,11 @@ enum { DRVID_INVALID = 0xFFu }; //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ -typedef struct { +typedef struct +{ uint8_t class_code; + uint8_t subclass; // 0xFF support all values of subclass + uint8_t protocol; // 0xFF support all values of protocol void (* init ) (void); void (* reset ) (uint8_t rhport); @@ -90,6 +93,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_CDC { .class_code = TUSB_CLASS_CDC, + .subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, + .protocol = 0xFF, // all protocols + .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, @@ -103,6 +109,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MSC { .class_code = TUSB_CLASS_MSC, + .subclass = MSC_SUBCLASS_SCSI, + .protocol = MSC_PROTOCOL_BOT, + .init = mscd_init, .reset = mscd_reset, .open = mscd_open, @@ -116,6 +125,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_HID { .class_code = TUSB_CLASS_HID, + .subclass = 0xFF, // all subclass + .protocol = 0xFF, // all protocol + .init = hidd_init, .reset = hidd_reset, .open = hidd_open, @@ -129,6 +141,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MIDI { .class_code = TUSB_CLASS_AUDIO, + .subclass = AUDIO_SUBCLASS_CONTROL, + .protocol = AUDIO_PROTOCOL_V1, + .init = midid_init, .open = midid_open, .reset = midid_reset, @@ -142,6 +157,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_VENDOR { .class_code = TUSB_CLASS_VENDOR_SPECIFIC, + .subclass = 0xFF, // all subclass + .protocol = 0xFF, // all protocol + .init = vendord_init, .reset = vendord_reset, .open = vendord_open, @@ -153,12 +171,11 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_USBTMC - // Presently USBTMC is the only defined class with the APP_SPECIFIC class code. - // We maybe need to add subclass codes here, or a callback to ask if a driver can - // handle a particular interface. { - .class_code = TUD_USBTMC_APP_CLASS, - //.subclass_code = TUD_USBTMC_APP_SUBCLASS + .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .subclass = APP_SUBCLASS_USBTMC, + .protocol = 0xFF, // all protocol + .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, @@ -171,8 +188,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_RT { - .class_code = TUD_DFU_APP_CLASS, - //.subclass_code = TUD_DFU_APP_SUBCLASS + .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .subclass = APP_SUBCLASS_DFU_RUNTIME, + .protocol = DFU_PROTOCOL_RT, + .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, @@ -183,11 +202,14 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_NET -#if CFG_TUD_NET != OPT_NET_EEM +#if CFG_TUD_NET + #if CFG_TUD_NET != OPT_NET_EEM /* RNDIS management interface */ { .class_code = TUD_RNDIS_ITF_CLASS, + .subclass = TUD_RNDIS_ITF_SUBCLASS, + .protocol = TUD_RNDIS_ITF_PROTOCOL, + .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -196,10 +218,14 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif + #endif + /* CDC-ECM management interface; CDC-EEM data interface */ { .class_code = TUSB_CLASS_CDC, + .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, + .protocol = 0x00, + .init = netd_init, .reset = netd_reset, #if CFG_TUD_NET == OPT_NET_EEM @@ -212,10 +238,14 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ -#if CFG_TUD_NET != OPT_NET_EEM + #if CFG_TUD_NET != OPT_NET_EEM { .class_code = TUSB_CLASS_CDC_DATA, + .subclass = 0x00, + .protocol = 0x00, + .init = netd_init_data, .reset = NULL, .open = netd_open_data, @@ -224,8 +254,8 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif #endif +#endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index dbc94bc35..7b04ef9a7 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -291,23 +291,23 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, // bulk-in endpoint ID #define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ -/* Interface */ \ + /* Interface */ \ 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx #define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u #define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ -/* Endpoint Out */ \ -7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ -/* Endpoint In */ \ -7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + /* Endpoint Out */ \ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ + /* Endpoint In */ \ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u #define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) /* optional interrupt endpoint */ \ // _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? #define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ -7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 #define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) @@ -377,7 +377,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ #else /* Windows 7+ */ - #define TUD_RNDIS_ITF_CLASS 0xE0 + #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER #define TUD_RNDIS_ITF_SUBCLASS 0x01 #define TUD_RNDIS_ITF_PROTOCOL 0x03 #endif -- cgit v1.3.1 From b90b00d43b18e1bed81c81e87ec148479ab1e696 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Apr 2020 18:35:50 +0700 Subject: complete adding subclass and protocol to driver id --- src/device/usbd.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 06fe1f23c..c0e17c058 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -273,6 +273,8 @@ static osal_queue_t _usbd_q; // Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); + static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -793,14 +795,10 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; + tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; - // Check if class is supported - uint8_t drv_id; - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) - { - if ( _usbd_driver[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } + // Find driver id for the interface + uint8_t drv_id = find_driver_id(desc_itf); TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); // Interface number must not be used already TODO alternate interface @@ -824,6 +822,24 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } +// Helper to find class driver id for an interface +// return 0xFF if not found +static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) +{ + for (uint8_t drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code + (driver->subclass == desc_itf->bInterfaceSubClass || driver->subclass == 0xFF) && // match subclass or 0xFF from driver + (driver->protocol == desc_itf->bInterfaceProtocol || driver->protocol == 0xFF)) // match protocol or 0xFF from driver + { + return drv_id; + } + } + + return DRVID_INVALID; +} + // Helper marking endpoint of interface belongs to class driver static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) { -- cgit v1.3.1 From ae6014627408ec938d94a7d2796abd54dfff6b1f Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Apr 2020 22:35:34 +0700 Subject: use explicit all_subclass and all_protocol since 0xFF is stil valid --- src/device/usbd.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index c0e17c058..c1ef482e2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -79,6 +79,12 @@ typedef struct uint8_t subclass; // 0xFF support all values of subclass uint8_t protocol; // 0xFF support all values of protocol + struct TU_ATTR_PACKED + { + uint8_t all_subclass : 1; + uint8_t all_protocol : 1; + }; + void (* init ) (void); void (* reset ) (uint8_t rhport); bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); @@ -94,7 +100,9 @@ static usbd_class_driver_t const _usbd_driver[] = { .class_code = TUSB_CLASS_CDC, .subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .protocol = 0xFF, // all protocols + .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 1, .init = cdcd_init, .reset = cdcd_reset, @@ -111,6 +119,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_MSC, .subclass = MSC_SUBCLASS_SCSI, .protocol = MSC_PROTOCOL_BOT, + .all_subclass = 0, + .all_protocol = 0, .init = mscd_init, .reset = mscd_reset, @@ -125,8 +135,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_HID { .class_code = TUSB_CLASS_HID, - .subclass = 0xFF, // all subclass - .protocol = 0xFF, // all protocol + .subclass = 0x00, + .protocol = 0x00, + .all_subclass = 1, + .all_protocol = 1, .init = hidd_init, .reset = hidd_reset, @@ -143,6 +155,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_AUDIO, .subclass = AUDIO_SUBCLASS_CONTROL, .protocol = AUDIO_PROTOCOL_V1, + .all_subclass = 0, + .all_protocol = 0, .init = midid_init, .open = midid_open, @@ -157,8 +171,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_VENDOR { .class_code = TUSB_CLASS_VENDOR_SPECIFIC, - .subclass = 0xFF, // all subclass - .protocol = 0xFF, // all protocol + .subclass = 0x00, + .protocol = 0x00, + .all_subclass = 1, + .all_protocol = 1, .init = vendord_init, .reset = vendord_reset, @@ -174,7 +190,9 @@ static usbd_class_driver_t const _usbd_driver[] = { .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, .subclass = APP_SUBCLASS_USBTMC, - .protocol = 0xFF, // all protocol + .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 1, .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, @@ -191,6 +209,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, .subclass = APP_SUBCLASS_DFU_RUNTIME, .protocol = DFU_PROTOCOL_RT, + .all_subclass = 0, + .all_protocol = 0, .init = dfu_rtd_init, .reset = dfu_rtd_reset, @@ -209,6 +229,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUD_RNDIS_ITF_CLASS, .subclass = TUD_RNDIS_ITF_SUBCLASS, .protocol = TUD_RNDIS_ITF_PROTOCOL, + .all_subclass = 0, + .all_protocol = 0, .init = netd_init, .reset = netd_reset, @@ -225,6 +247,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_CDC, .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 0, .init = netd_init, .reset = netd_reset, @@ -245,6 +269,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_CDC_DATA, .subclass = 0x00, .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 0, .init = netd_init_data, .reset = NULL, @@ -829,9 +855,9 @@ static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) for (uint8_t drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code - (driver->subclass == desc_itf->bInterfaceSubClass || driver->subclass == 0xFF) && // match subclass or 0xFF from driver - (driver->protocol == desc_itf->bInterfaceProtocol || driver->protocol == 0xFF)) // match protocol or 0xFF from driver + if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code + (driver->subclass == desc_itf->bInterfaceSubClass || driver->all_subclass ) && // match subclass or driver support all + (driver->protocol == desc_itf->bInterfaceProtocol || driver->all_protocol)) // match protocol or driver support all { return drv_id; } -- cgit v1.3.1 From 3ef6e33533c533ef52336fae66e784b7d85e612f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 00:59:56 +0700 Subject: use class driver open() for interface support detection tested with dfu_runtime --- examples/device/dfu_rt/src/main.h | 5 -- examples/device/dfu_rt/src/usb_descriptors.c | 71 +--------------------------- src/class/dfu/dfu_rt_device.c | 4 +- src/class/dfu/dfu_rt_device.h | 2 +- src/device/usbd.c | 37 +++++++++++++-- 5 files changed, 38 insertions(+), 81 deletions(-) delete mode 100644 examples/device/dfu_rt/src/main.h (limited to 'src/device') diff --git a/examples/device/dfu_rt/src/main.h b/examples/device/dfu_rt/src/main.h deleted file mode 100644 index 673247ec7..000000000 --- a/examples/device/dfu_rt/src/main.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H -void led_indicator_pulse(void); - -#endif diff --git a/examples/device/dfu_rt/src/usb_descriptors.c b/examples/device/dfu_rt/src/usb_descriptors.c index 5cd661b2b..3d900efd9 100644 --- a/examples/device/dfu_rt/src/usb_descriptors.c +++ b/examples/device/dfu_rt/src/usb_descriptors.c @@ -77,92 +77,25 @@ uint8_t const * tud_descriptor_device_cb(void) return (uint8_t const *) &desc_device; } -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ -#if CFG_TUD_HID - -uint8_t const desc_hid_report[] = -{ - TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ), - TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), ) -}; - -// Invoked when received GET HID REPORT DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void) -{ - return desc_hid_report; -} - -#endif - //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ enum { -#if CFG_TUD_CDC - ITF_NUM_CDC = 0, - ITF_NUM_CDC_DATA, -#endif - -#if CFG_TUD_MSC - ITF_NUM_MSC, -#endif - -#if CFG_TUD_HID - ITF_NUM_HID, -#endif - -#if CFG_TUD_DFU_RT ITF_NUM_DFU_RT, -#endif - ITF_NUM_TOTAL }; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + \ - CFG_TUD_HID*TUD_HID_DESC_LEN + (CFG_TUD_DFU_RT)*TUD_DFU_RT_DESC_LEN) - -#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force - // endpoint number for MSC to 5 - #define EPNUM_MSC 0x05 -#else - #define EPNUM_MSC 0x03 -#endif - +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_RT_DESC_LEN) uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), -#if CFG_TUD_CDC - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 1, 0x81, 8, 0x02, 0x82, 64), -#endif - -#if CFG_TUD_MSC - // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), -#endif - -#if CFG_TUD_HID - // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10), -#endif - -#if CFG_TUD_DFU_RT // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 7, 0x0d, 1000, 4096), -#endif + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), }; diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index ad1871dad..0ef5fe63f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -61,8 +61,8 @@ bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 (void) rhport; // Ensure this is DFU Runtime - TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); - TU_ASSERT(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); + TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 4348a0f3a..294d993e3 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -58,7 +58,7 @@ typedef enum //--------------------------------------------------------------------+ // Invoked when received new data -TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); +TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.c b/src/device/usbd.c index c1ef482e2..eea344c3b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -76,8 +76,8 @@ enum { DRVID_INVALID = 0xFFu }; typedef struct { uint8_t class_code; - uint8_t subclass; // 0xFF support all values of subclass - uint8_t protocol; // 0xFF support all values of protocol + uint8_t subclass; + uint8_t protocol; struct TU_ATTR_PACKED { @@ -299,7 +299,7 @@ static osal_queue_t _usbd_q; // Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); -static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); +//static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); @@ -346,6 +346,9 @@ static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] = #if CFG_TUD_VENDOR "Vendor", #endif + #if CFG_TUD_DFU_RT + "DFU Runtime", + #endif #if CFG_TUD_USBTMC "USBTMC" #endif @@ -823,6 +826,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; +#if 0 // Find driver id for the interface uint8_t drv_id = find_driver_id(desc_itf); TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); @@ -835,8 +839,31 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_LOG2(" %s open\r\n", _usbd_driver_str[drv_id]); TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); +#else + uint8_t drv_id; + uint16_t itf_len; + + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + + itf_len = 0; + if ( driver->open(rhport, desc_itf, &itf_len) ) + { + // Interface number must not be used already TODO alternate interface + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); + TU_LOG2(" itf_len = %d \r\n", itf_len); + break; + } + } + + // Assert if cannot find a driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && itf_len >= sizeof(tusb_desc_interface_t) ); +#endif + + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); // TODO refactor p_desc += itf_len; // next interface } @@ -848,6 +875,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } +#if 0 // Helper to find class driver id for an interface // return 0xFF if not found static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) @@ -865,6 +893,7 @@ static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) return DRVID_INVALID; } +#endif // Helper marking endpoint of interface belongs to class driver static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -- cgit v1.3.1 From 7fa8d872916789fc5876c2e6bfae0d5a4d6fe379 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 14 Apr 2020 21:10:43 -0500 Subject: usbnet: remove CDC-EEM --- examples/device/net_lwip_webserver/src/main.c | 9 +-- .../device/net_lwip_webserver/src/tusb_config.h | 3 +- .../net_lwip_webserver/src/usb_descriptors.c | 28 +-------- src/class/net/net_device.c | 69 +--------------------- src/device/usbd.c | 10 +--- src/tusb_option.h | 8 --- 6 files changed, 10 insertions(+), 117 deletions(-) (limited to 'src/device') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 26c6401e6..b672ca3bb 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -26,14 +26,9 @@ */ /* -depending on the value of CFG_TUD_NET (tusb_config.h), this can be a RNDIS+CDC-ECM or CDC-EEM USB virtual network adapter +this appears as either a RNDIS or CDC-ECM USB virtual network adapter; the OS picks its preference -OPT_NET_RNDIS_ECM : RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and MacOS hosts -OPT_NET_EEM : CDC-EEM should be valid on Linux hosts - -OPT_NET_RNDIS_ECM should be the best choice, as it makes for a hopefully universal solution. - -You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network option. +RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and macOS hosts The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. */ diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index d8c750d5c..a959968bc 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -79,8 +79,7 @@ #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -#define CFG_TUD_NET OPT_NET_RNDIS_ECM -//#define CFG_TUD_NET OPT_NET_EEM +#define CFG_TUD_NET 1 #ifdef __cplusplus } diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 39c542eca..3e61112e2 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -30,7 +30,7 @@ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. * * Auto ProductID layout's Bitmap: - * [MSB] NET1:NET0 | VENDOR | MIDI | HID | MSC | CDC [LSB] + * [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB] */ #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ @@ -69,11 +69,7 @@ tusb_desc_device_t const desc_device = .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, -#if CFG_TUD_NET == OPT_NET_EEM - .bNumConfigurations = 0x01 -#else .bNumConfigurations = 0x02 -#endif }; // Invoked when received GET DEVICE DESCRIPTOR @@ -89,9 +85,7 @@ uint8_t const * tud_descriptor_device_cb(void) enum { ITF_NUM_CDC = 0, -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM ITF_NUM_CDC_DATA, -#endif ITF_NUM_TOTAL }; @@ -101,12 +95,8 @@ enum CONFIG_NUM_ALTERNATE = 2, }; -#if CFG_TUD_NET == OPT_NET_EEM - #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) -#else - #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) - #define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) -#endif +#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) +#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -121,16 +111,10 @@ static uint8_t const main_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_DEFAULT, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), -#if CFG_TUD_NET == OPT_NET_EEM - // Interface number, description string index, EP data address (out, in) and size. - TUD_CDC_EEM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#else // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#endif }; -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM static uint8_t const alt_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA @@ -139,19 +123,13 @@ static uint8_t const alt_configuration[] = // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), }; -#endif // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { -#if CFG_TUD_NET == OPT_NET_EEM - (void) index; // for multiple configurations - return main_configuration; -#else return (0 == index) ? main_configuration : alt_configuration; -#endif } //--------------------------------------------------------------------+ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 19bc5d2d6..777d0da98 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if ( TUSB_OPT_DEVICE_ENABLED && (CFG_TUD_NET != OPT_NET_NONE) ) +#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET ) #include "net_device.h" #include "device/usbd_pvt.h" @@ -41,21 +41,14 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ typedef struct { uint8_t itf_num; -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM uint8_t ep_notif; bool ecm_mode; -#endif uint8_t ep_in; uint8_t ep_out; } netd_interface_t; -#if CFG_TUD_NET == OPT_NET_EEM - #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 -#else - #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 -#endif +#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) +#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; @@ -113,9 +106,7 @@ static void do_in_xfer(uint8_t *buf, uint16_t len) void netd_report(uint8_t *buf, uint16_t len) { -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); -#endif } //--------------------------------------------------------------------+ @@ -137,16 +128,11 @@ void netd_reset(uint8_t rhport) netd_init(); } -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { // sanity check the descriptor -#if CFG_TUD_NET == OPT_NET_EEM - TU_VERIFY (CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL == itf_desc->bInterfaceSubClass); -#else _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); -#endif // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_notif); @@ -176,7 +162,6 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t return true; } -#endif bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { @@ -223,14 +208,12 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques // Handle class request only TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM TU_VERIFY (_netd_itf.itf_num == request->wIndex); if ( !_netd_itf.ecm_mode && (request->bmRequestType_bit.direction == TUSB_DIR_OUT) ) { rndis_class_set_handler(notify.rndis_buf, request->wLength); } -#endif return true; } @@ -251,9 +234,6 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_EEM - (void)rhport; -#else if (_netd_itf.ecm_mode) { /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ @@ -277,40 +257,15 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); } } -#endif return true; } -struct cdc_eem_packet_header -{ - uint16_t length:14; - uint16_t bmCRC:1; - uint16_t bmType:1; -}; - static void handle_incoming_packet(uint32_t len) { uint8_t *pnt = received; uint32_t size = 0; -#if CFG_TUD_NET == OPT_NET_EEM - struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; - - (void)len; - - if (hdr->bmType) - { - /* EEM Control Packet: discard it */ - tud_network_recv_renew(); - } - else - { - /* EEM Data Packet */ - pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; - size = hdr->length - 4; /* discard the unused CRC-32 */ - } -#else if (_netd_itf.ecm_mode) { size = len; @@ -326,7 +281,6 @@ static void handle_incoming_packet(uint32_t len) size = r->DataLength; } } -#endif bool accepted = false; @@ -378,12 +332,10 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) { if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); } -#endif return true; } @@ -402,11 +354,7 @@ void tud_network_xmit(struct pbuf *p) if (!can_xmit) return; -#if CFG_TUD_NET == OPT_NET_EEM - len = CFG_TUD_NET_PACKET_PREFIX_LEN; -#else len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; -#endif data = transmitted + len; for(q = p; q != NULL; q = q->next) @@ -416,16 +364,6 @@ void tud_network_xmit(struct pbuf *p) len += q->len; } -#if CFG_TUD_NET == OPT_NET_EEM - struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted; - /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */ - data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; - /* adjust length to reflect added fake CRC-32 */ - len += 4; - hdr->bmType = 0; /* EEM Data Packet */ - hdr->length = len - sizeof(struct cdc_eem_packet_header); - hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */ -#else if (!_netd_itf.ecm_mode) { rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; @@ -435,7 +373,6 @@ void tud_network_xmit(struct pbuf *p) hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); hdr->DataLength = len - sizeof(rndis_data_packet_t); } -#endif do_in_xfer(transmitted, len); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 9d15ea4a4..651cbbc7d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -184,7 +184,6 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET -#if CFG_TUD_NET != OPT_NET_EEM /* RNDIS management interface */ { .class_code = TUD_RNDIS_ITF_CLASS, @@ -196,24 +195,18 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif - /* CDC-ECM management interface; CDC-EEM data interface */ + /* CDC-ECM management interface */ { .class_code = TUSB_CLASS_CDC, .init = netd_init, .reset = netd_reset, -#if CFG_TUD_NET == OPT_NET_EEM - .open = netd_open_data, -#else .open = netd_open, -#endif .control_request = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, .sof = NULL, }, /* RNDIS/CDC-ECM data interface */ -#if CFG_TUD_NET != OPT_NET_EEM { .class_code = TUSB_CLASS_CDC_DATA, .init = netd_init_data, @@ -224,7 +217,6 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif #endif }; diff --git a/src/tusb_option.h b/src/tusb_option.h index c2394880f..0826a5aab 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -124,14 +124,6 @@ #define OPT_MODE_HIGH_SPEED 0x10 ///< High speed /** @} */ -/** \defgroup group_supported_netif Supported Network Interface - * \ref CFG_TUD_NET must be defined to one of these - * @{ */ -#define OPT_NET_NONE 0 ///< No network interface -#define OPT_NET_RNDIS_ECM 1 ///< RNDIS+CDC-ECM -#define OPT_NET_EEM 2 ///< CDC-EEM -/** @} */ - #ifndef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif -- cgit v1.3.1 From c74f7e708e055242f8a8e7492f7e1138fd5c5118 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 11:06:35 +0700 Subject: remove class_code/subclass/protocol from driver structure, add name for logging --- src/device/usbd.c | 129 +++++++++++++++++------------------------------------- 1 file changed, 40 insertions(+), 89 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f9c52d841..4db6cd671 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -73,17 +73,17 @@ enum { DRVID_INVALID = 0xFFu }; //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + #define DRIVER_NAME(_name) .name = _name, +#else + #define DRIVER_NAME(_name) +#endif + typedef struct { - uint8_t class_code; - uint8_t subclass; - uint8_t protocol; - - struct TU_ATTR_PACKED - { - uint8_t all_subclass : 1; - uint8_t all_protocol : 1; - }; + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif void (* init ) (void); void (* reset ) (uint8_t rhport); @@ -98,12 +98,7 @@ static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC { - .class_code = TUSB_CLASS_CDC, - .subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .protocol = 0x00, - .all_subclass = 0, - .all_protocol = 1, - + DRIVER_NAME("CDC") .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, @@ -116,12 +111,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MSC { - .class_code = TUSB_CLASS_MSC, - .subclass = MSC_SUBCLASS_SCSI, - .protocol = MSC_PROTOCOL_BOT, - .all_subclass = 0, - .all_protocol = 0, - + DRIVER_NAME("MSC") .init = mscd_init, .reset = mscd_reset, .open = mscd_open, @@ -134,12 +124,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_HID { - .class_code = TUSB_CLASS_HID, - .subclass = 0x00, - .protocol = 0x00, - .all_subclass = 1, - .all_protocol = 1, - + DRIVER_NAME("HID") .init = hidd_init, .reset = hidd_reset, .open = hidd_open, @@ -152,12 +137,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MIDI { - .class_code = TUSB_CLASS_AUDIO, - .subclass = AUDIO_SUBCLASS_CONTROL, - .protocol = AUDIO_PROTOCOL_V1, - .all_subclass = 0, - .all_protocol = 0, - + DRIVER_NAME("MIDI") .init = midid_init, .open = midid_open, .reset = midid_reset, @@ -170,12 +150,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_VENDOR { - .class_code = TUSB_CLASS_VENDOR_SPECIFIC, - .subclass = 0x00, - .protocol = 0x00, - .all_subclass = 1, - .all_protocol = 1, - + DRIVER_NAME("VENDOR") .init = vendord_init, .reset = vendord_reset, .open = vendord_open, @@ -188,12 +163,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_USBTMC { - .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, - .subclass = APP_SUBCLASS_USBTMC, - .protocol = 0x00, - .all_subclass = 0, - .all_protocol = 1, - + DRIVER_NAME("TMC") .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, @@ -206,12 +176,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_RT { - .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, - .subclass = APP_SUBCLASS_DFU_RUNTIME, - .protocol = DFU_PROTOCOL_RT, - .all_subclass = 0, - .all_protocol = 0, - + DRIVER_NAME("DFU-RT") .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, @@ -225,7 +190,12 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_NET /* RNDIS management interface */ { - .class_code = TUD_RNDIS_ITF_CLASS, +// .class_code = TUD_RNDIS_ITF_CLASS, +// .subclass = TUD_RNDIS_ITF_SUBCLASS, +// .protocol = TUD_RNDIS_ITF_PROTOCOL, +// .all_subclass = 0, +// .all_protocol = 0, + DRIVER_NAME("RNDIS") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -236,7 +206,13 @@ static usbd_class_driver_t const _usbd_driver[] = }, /* CDC-ECM management interface */ { - .class_code = TUSB_CLASS_CDC, +// .class_code = TUSB_CLASS_CDC, +// .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, +// .protocol = 0x00, +// .all_subclass = 0, +// .all_protocol = 0, + + DRIVER_NAME("CDC-ECM") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -247,7 +223,12 @@ static usbd_class_driver_t const _usbd_driver[] = }, /* RNDIS/CDC-ECM data interface */ { - .class_code = TUSB_CLASS_CDC_DATA, +// .class_code = TUSB_CLASS_CDC_DATA, +// .subclass = 0x00, +// .protocol = 0x00, +// .all_subclass = 0, +// .all_protocol = 0, + DRIVER_NAME("CDC-DATA") .init = netd_init_data, .reset = NULL, .open = netd_open_data, @@ -303,35 +284,6 @@ static char const* const _usbd_event_str[DCD_EVENT_COUNT] = "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_DFU_RT - "DFU Runtime", - #endif - #if CFG_TUD_USBTMC - "USBTMC" - #endif - #if CFG_TUD_NET - "NET" - #endif -}; - static char const* const _tusb_std_request_str[] = { "Get Status" , @@ -388,7 +340,7 @@ bool tud_init (void) // Init class drivers for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) { - TU_LOG2("%s init\r\n", _usbd_driver_str[i]); + TU_LOG2("%s init\r\n", _usbd_driver[i].name); _usbd_driver[i].init(); } @@ -497,7 +449,7 @@ void tud_task (void) 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]); + TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } } @@ -542,7 +494,7 @@ static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_req TU_ASSERT(_usbd_driver[drvid].control_request); usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); - TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]); + TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); return _usbd_driver[drvid].control_request(rhport, request); } @@ -811,7 +763,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_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); #else @@ -827,9 +779,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { // Interface number must not be used already TODO alternate interface TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - TU_LOG2(" itf_len = %d \r\n", itf_len); break; } } -- cgit v1.3.1 From 1faa3b2768f625ffcc06429b7266c88e11605bfc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 11:41:26 +0700 Subject: tested usbnet, completely remove class code --- src/class/net/net_device.c | 17 ++++++++++++++--- src/device/usbd.c | 18 ++---------------- 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'src/device') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 777d0da98..8d0cb5d37 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -130,13 +130,22 @@ void netd_reset(uint8_t rhport) bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { - // sanity check the descriptor - _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); - TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); + bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && + TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); + + bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0x00 == itf_desc->bInterfaceProtocol); + + TU_VERIFY ( is_rndis || is_ecm ); // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_notif); + // sanity check the descriptor + _netd_itf.ecm_mode = is_ecm; + //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; @@ -165,6 +174,8 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { + TU_VERIFY(TUSB_CLASS_CDC_DATA == itf_desc->bInterfaceClass); + // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_in); diff --git a/src/device/usbd.c b/src/device/usbd.c index 4db6cd671..0f60117ee 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,11 +190,6 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_NET /* RNDIS management interface */ { -// .class_code = TUD_RNDIS_ITF_CLASS, -// .subclass = TUD_RNDIS_ITF_SUBCLASS, -// .protocol = TUD_RNDIS_ITF_PROTOCOL, -// .all_subclass = 0, -// .all_protocol = 0, DRIVER_NAME("RNDIS") .init = netd_init, .reset = netd_reset, @@ -204,14 +199,9 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* CDC-ECM management interface */ { -// .class_code = TUSB_CLASS_CDC, -// .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, -// .protocol = 0x00, -// .all_subclass = 0, -// .all_protocol = 0, - DRIVER_NAME("CDC-ECM") .init = netd_init, .reset = netd_reset, @@ -221,13 +211,9 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ { -// .class_code = TUSB_CLASS_CDC_DATA, -// .subclass = 0x00, -// .protocol = 0x00, -// .all_subclass = 0, -// .all_protocol = 0, DRIVER_NAME("CDC-DATA") .init = netd_init_data, .reset = NULL, -- cgit v1.3.1 From 3bfb402d8ce0fda082f77d4e552537a51f93375c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 11:44:12 +0700 Subject: clean up --- src/device/usbd.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 0f60117ee..eabe24be0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -739,29 +739,15 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; -#if 0 - // Find driver id for the interface - uint8_t drv_id = find_driver_id(desc_itf); - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); - - // Interface number must not be used already TODO alternate interface - TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - uint16_t itf_len=0; - TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); - TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); -#else uint8_t drv_id; - uint16_t itf_len; + uint16_t drv_len; for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - itf_len = 0; - if ( driver->open(rhport, desc_itf, &itf_len) ) + drv_len = 0; + if ( driver->open(rhport, desc_itf, &drv_len) ) { // Interface number must not be used already TODO alternate interface TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); @@ -771,13 +757,12 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - // Assert if cannot find a driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && itf_len >= sizeof(tusb_desc_interface_t) ); -#endif + // Assert if cannot find supported driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); // TODO refactor + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor - p_desc += itf_len; // next interface + p_desc += drv_len; // next interface } } -- cgit v1.3.1 From 93ffe317b262df34afe74e216017411ac70324b5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 13:53:50 +0700 Subject: clean up --- src/device/usbd.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index eabe24be0..4587a2cc7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -241,8 +241,6 @@ static osal_queue_t _usbd_q; // Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); -//static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); - static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -772,26 +770,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } -#if 0 -// Helper to find class driver id for an interface -// return 0xFF if not found -static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) -{ - for (uint8_t drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) - { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code - (driver->subclass == desc_itf->bInterfaceSubClass || driver->all_subclass ) && // match subclass or driver support all - (driver->protocol == desc_itf->bInterfaceProtocol || driver->all_protocol)) // match protocol or driver support all - { - return drv_id; - } - } - - return DRVID_INVALID; -} -#endif - // Helper marking endpoint of interface belongs to class driver static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) { -- cgit v1.3.1 From b03b9eb93991c561610a01c379154e7db55e9f4b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 15:14:26 +0700 Subject: change cdc template protocol to None --- src/class/cdc/cdc_host.c | 2 +- src/device/usbd.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 595e7fd62..5e45e8f6b 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -86,7 +86,7 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) { // TODO consider all AT Command as serial candidate return tuh_cdc_mounted(dev_addr) && - (CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].itf_protocol) && + (CDC_COMM_PROTOCOL_NONE <= cdch_data[dev_addr-1].itf_protocol) && (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); } diff --git a/src/device/usbd.h b/src/device/usbd.h index 7b04ef9a7..acefb6943 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -183,9 +183,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, 0,\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ /* CDC Header */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC Call */\ -- cgit v1.3.1 From 0b39168dc25ad970a9829ada2c0e6af26cb0d1ed Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 15:40:53 +0700 Subject: add IAD for CDC ECM, remove EEM descriptor template --- src/device/usbd.h | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index acefb6943..3b409e70b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -343,11 +343,13 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- CDC-ECM -------------// // Length of template descriptor: 71 bytes -#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+9+7+7) +#define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ /* CDC Control Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ /* CDC-ECM Header */\ @@ -410,22 +412,6 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- CDC-EEM -------------// - -// Length of template descriptor: 23 bytes -#define TUD_CDC_EEM_DESC_LEN (9+7+7) - -// CDC-EEM Descriptor Template -// Interface number, description string index, EP data address (out, in) and size. -#define TUD_CDC_EEM_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* EEM Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL, CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL, _stridx,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - - #ifdef __cplusplus } #endif -- cgit v1.3.1 From d315393fbb39ab6a70ea2c636d28305d9777ff97 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 16:18:24 +0700 Subject: use IAD to assign itf2drv mapping correctly merge net_data back into net driver --- src/class/cdc/cdc_device.c | 4 +- src/class/net/net_device.c | 30 ++++----------- src/class/net/net_device.h | 2 - src/device/usbd.c | 92 ++++++++++++++++++++++------------------------ 4 files changed, 53 insertions(+), 75 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 04c73da78..95b14ba54 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -262,12 +262,12 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8d0cb5d37..8bbce2305 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -117,10 +117,6 @@ void netd_init(void) tu_memclr(&_netd_itf, sizeof(_netd_itf)); } -void netd_init_data(void) -{ -} - void netd_reset(uint8_t rhport) { (void) rhport; @@ -166,32 +162,21 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } - return true; -} - -bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) -{ - TU_VERIFY(TUSB_CLASS_CDC_DATA == itf_desc->bInterfaceClass); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); - //------------- Data Interface -------------// - while ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + // TODO extract Alt Interface 0 & 1 + while ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - (*p_length) += sizeof(tusb_desc_interface_t); } - if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); @@ -207,6 +192,7 @@ bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint // prepare for incoming packets tud_network_recv_renew(); + return true; } diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 6914ed050..67cd99933 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,10 +73,8 @@ void tud_network_xmit(struct pbuf *p); // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void netd_init (void); -void netd_init_data (void); void netd_reset (uint8_t rhport); bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool netd_open_data (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 4587a2cc7..ad5a32f92 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -188,9 +188,8 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET - /* RNDIS management interface */ { - DRIVER_NAME("RNDIS") + DRIVER_NAME("NET") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -199,30 +198,6 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, - - /* CDC-ECM management interface */ - { - DRIVER_NAME("CDC-ECM") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_request = netd_control_request, - .control_complete = netd_control_complete, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, - - /* RNDIS/CDC-ECM data interface */ - { - DRIVER_NAME("CDC-DATA") - .init = netd_init_data, - .reset = NULL, - .open = netd_open_data, - .control_request = NULL, - .control_complete = NULL, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, #endif }; @@ -611,9 +586,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_SET_INTERFACE: { uint8_t const alternate = (uint8_t) p_request->wValue; + (void) alternate; // TODO not support alternate interface yet - TU_ASSERT(alternate == 0); +// TU_ASSERT(alternate == 0); tud_control_status(rhport, p_request); } break; @@ -727,41 +703,59 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - // Each interface always starts with Interface or Association descriptor + tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + + // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - p_desc = tu_desc_next(p_desc); // ignore Interface Association - }else - { - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); + desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + p_desc = tu_desc_next(p_desc); // next to Interface + } - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - uint8_t drv_id; - uint16_t drv_len; + tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + uint8_t drv_id; + uint16_t drv_len; - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + + drv_len = 0; + if ( driver->open(rhport, desc_itf, &drv_len) ) { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + // Interface number must not be used already + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) + TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + // If IAD exist, assign all interfaces to the same driver + if (desc_itf_assoc) { - // Interface number must not be used already TODO alternate interface - TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - break; + // IAD's first interface number and class/subclass/protocol should match with opened interface + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && + desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && + desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + + for(uint8_t i=1; ibInterfaceCount; i++) + { + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; + } } + + break; } + } - // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + // Assert if cannot find supported driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor - p_desc += drv_len; // next interface - } + p_desc += drv_len; // next interface } // invoke callback -- cgit v1.3.1 From caa1dceed97d841ca4176d96e324de976948f327 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 17:51:02 +0700 Subject: implement alternate setInterface() request mostly forward these request (recipient = interface) to class driver. --- src/class/net/net_device.c | 158 +++++++++++++++++++++++++++++++++------------ src/device/usbd.c | 37 +---------- 2 files changed, 118 insertions(+), 77 deletions(-) (limited to 'src/device') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8bbce2305..575a15edd 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -40,11 +40,20 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ //--------------------------------------------------------------------+ typedef struct { - uint8_t itf_num; + uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface + uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active + uint8_t ep_notif; - bool ecm_mode; uint8_t ep_in; uint8_t ep_out; + + bool ecm_mode; + + // Endpoint descriptor use to open/close when receving SetInterface + // TODO since configuration descriptor may not be long-lived memory, we should + // keep a copy of endpoint attribute instead + uint8_t const * ecm_desc_epdata; + } netd_interface_t; #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) @@ -145,8 +154,8 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; - uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); + uint8_t const * p_desc = tu_desc_next( itf_desc ); // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) @@ -167,31 +176,44 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t } //------------- Data Interface -------------// - // TODO extract Alt Interface 0 & 1 - while ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + // - RNDIS Data followed immediately by a pair of endpoints + // - CDC-ECM data interface has 2 alternate settings + // - 0 : zero endpoints for inactive (default) + // - 1 : IN & OUT endpoints for active networking + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); + + do { - // next to endpoint descriptor + tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass); + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - } + }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) ); - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) + // Pair of endpoints + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); + + if ( _netd_itf.ecm_mode ) + { + // ECM by default is in-active, save the endpoint attribute + // to open later when received setInterface + _netd_itf.ecm_desc_epdata = p_desc; + }else { - // Open endpoint pair + // Open endpoint pair for RNDIS TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - (*p_length) += 2*sizeof(tusb_desc_endpoint_t); - } + tud_network_init_cb(); - tud_network_init_cb(); + // we are ready to transmit a packet + can_xmit = true; - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); + // prepare for incoming packets + tud_network_recv_renew(); + } + (*p_length) += 2*sizeof(tusb_desc_endpoint_t); return true; } @@ -226,33 +248,83 @@ static void ecm_report(bool nc) // return false to stall control endpoint (e.g unsupported request) bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) + { + case TUSB_REQ_GET_INTERFACE: + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + break; + + case TUSB_REQ_SET_INTERFACE: + { + // Request to enable/disable network activities on ACM-ECM only + TU_ASSERT(_netd_itf.ecm_mode); + + _netd_itf.itf_data_alt = (uint8_t) request->wValue; + + if ( _netd_itf.itf_data_alt ) + { + // TODO since we don't actually close endpoint + // hack here to not re-open it + if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + { + TU_ASSERT(_netd_itf.ecm_desc_epdata); + TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + // TODO should have opposite callback for application to disable network !! + tud_network_init_cb(); + can_xmit = true; // we are ready to transmit a packet + tud_network_recv_renew(); // prepare for incoming packets + } + }else + { + // TODO close the endpoint pair + // For now pretend that we did, this should have no harm since host won't try to + // communicate with the endpoints again + // _netd_itf.ep_in = _netd_itf.ep_out = 0 + } + + tud_control_status(rhport, request); + } + break; - TU_VERIFY (_netd_itf.itf_num == request->wIndex); + // unsupported request + default: return false; + } + break; - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, msglen); - } - else - { - tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); - } + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + + if (_netd_itf.ecm_mode) + { + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } + } + else + { + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } + } + break; + + // unsupported request + default: return false; } return true; diff --git a/src/device/usbd.c b/src/device/usbd.c index ad5a32f92..1df850165 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -571,40 +571,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const drvid = _usbd_dev.itf2drv[itf]; TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - switch ( p_request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - // TODO not support alternate interface yet - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const alternate = (uint8_t) p_request->wValue; - (void) alternate; - - // TODO not support alternate interface yet -// TU_ASSERT(alternate == 0); - tud_control_status(rhport, p_request); - } - break; - - default: - // forward to class driver: "STD request to Interface" - // GET HID REPORT DESCRIPTOR falls into this case - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); - break; - } - }else - { - // forward to class driver: "non-STD request to Interface" - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); - } + // all requests to Interface (STD or Class) is forwarded to class driver. + // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE + TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); } break; -- cgit v1.3.1 From 0ddbda08cba7895d4710f787c230af074c25cb0f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 23:08:49 +0700 Subject: always response if GET_INTERFACE even if class driver does not support alt interface --- src/device/usbd.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 1df850165..cf16b28c8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -573,7 +573,16 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); + if ( !invoke_class_control(rhport, drvid, p_request) ) + { + // For STD GET_INTERFACE even if class driver doesn't support alternate setting + // It is still mandatory to response with value of zero + TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && + TUSB_REQ_GET_INTERFACE == p_request->bRequest); + + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + } } break; -- cgit v1.3.1 From 2eed58d0962849014ab3166d4a3f0d3677d32c01 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 11:13:54 +0700 Subject: per review --- src/class/net/net_device.c | 16 +++++++++++----- src/device/usbd.c | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'src/device') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8cb2e2e0b..0f2ccbd44 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -255,20 +255,26 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } break; case TUSB_REQ_SET_INTERFACE: { uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; - // Request to enable/disable network activities on ACM-ECM only - TU_ASSERT(_netd_itf.ecm_mode); + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - // Only valid for Data Interface - TU_ASSERT(_netd_itf.itf_num+1 == req_itfnum); + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); - _netd_itf.itf_data_alt = (uint8_t) request->wValue; + _netd_itf.itf_data_alt = req_alt; if ( _netd_itf.itf_data_alt ) { diff --git a/src/device/usbd.c b/src/device/usbd.c index cf16b28c8..29845ff36 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -575,8 +575,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE if ( !invoke_class_control(rhport, drvid, p_request) ) { - // For STD GET_INTERFACE even if class driver doesn't support alternate setting - // It is still mandatory to response with value of zero + // For GET_INTERFACE, it is mandatory to respond even if the class + // driver doesn't use alternate settings. TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && TUSB_REQ_GET_INTERFACE == p_request->bRequest); -- cgit v1.3.1 From 969121df4f1025481cfe085397c8dede454f4537 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 15:52:45 +0700 Subject: added dcd disconnect/connect to lpc17/40 --- src/device/dcd.h | 6 +++--- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index f4e6edb95..08b217fa9 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -106,10 +106,10 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num); // Wake up host void dcd_remote_wakeup(uint8_t rhport); -// Connect or disconnect D+/D- line pull-up resistor. -// Defined in dcd source if MCU has internal pull-up. -// Otherwise, may be defined in BSP. +// Connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; + +// Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 884260f31..b4a11f49c 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -181,9 +181,7 @@ void dcd_init(uint8_t rhport) LPC_USB->UDCAH = (uint32_t) _dcd.udca; LPC_USB->DMAIntEn = (DMA_INT_END_OF_XFER_MASK /*| DMA_INT_NEW_DD_REQUEST_MASK*/ | DMA_INT_ERROR_MASK); - sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); // connect - - // USB IRQ priority should be set by application previously + // Clear pending IRQ NVIC_ClearPendingIRQ(USB_IRQn); } @@ -219,6 +217,16 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, SIE_DEV_STATUS_CONNECT_STATUS_MASK); +} + +void dcd_disconnect(uint8_t rhport) +{ + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 0); +} + //--------------------------------------------------------------------+ // CONTROL HELPER //--------------------------------------------------------------------+ -- cgit v1.3.1 From 2994d100cd6198a4c90dce667f52fde07fe4a073 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 16 Apr 2020 09:57:56 -0400 Subject: Remove transfer queue filtering. May need to be revisited later. --- src/device/usbd.c | 47 ++--------------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 75c0a3720..55a9ccebc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1064,50 +1064,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) } /** - * Remove queued xfer complete messages from event queue, - * for a particular ep. + * usbd_edpt_close will disable an endpoint. * - * Must be called with interrupts enabled. - */ -static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) -{ - dcd_event_t ev_sentinal = - { - .event_id = DCD_EVENT_COUNT, ///< This is an invalid event ID. - }; - dcd_event_t event; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - dcd_int_disable(rhport); - // Queue sentinal element - TU_ASSERT(osal_queue_send(_usbd_q, &ev_sentinal, true), /**/); - - TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); - - while(event.event_id != DCD_EVENT_COUNT) - { - if((event.rhport == rhport) && (event.event_id == DCD_EVENT_XFER_COMPLETE) - && (event.xfer_complete.ep_addr == ep_addr)) - { - _usbd_dev.ep_status[epnum][ep_dir].busy = false; - } - else - { - TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); - } - TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); - } - - dcd_int_enable(rhport); -} - -/** - * usbd_edpt_close will disable an endpoint, and clear all pending transfers - * through the particular endpoint. + * In progress transfers on this EP may be delivered after this call. * - * It must be called from the usb task (e.g. from the control request - * handler while handling SET_ALTERNATE), with interrupts enabled. */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { @@ -1116,9 +1076,6 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) dcd_edpt_close(rhport, ep_addr); - /* Now, in progress transfers have to be expunged */ - usbd_abort_transfers(rhport, ep_addr); - return; } -- cgit v1.3.1 From 50be9d7c3ad08fdc8a79f38606111cf83c84efb9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 12:27:53 +0700 Subject: mass rename tud/dcd_irq_handler to tud/dcd_init_handler --- changelog.md | 4 ++-- docs/porting.md | 2 +- examples/device/board_test/Makefile | 2 +- hw/bsp/adafruit_clue/adafruit_clue.c | 2 +- hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c | 2 +- hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c | 2 +- hw/bsp/circuitplayground_express/circuitplayground_express.c | 2 +- hw/bsp/ea4088qs/ea4088qs.c | 2 +- hw/bsp/ea4357/ea4357.c | 4 ++-- hw/bsp/feather_m0_express/feather_m0_express.c | 2 +- hw/bsp/feather_m4_express/feather_m4_express.c | 8 ++++---- hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c | 2 +- hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c | 2 +- hw/bsp/feather_stm32f405/feather_stm32f405.c | 2 +- hw/bsp/fomu/fomu.c | 2 +- hw/bsp/itsybitsy_m0/itsybitsy_m0.c | 2 +- hw/bsp/itsybitsy_m4/itsybitsy_m4.c | 8 ++++---- hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c | 2 +- hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c | 2 +- hw/bsp/lpcxpresso1347/lpcxpresso1347.c | 2 +- hw/bsp/lpcxpresso1549/lpcxpresso1549.c | 2 +- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c | 2 +- hw/bsp/lpcxpresso54114/lpcxpresso54114.c | 2 +- hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c | 4 ++-- hw/bsp/mbed1768/mbed1768.c | 2 +- hw/bsp/mcb1800/mcb1800.c | 4 ++-- hw/bsp/metro_m0_express/metro_m0_express.c | 2 +- hw/bsp/metro_m4_express/metro_m4_express.c | 8 ++++---- hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c | 2 +- hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c | 2 +- hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c | 2 +- hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c | 4 ++-- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 4 ++-- hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c | 4 ++-- hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c | 2 +- hw/bsp/ngx4330/ngx4330.c | 4 ++-- hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c | 2 +- hw/bsp/nutiny_nuc121s/nutiny_nuc121.c | 2 +- hw/bsp/nutiny_nuc125s/nutiny_nuc125.c | 2 +- hw/bsp/nutiny_nuc126v/nutiny_nuc126.c | 2 +- hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c | 2 +- hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c | 2 +- hw/bsp/pca10056/pca10056.c | 2 +- hw/bsp/pca10059/pca10059.c | 2 +- hw/bsp/pca10100/pca10100.c | 2 +- hw/bsp/pyboardv11/pyboardv11.c | 2 +- hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c | 2 +- hw/bsp/samg55xplained/samg55xplained.c | 2 +- hw/bsp/seeeduino_xiao/seeeduino_xiao.c | 2 +- hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c | 2 +- hw/bsp/stm32f072disco/stm32f072disco.c | 2 +- hw/bsp/stm32f103bluepill/stm32f103bluepill.c | 6 +++--- hw/bsp/stm32f207nucleo/stm32f207nucleo.c | 2 +- hw/bsp/stm32f303disco/stm32f303disco.c | 6 +++--- hw/bsp/stm32f401blackpill/stm32f401blackpill.c | 2 +- hw/bsp/stm32f407disco/stm32f407disco.c | 2 +- hw/bsp/stm32f411blackpill/stm32f411blackpill.c | 2 +- hw/bsp/stm32f411disco/stm32f411disco.c | 2 +- hw/bsp/stm32f412disco/stm32f412disco.c | 2 +- hw/bsp/stm32f767nucleo/stm32f767nucleo.c | 2 +- hw/bsp/stm32h743nucleo/stm32h743nucleo.c | 2 +- hw/bsp/stm32l0538disco/stm32l0538disco.c | 2 +- hw/bsp/stm32l476disco/stm32l476disco.c | 2 +- hw/bsp/teensy_40/teensy40.c | 4 ++-- src/device/dcd.h | 2 +- src/device/usbd.h | 2 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 4 ++-- src/portable/microchip/samd/dcd_samd.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 2 +- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 2 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 2 +- src/portable/nxp/transdimension/dcd_transdimension.c | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- src/portable/valentyusb/eptri/dcd_eptri.c | 2 +- 81 files changed, 104 insertions(+), 104 deletions(-) (limited to 'src/device') diff --git a/changelog.md b/changelog.md index e25e93721..807b4dc3a 100644 --- a/changelog.md +++ b/changelog.md @@ -4,7 +4,7 @@ ### Breaking -- TinyUSB does not directly implement USB IRQ Handler function anymore. Application must implement IRQ Handler and invoke `tud_irq_handler(rhport)`. This is due to: +- TinyUSB does not directly implement USB IRQ Handler function anymore. Application must implement IRQ Handler and invoke `tud_int_handler(rhport)`. This is due to: - IRQ Handler name can be different across system depending on the startup - Some OS need to execute enterISR()/exitISR() to work properly, also tracing tool may need to insert trace ISR enter/exit to record usb event @@ -12,7 +12,7 @@ ### MCU -- All default IRQ Handler is renamed to `dcd_irq_handler()` +- All default IRQ Handler is renamed to `dcd_int_handler()` ## 0.6.0 - 2019.03.30 diff --git a/docs/porting.md b/docs/porting.md index 83b08da27..fabf24510 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -68,7 +68,7 @@ This function should leave an internal D+/D- pull-up in its default power-on sta Enables or disables the USB device interrupt(s). May be used to prevent concurrency issues when mutating data structures shared between main code and the interrupt handler. -##### dcd_irq_handler +##### dcd_int_handler Processes all the hardware generated events e.g Bus reset, new data packet from host etc ... It will be called by application in the MCU USB interrupt handler. diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index 66d8571cf..b65575ce6 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -13,6 +13,6 @@ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) # This can cause some TinyUSB API missing, this hack to allow us to fill those API # to pass the compilation process CFLAGS += \ - -D"tud_irq_handler(x)= " \ + -D"tud_int_handler(x)= " \ include ../../rules.mk diff --git a/hw/bsp/adafruit_clue/adafruit_clue.c b/hw/bsp/adafruit_clue/adafruit_clue.c index 54b822fc9..cb5c2f223 100644 --- a/hw/bsp/adafruit_clue/adafruit_clue.c +++ b/hw/bsp/adafruit_clue/adafruit_clue.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c index a3ab49a5d..d2d126311 100644 --- a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c +++ b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c index 17e619704..9638b3cc8 100644 --- a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c +++ b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/circuitplayground_express/circuitplayground_express.c b/hw/bsp/circuitplayground_express/circuitplayground_express.c index 0e2583383..4ff95b2ff 100644 --- a/hw/bsp/circuitplayground_express/circuitplayground_express.c +++ b/hw/bsp/circuitplayground_express/circuitplayground_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 756c9d384..7fc047490 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -37,7 +37,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index 87b19260e..87f1e83cc 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -240,7 +240,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -251,7 +251,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/hw/bsp/feather_m0_express/feather_m0_express.c b/hw/bsp/feather_m0_express/feather_m0_express.c index 83b20793e..4eb157c8f 100644 --- a/hw/bsp/feather_m0_express/feather_m0_express.c +++ b/hw/bsp/feather_m0_express/feather_m0_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_m4_express/feather_m4_express.c b/hw/bsp/feather_m4_express/feather_m4_express.c index 8b4764cd0..72183c612 100644 --- a/hw/bsp/feather_m4_express/feather_m4_express.c +++ b/hw/bsp/feather_m4_express/feather_m4_express.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_1_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_2_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_3_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c index e36615ee1..34e7fa8ec 100644 --- a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c +++ b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c index fb4ef9af2..284ae27b1 100644 --- a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c +++ b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_stm32f405/feather_stm32f405.c b/hw/bsp/feather_stm32f405/feather_stm32f405.c index bdd216272..a8c782da5 100644 --- a/hw/bsp/feather_stm32f405/feather_stm32f405.c +++ b/hw/bsp/feather_stm32f405/feather_stm32f405.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/fomu/fomu.c b/hw/bsp/fomu/fomu.c index 404b72333..25e5e9613 100644 --- a/hw/bsp/fomu/fomu.c +++ b/hw/bsp/fomu/fomu.c @@ -63,7 +63,7 @@ void isr(void) #if CFG_TUSB_RHPORT0_MODE == OPT_MODE_DEVICE if (irqs & (1 << USB_INTERRUPT)) { - tud_irq_handler(0); + tud_int_handler(0); } #endif if (irqs & (1 << TIMER0_INTERRUPT)) { diff --git a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c index 93661b899..652bc6b3d 100644 --- a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c +++ b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c index 3ae9565c9..0195a9fc4 100644 --- a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c +++ b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_1_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_2_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_3_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c b/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c index 6f2ae80e8..11f1797a2 100644 --- a/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c +++ b/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //---------------------------------------------------------------- ----+ diff --git a/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c b/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c index 193df3bb1..e33a5c6e5 100644 --- a/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c +++ b/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1347/lpcxpresso1347.c b/hw/bsp/lpcxpresso1347/lpcxpresso1347.c index 14a0009e4..a9a67ae3a 100644 --- a/hw/bsp/lpcxpresso1347/lpcxpresso1347.c +++ b/hw/bsp/lpcxpresso1347/lpcxpresso1347.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1549/lpcxpresso1549.c b/hw/bsp/lpcxpresso1549/lpcxpresso1549.c index 2ae8d7506..a10cd38ec 100644 --- a/hw/bsp/lpcxpresso1549/lpcxpresso1549.c +++ b/hw/bsp/lpcxpresso1549/lpcxpresso1549.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 3b5c9dcab..cc6fd95ae 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -37,7 +37,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c b/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c index 2a314388d..6bade7743 100644 --- a/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c +++ b/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ void USB0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso54114/lpcxpresso54114.c b/hw/bsp/lpcxpresso54114/lpcxpresso54114.c index 847accb67..3bccc4bd7 100644 --- a/hw/bsp/lpcxpresso54114/lpcxpresso54114.c +++ b/hw/bsp/lpcxpresso54114/lpcxpresso54114.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ void USB0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c b/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c index 31519dc8f..a17cffe9c 100644 --- a/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c +++ b/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c @@ -35,12 +35,12 @@ //--------------------------------------------------------------------+ void USB0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB1_IRQHandler(void) { - tud_irq_handler(1); + tud_int_handler(1); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index cda508803..5963ad8ec 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -145,7 +145,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 43dc7bfbb..ae9f1b62f 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -37,7 +37,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -48,7 +48,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/hw/bsp/metro_m0_express/metro_m0_express.c b/hw/bsp/metro_m0_express/metro_m0_express.c index 83b20793e..4eb157c8f 100644 --- a/hw/bsp/metro_m0_express/metro_m0_express.c +++ b/hw/bsp/metro_m0_express/metro_m0_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m4_express/metro_m4_express.c b/hw/bsp/metro_m4_express/metro_m4_express.c index 61b270de0..b489b79c4 100644 --- a/hw/bsp/metro_m4_express/metro_m4_express.c +++ b/hw/bsp/metro_m4_express/metro_m4_express.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_1_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_2_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_3_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c index d061c0e04..c682ace8d 100644 --- a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c +++ b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c index 874e4517e..214077a4a 100644 --- a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c +++ b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c index 17727c0ab..f32ec5401 100644 --- a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c +++ b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c @@ -124,7 +124,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c index ed29be4d3..be0ae3ea8 100644 --- a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c +++ b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index ed29be4d3..be0ae3ea8 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c index ed29be4d3..be0ae3ea8 100644 --- a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c +++ b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c index 621d21d55..e9336b634 100644 --- a/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c +++ b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index a789a8819..5296ddcb3 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -229,7 +229,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -240,7 +240,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c index 99db842ac..870a290dd 100644 --- a/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c +++ b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c b/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c index 115c88165..7117a3422 100644 --- a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c +++ b/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c b/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c index 115c88165..7117a3422 100644 --- a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c +++ b/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c b/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c index 214873f8c..da62e7bd2 100644 --- a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c +++ b/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c index 906d44454..0d78116b8 100644 --- a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c +++ b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c index 9018e698d..49e66d2d0 100644 --- a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c +++ b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/pca10056/pca10056.c b/hw/bsp/pca10056/pca10056.c index ec34dbb9e..30df50124 100644 --- a/hw/bsp/pca10056/pca10056.c +++ b/hw/bsp/pca10056/pca10056.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10059/pca10059.c b/hw/bsp/pca10059/pca10059.c index 72a85a9fa..2a2a45eb2 100644 --- a/hw/bsp/pca10059/pca10059.c +++ b/hw/bsp/pca10059/pca10059.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10100/pca10100.c b/hw/bsp/pca10100/pca10100.c index ec34dbb9e..30df50124 100644 --- a/hw/bsp/pca10100/pca10100.c +++ b/hw/bsp/pca10100/pca10100.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/pyboardv11/pyboardv11.c b/hw/bsp/pyboardv11/pyboardv11.c index e6f45b339..5c910484d 100644 --- a/hw/bsp/pyboardv11/pyboardv11.c +++ b/hw/bsp/pyboardv11/pyboardv11.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c index 62e6fa045..97f3cbf05 100644 --- a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c +++ b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/samg55xplained/samg55xplained.c b/hw/bsp/samg55xplained/samg55xplained.c index 4f894a2bc..c9bc0656e 100644 --- a/hw/bsp/samg55xplained/samg55xplained.c +++ b/hw/bsp/samg55xplained/samg55xplained.c @@ -100,7 +100,7 @@ void board_init(void) void UDP_Handler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c index d8dbd2b1c..0456228da 100644 --- a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c +++ b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c index 132da8aee..ded5a9c85 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c +++ b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f072disco/stm32f072disco.c b/hw/bsp/stm32f072disco/stm32f072disco.c index 9a3a354ef..2815beef4 100644 --- a/hw/bsp/stm32f072disco/stm32f072disco.c +++ b/hw/bsp/stm32f072disco/stm32f072disco.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f103bluepill/stm32f103bluepill.c b/hw/bsp/stm32f103bluepill/stm32f103bluepill.c index dbb58032c..600f3aaef 100644 --- a/hw/bsp/stm32f103bluepill/stm32f103bluepill.c +++ b/hw/bsp/stm32f103bluepill/stm32f103bluepill.c @@ -32,17 +32,17 @@ //--------------------------------------------------------------------+ void USB_HP_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_LP_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } void USBWakeUp_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f207nucleo/stm32f207nucleo.c b/hw/bsp/stm32f207nucleo/stm32f207nucleo.c index 3d1765e8b..619c90d68 100644 --- a/hw/bsp/stm32f207nucleo/stm32f207nucleo.c +++ b/hw/bsp/stm32f207nucleo/stm32f207nucleo.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f303disco/stm32f303disco.c b/hw/bsp/stm32f303disco/stm32f303disco.c index 444472a79..1fe908bc3 100644 --- a/hw/bsp/stm32f303disco/stm32f303disco.c +++ b/hw/bsp/stm32f303disco/stm32f303disco.c @@ -38,7 +38,7 @@ // the highest possible transfer rate. void USB_HP_CAN_TX_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } // USB low-priority interrupt (Channel 20): Triggered by all USB events @@ -46,14 +46,14 @@ void USB_HP_CAN_TX_IRQHandler(void) // interrupt source before serving the interrupt. void USB_LP_CAN_RX0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } // USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB // Suspend mode. void USBWakeUp_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f401blackpill/stm32f401blackpill.c b/hw/bsp/stm32f401blackpill/stm32f401blackpill.c index 90507e178..f9daa364f 100644 --- a/hw/bsp/stm32f401blackpill/stm32f401blackpill.c +++ b/hw/bsp/stm32f401blackpill/stm32f401blackpill.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f407disco/stm32f407disco.c b/hw/bsp/stm32f407disco/stm32f407disco.c index d317ae7df..ce3b67da0 100644 --- a/hw/bsp/stm32f407disco/stm32f407disco.c +++ b/hw/bsp/stm32f407disco/stm32f407disco.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f411blackpill/stm32f411blackpill.c b/hw/bsp/stm32f411blackpill/stm32f411blackpill.c index 0d085b20e..af1cf70ed 100644 --- a/hw/bsp/stm32f411blackpill/stm32f411blackpill.c +++ b/hw/bsp/stm32f411blackpill/stm32f411blackpill.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f411disco/stm32f411disco.c b/hw/bsp/stm32f411disco/stm32f411disco.c index 3f95afb09..5d432fe23 100644 --- a/hw/bsp/stm32f411disco/stm32f411disco.c +++ b/hw/bsp/stm32f411disco/stm32f411disco.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f412disco/stm32f412disco.c b/hw/bsp/stm32f412disco/stm32f412disco.c index be0731fb6..669891d68 100644 --- a/hw/bsp/stm32f412disco/stm32f412disco.c +++ b/hw/bsp/stm32f412disco/stm32f412disco.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f767nucleo/stm32f767nucleo.c b/hw/bsp/stm32f767nucleo/stm32f767nucleo.c index b9025a42c..8328c361a 100644 --- a/hw/bsp/stm32f767nucleo/stm32f767nucleo.c +++ b/hw/bsp/stm32f767nucleo/stm32f767nucleo.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32h743nucleo/stm32h743nucleo.c b/hw/bsp/stm32h743nucleo/stm32h743nucleo.c index 9a758988c..bb768eb40 100644 --- a/hw/bsp/stm32h743nucleo/stm32h743nucleo.c +++ b/hw/bsp/stm32h743nucleo/stm32h743nucleo.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32l0538disco/stm32l0538disco.c b/hw/bsp/stm32l0538disco/stm32l0538disco.c index 0bfb1f845..ab04e5c51 100644 --- a/hw/bsp/stm32l0538disco/stm32l0538disco.c +++ b/hw/bsp/stm32l0538disco/stm32l0538disco.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32l476disco/stm32l476disco.c b/hw/bsp/stm32l476disco/stm32l476disco.c index 65c544137..2d4a4e3de 100644 --- a/hw/bsp/stm32l476disco/stm32l476disco.c +++ b/hw/bsp/stm32l476disco/stm32l476disco.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index 9e49ed19c..f45a98ef3 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -129,7 +129,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -140,7 +140,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/src/device/dcd.h b/src/device/dcd.h index 6554be2c8..99a0e01ca 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_irq_handler(uint8_t rhport) TU_ATTR_USED; +void dcd_int_handler(uint8_t rhport); // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/device/usbd.h b/src/device/usbd.h index 3b409e70b..fcb4e5c5f 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -48,7 +48,7 @@ bool tud_init (void); void tud_task (void); // Interrupt handler, name alias to DCD -#define tud_irq_handler dcd_irq_handler +#define tud_int_handler dcd_int_handler // Check if device is connected and configured bool tud_mounted(void); diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 47c90fd13..986df3b3b 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -638,7 +638,7 @@ static void handle_epin_ints(void) } -static void dcd_int_handler(void* arg) +static void _dcd_int_handler(void* arg) { (void) arg; @@ -726,7 +726,7 @@ static void dcd_int_handler(void* arg) void dcd_int_enable (uint8_t rhport) { (void) rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) dcd_int_handler, NULL, &usb_ih); + esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); } void dcd_int_disable (uint8_t rhport) diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 2c01f8017..bd61df86a 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -331,7 +331,7 @@ void maybe_transfer_complete(void) { } -void dcd_irq_handler (uint8_t rhport) +void dcd_int_handler (uint8_t rhport) { (void) rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index c122b9bee..7703ee0dc 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -347,7 +347,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { uint32_t const intr_mask = UDP->UDP_IMR; uint32_t const intr_status = UDP->UDP_ISR & intr_mask; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 389266217..95240f9f0 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -373,7 +373,7 @@ void bus_reset(void) _dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE; } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 050aea255..9195b8dbe 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -306,7 +306,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) ep->CFG |= USBD_CFG_CSTALL_Msk; } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index df72cbb2d..edd1e14a7 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -312,7 +312,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) ep->CFG |= USBD_CFG_CSTALL_Msk; } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 3baed87c5..af6972961 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -435,7 +435,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) } } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index dfdae1450..14f3dce3b 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -505,7 +505,7 @@ static void dd_complete_isr(uint8_t rhport, uint8_t ep_id) } // main USB IRQ handler -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { uint32_t const dev_int_status = LPC_USB->DevIntSt & LPC_USB->DevIntEn; LPC_USB->DevIntClr = dev_int_status;// Acknowledge handled interrupt diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 980fa118f..c1f80185b 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -345,7 +345,7 @@ static void process_xfer_isr(uint32_t int_status) } } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; // TODO support multiple USB on supported mcu such as LPC55s69 diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index cea7c2b04..539629c3d 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -503,7 +503,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 14ffcbe40..dbc1e6952 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -499,7 +499,7 @@ static void dcd_ep_ctr_handler(void) } } -void dcd_irq_handler(uint8_t rhport) { +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 38c284c5a..0c9c2650d 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -669,7 +669,7 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType } } -void dcd_irq_handler(uint8_t rhport) { +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 1512f0de4..da75a7f3f 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -558,7 +558,7 @@ static void handle_setup_packet(void) dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true); } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index 1e7219a1f..8dde874fc 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -626,7 +626,7 @@ static void handle_setup(void) usb_setup_ev_pending_write(1); } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void)rhport; uint8_t next_ev; -- cgit v1.3.1 From 6f9c256ad0e6b030468bd8a8fbfd41801b70a69a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 13:52:34 +0700 Subject: complete remove dcd_set_config(), fix unit test --- docs/porting.md | 4 ---- src/device/dcd.h | 3 --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 7 ------- src/portable/microchip/samd/dcd_samd.c | 7 ------- src/portable/microchip/samg/dcd_samg.c | 10 ---------- src/portable/nordic/nrf5x/dcd_nrf5x.c | 6 ------ src/portable/nuvoton/nuc120/dcd_nuc120.c | 6 ------ src/portable/nuvoton/nuc121/dcd_nuc121.c | 6 ------ src/portable/nuvoton/nuc505/dcd_nuc505.c | 6 ------ src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 6 ------ src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 6 ------ src/portable/nxp/transdimension/dcd_transdimension.c | 7 ------- src/portable/sony/cxd56/dcd_cxd56.c | 7 ------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 8 -------- src/portable/st/synopsys/dcd_synopsys.c | 7 ------- src/portable/template/dcd_template.c | 7 ------- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 7 ------- src/portable/valentyusb/eptri/dcd_eptri.c | 8 -------- test/test/device/msc/test_msc_device.c | 2 -- 19 files changed, 120 deletions(-) (limited to 'src/device') diff --git a/docs/porting.md b/docs/porting.md index fabf24510..473768450 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -78,10 +78,6 @@ Called when the device is given a new bus address. If your peripheral automatically changes address during enumeration (like the nrf52) you may leave this empty and also no queue an event for the corresponding SETUP packet. -##### dcd_set_config - -Called when the device received SET_CONFIG request, you can leave this empty if your peripheral does not require any specific action. - ##### dcd_remote_wakeup Called to remote wake up host when suspended (e.g hid keyboard) diff --git a/src/device/dcd.h b/src/device/dcd.h index 99a0e01ca..68798c259 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -100,9 +100,6 @@ void dcd_int_disable(uint8_t rhport); // Receive Set Address request, mcu port must also include status IN response void dcd_set_address(uint8_t rhport, uint8_t dev_addr); -// Receive Set Configure request -void dcd_set_config (uint8_t rhport, uint8_t config_num); - // Wake up host void dcd_remote_wakeup(uint8_t rhport); diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 986df3b3b..16c0e7207 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -201,13 +201,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void)rhport; - (void)config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index bd61df86a..a01bef38a 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -144,13 +144,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SUSPEND; } -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 7703ee0dc..1824d549a 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -167,16 +167,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() } -// Receive Set Configure request -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - - // Configured State -// UDP->UDP_GLB_STAT |= UDP_GLB_STAT_CONFG_Msk; -} - // Wake up host void dcd_remote_wakeup (uint8_t rhport) { diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 95240f9f0..12435ea23 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -216,12 +216,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk; } -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; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 9195b8dbe..1a0007d8a 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -219,12 +219,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) assigned_address = dev_addr; } -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; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index edd1e14a7..af7fee8b0 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -225,12 +225,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) assigned_address = dev_addr; } -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; diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index aceb6df09..02f0b35a6 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -298,12 +298,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) assigned_address = dev_addr; } -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; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 21a678c66..f7a59a808 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -208,12 +208,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); } -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; diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index c1f80185b..3d1420c65 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -198,12 +198,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) DCD_REGS->DEVCMDSTAT |= dev_addr; } -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; diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 539629c3d..fcedc1c0c 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -363,13 +363,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_reg->DEVICEADDR = (dev_addr << 25) | TU_BIT(24); } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 7fd630384..bcf94dc21 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -187,13 +187,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) (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; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dbc1e6952..c5666421b 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -317,14 +317,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() } -// Receive Set Config request -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do? Handled by stack. -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 0c9c2650d..3386abdac 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -234,13 +234,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index ba1383f31..812bb7866 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -78,13 +78,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; } -// Receive Set Configure request -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - // Wake up host void dcd_remote_wakeup (uint8_t rhport) { diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index da75a7f3f..8672050f0 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -192,13 +192,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index 8dde874fc..d670dd38e 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -383,14 +383,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) usb_address_write(dev_addr); } -// Called when the device received SET_CONFIG request, you can leave this -// empty if your peripheral does not require any specific action. -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - // Called to remote wake up host when suspended (e.g hid keyboard) void dcd_remote_wakeup(uint8_t rhport) { diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 62a36d3e3..34bd90c7e 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -241,8 +241,6 @@ void test_msc(void) dcd_event_setup_received(rhport, (uint8_t*) &request_set_configuration, false); - dcd_set_config_Expect(rhport, 1); - // open endpoints dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) desc_ep, true); dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep), true); -- cgit v1.3.1 From bbcf9241bd3788c65c5fcbdabcc774f2f9cd8794 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 Apr 2020 23:46:17 +0700 Subject: add back MIDI multiple jack --- src/device/usbd.h | 66 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 21 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index fcb4e5c5f..713bee2b2 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -249,37 +249,61 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- MIDI -------------// -// Length of template descriptor (96 bytes) -#define TUD_MIDI_DESC_LEN (9 + 9 + 9 + 7 + 6 + 6 + 9 + 9 + 7 + 5 + 7 + 5) - -// MIDI simple descriptor -// - 1 Embedded Jack In connected to 1 External Jack Out -// - 1 Embedded Jack out connected to 1 External Jack In -#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ +#define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) +#define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ /* Audio Control (AC) Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum)+1),\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0025),\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + +#define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 1) + +#define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 2) + +#define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 3) + +#define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 4) + +#define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) +#define TUD_MIDI_DESC_JACK(_cablenum) \ /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, 1, 0,\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, 2, 0,\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, 3, 1, 2, 1, 0,\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, 4, 1, 1, 1, 0,\ - /* Endpoint Out */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + +#define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) +#define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ + /* Endpoint */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack in) */\ - 5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 1,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack out) */\ - 5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 3 + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + +// Length of template descriptor (88 bytes) +#define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) + +// MIDI simple descriptor +// - 1 Embedded Jack In connected to 1 External Jack Out +// - 1 Embedded Jack out connected to 1 External Jack In +#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -- cgit v1.3.1 From d1656c0b8d108d8f91748269e9196d1bbc711506 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 20 Apr 2020 16:00:21 -0400 Subject: tu_verify for getting descriptors --- src/device/usbd.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 26183c960..0a2169185 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -450,7 +450,7 @@ void tud_task (void) // Helper to invoke class driver control request handler static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request) { - TU_ASSERT(_usbd_driver[drvid].control_request); + TU_VERIFY(_usbd_driver[drvid].control_request); usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); @@ -463,7 +463,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { usbd_control_set_complete_callback(NULL); - TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + TU_VERIFY(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) @@ -801,7 +801,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_CONFIGURATION: { tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); - TU_ASSERT(desc_config); + TU_VERIFY(desc_config); uint16_t total_len; memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory @@ -817,10 +817,11 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // The 0xEE index string is a Microsoft OS Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors return false; - }else + } + else { uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); - TU_ASSERT(desc_str); + TU_VERIFY(desc_str); // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); -- cgit v1.3.1 From 0ec69de77c22bd018f9e5e5d038cfb8275922351 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 21 Apr 2020 10:06:17 -0400 Subject: sof is optional, revert other changes but remove unneeded check. --- src/device/usbd.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 0a2169185..219dd23be 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -91,7 +91,7 @@ typedef struct bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); + void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; static usbd_class_driver_t const _usbd_driver[] = @@ -450,8 +450,6 @@ void tud_task (void) // Helper to invoke class driver control request handler static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request) { - TU_VERIFY(_usbd_driver[drvid].control_request); - usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); return _usbd_driver[drvid].control_request(rhport, request); @@ -463,7 +461,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { usbd_control_set_complete_callback(NULL); - TU_VERIFY(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) @@ -801,7 +799,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_CONFIGURATION: { tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); - TU_VERIFY(desc_config); + TU_ASSERT(desc_config); uint16_t total_len; memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory @@ -821,7 +819,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const else { uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); - TU_VERIFY(desc_str); + TU_ASSERT(desc_str); // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); -- cgit v1.3.1 From 017c95037f3173455fa09efae6093d56fd3f3d1a Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 14:51:44 +0700 Subject: add usbd edpt open - RTT mode is blocking to prevent log lost - Improve logging message --- examples/make.mk | 2 +- src/class/cdc/cdc_device.c | 2 +- src/class/midi/midi_device.c | 2 +- src/class/net/net_device.c | 2 +- src/class/usbtmc/usbtmc_device.c | 2 +- src/common/tusb_common.h | 12 ++++++++++-- src/common/tusb_verify.h | 6 +++--- src/device/usbd.c | 38 ++++++++++++++++++++++++++++++-------- src/device/usbd_control.c | 6 +++--- src/device/usbd_pvt.h | 5 ++++- src/tusb.c | 8 +++++--- test/test/support/tusb_config.h | 2 ++ 12 files changed, 62 insertions(+), 25 deletions(-) (limited to 'src/device') diff --git a/examples/make.mk b/examples/make.mk index 319ceece8..449dc899d 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -84,7 +84,7 @@ endif ifeq ($(LOGGER),rtt) RTT_SRC = lib/SEGGER_RTT - CFLAGS += -DLOGGER_RTT + CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL INC += $(TOP)/$(RTT_SRC)/RTT SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT_printf.c SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 3c7118f13..2d8f986ae 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -260,7 +260,7 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint if any - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 56a27fbce..7bc8cef84 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -339,7 +339,7 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t { if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { p_midi->ep_in = ep_addr; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 0f2ccbd44..ad1d66fca 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -167,7 +167,7 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t // notification endpoint (if any) if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index abe26ced3..b14135146 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -309,7 +309,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin default: TU_ASSERT(false); } - TU_VERIFY( dcd_edpt_open(rhport, ep_desc)); + TU_VERIFY( usbd_edpt_open(rhport, ep_desc)); found_endpoints++; } (*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2d80f8210..fcb22cde1 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -219,17 +219,25 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); #define tu_printf printf #endif +static inline +void tu_print_var(uint8_t const* buf, uint32_t bufsize) +{ + for(uint32_t i=0; i 1 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM + #define TU_LOG2_VAR TU_LOG1_VAR #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index fee291df6..406f5e6ee 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -90,13 +90,13 @@ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ } while(0) -#else -#if defined(__riscv) + +#elif defined(__riscv) #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) + #else #define TU_BREAKPOINT() do {} while (0) #endif -#endif /*------------------------------------------------------------------*/ /* Macro Generator diff --git a/src/device/usbd.c b/src/device/usbd.c index 219dd23be..f0b7fcefc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -356,7 +356,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"); + TU_LOG2("USBD: %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); + TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); switch ( event.event_id ) { @@ -372,7 +373,8 @@ void tud_task (void) break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG2_MEM(&event.setup_received, 8, 2); + TU_LOG2_VAR(&event.setup_received); + TU_LOG2("\r\n"); // 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 @@ -395,7 +397,7 @@ void tud_task (void) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; @@ -472,10 +474,11 @@ 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 CFG_TUSB_DEBUG >= 2 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]); + TU_LOG2(" %s", _tusb_std_request_str[p_request->bRequest]); + if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n"); } #endif @@ -702,7 +705,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Interface number must not be used already TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -767,6 +770,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const { case TUSB_DESC_DEVICE: { + TU_LOG2(" Device\r\n"); + uint16_t len = sizeof(tusb_desc_device_t); // Only send up to EP0 Packet Size if not addressed @@ -785,6 +790,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_BOS: { + TU_LOG2(" BOS\r\n"); + // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) if (!tud_descriptor_bos_cb) return false; @@ -798,6 +805,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_CONFIGURATION: { + TU_LOG2(" Configuration[%u]\r\n", desc_index); + tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); TU_ASSERT(desc_config); @@ -809,6 +818,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_STRING: + TU_LOG2(" String[%u]\r\n", desc_index); + // String Descriptor always uses the desc set from user if ( desc_index == 0xEE ) { @@ -827,6 +838,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_DEVICE_QUALIFIER: + TU_LOG2(" Device Qualifier\r\n"); + // TODO If not highspeed capable stall this request otherwise // return the descriptor that could work in highspeed return false; @@ -920,7 +933,7 @@ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); - TU_ASSERT(dcd_edpt_open(rhport, desc_ep)); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { @@ -955,15 +968,24 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) // USBD Endpoint API //--------------------------------------------------------------------+ +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) +{ + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + + return dcd_edpt_open(rhport, desc_ep); +} + bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ); _usbd_dev.ep_status[epnum][dir].busy = true; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, total_bytes); + TU_LOG2("OK\r\n"); return true; } diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index c61606f18..b0ae85e3b 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -63,7 +63,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, 0); + TU_LOG2(" Queue EP %02X with zlp Status\r\n", ep_addr); // status direction is reversed to one in the setup packet // Note: Status must always be DATA1 @@ -96,7 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\r\n", ep_addr, xact_len); + TU_LOG2(" Queue EP %02X with %u bytes\r\n", ep_addr, xact_len); return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -118,7 +118,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo TU_ASSERT(buffer); } - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); +// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 26b9700e8..48188ec99 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -37,7 +37,10 @@ // USBD Endpoint API //--------------------------------------------------------------------+ -//bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +// Open an endpoint +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); + +// Close an endpoint void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer diff --git a/src/tusb.c b/src/tusb.c index 8f234455f..1bc134dba 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -78,9 +78,11 @@ static void dump_str_line(uint8_t const* buf, uint16_t count) } } -// size : item size in bytes -// count : number of item -// print offet or not (handfy for dumping large memory) +/* Print out memory contents + * - size : item size in bytes + * - count : number of item + * - indent: prefix spaces on every line + */ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent) { uint8_t const size = 1; // fixed 1 byte for now diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 5e7b70e0d..5258513ec 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -52,7 +52,9 @@ #define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build +#ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 +#endif /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put -- cgit v1.3.1 From a1c599f4b6a05aefb948aaacf9a0984f577252bb Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 22:02:41 +0700 Subject: clean up log message --- src/device/usbd.c | 31 ++++++++++++++++++++++--------- src/device/usbd_control.c | 11 ++++++++--- 2 files changed, 30 insertions(+), 12 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f0b7fcefc..1f660f0f2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -232,15 +232,15 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, #if CFG_TUSB_DEBUG >= 2 static char const* const _usbd_event_str[DCD_EVENT_COUNT] = { - "INVALID" , - "BUS_RESET" , - "UNPLUGGED" , + "Invalid" , + "Bus Reset" , + "Unplugged" , "SOF" , - "SUSPEND" , - "RESUME" , - "SETUP_RECEIVED" , - "XFER_COMPLETE" , - "FUNC_CALL" + "Suspend" , + "Resume" , + "Setup Received" , + "Xfer Complete" , + "Func Call" }; static char const* const _tusb_std_request_str[] = @@ -260,6 +260,19 @@ static char const* const _tusb_std_request_str[] = "Synch Frame" }; +// for usbd_control to print the name of control complete driver +void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) +{ + for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + { + if (_usbd_driver[i].control_complete == control_complete ) + { + TU_LOG2(" %s control complete\r\n", _usbd_driver[i].name); + return; + } + } +} + #endif //--------------------------------------------------------------------+ @@ -356,7 +369,7 @@ void tud_task (void) if ( !osal_queue_receive(_usbd_q, &event) ) return; - TU_LOG2("USBD: %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); + TU_LOG2("USBD %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); switch ( event.event_id ) diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index b0ae85e3b..2778a0d77 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -58,6 +58,7 @@ static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; // Application API //--------------------------------------------------------------------+ +// Queue ZLP status transaction static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) { // Opposite to endpoint in Data Phase @@ -81,7 +82,7 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) return _status_stage_xact(rhport, request); } -// Transfer an transaction in Data Stage +// Queue an transaction in Data Stage // Each transaction has up to Endpoint0's max packet size. // This function can also transfer an zero-length packet static bool _data_stage_xact(uint8_t rhport) @@ -102,7 +103,6 @@ static bool _data_stage_xact(uint8_t rhport) } // Transmit data to/from the control endpoint. -// // If the request's wLength is zero, a status packet is sent instead. bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) { @@ -182,7 +182,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // Data Stage is complete when all request's length are transferred or // a short packet is sent including zero-length packet. - if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE ) + if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) { // DATA stage is complete bool is_ok = true; @@ -191,6 +191,11 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // callback can still stall control in status phase e.g out data does not make sense if ( _ctrl_xfer.complete_cb ) { + #if CFG_TUSB_DEBUG >= 2 + extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); + usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); + #endif + is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request); } -- cgit v1.3.1 From 63cefb761535bf9f9f86a261c4a7ba07710c6c1d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 27 Apr 2020 16:42:35 +0200 Subject: Fix endpoint busy flag race condition Busy flag was set to true after call to dcd_edpt_xfer(). In some cased it was possible that transfer finished before function ended. In this case busy flag could be set to false before it was set to true. Then setting it to true after dcd_edpt_xfer() made edpoint busy forever. This change marks endpoint as busy before transfer is started to avoid race condition. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f0b7fcefc..2042d35b7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -982,8 +982,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ); _usbd_dev.ep_status[epnum][dir].busy = true; + TU_VERIFY_HDLR( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes), _usbd_dev.ep_status[epnum][dir].busy = false); TU_LOG2("OK\r\n"); -- cgit v1.3.1 From fcdb22b2f9db6f4e08ce05a1b2b7a1c9cc06a4ab Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 28 Apr 2020 10:53:43 +0700 Subject: fix typo --- src/device/usbd_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 2778a0d77..353a66ad1 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -82,7 +82,7 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) return _status_stage_xact(rhport, request); } -// Queue an transaction in Data Stage +// Queue a transaction in Data Stage // Each transaction has up to Endpoint0's max packet size. // This function can also transfer an zero-length packet static bool _data_stage_xact(uint8_t rhport) -- cgit v1.3.1 From c14c0cfc9fec9101b63df682c5fa5ac0576de0f8 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Apr 2020 10:49:58 +0700 Subject: support class drivers implemented by application --- src/device/usbd.c | 114 ++++++++++++++++++++++++++++---------------------- src/device/usbd_pvt.h | 23 ++++++++++ 2 files changed, 87 insertions(+), 50 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 1f660f0f2..432786140 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -79,21 +79,7 @@ enum { DRVID_INVALID = 0xFFu }; #define DRIVER_NAME(_name) #endif -typedef struct -{ - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* init ) (void); - void (* reset ) (uint8_t rhport); - bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ -} usbd_class_driver_t; - +// Built-in class drivers static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC @@ -203,6 +189,29 @@ static usbd_class_driver_t const _usbd_driver[] = enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; +// Additional class drivers implemented by application +static usbd_class_driver_t const * _app_driver = NULL; +static uint8_t _app_driver_count = 0; + +// virtually joins built-in and application drivers together +// All drivers = built-in + application +static inline usbd_class_driver_t const * get_driver(uint8_t drvid) +{ + // Built-in drivers + if (drvid < USBD_CLASS_DRIVER_COUNT) return &_usbd_driver[drvid]; + + // App drivers + if ( usbd_app_driver_get_cb ) + { + drvid -= USBD_CLASS_DRIVER_COUNT; + if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + } + + return NULL; +} + +#define TOTAL_DRIVER_COUNT (USBD_CLASS_DRIVER_COUNT+_app_driver_count) + //--------------------------------------------------------------------+ // DCD Event //--------------------------------------------------------------------+ @@ -263,11 +272,12 @@ static char const* const _tusb_std_request_str[] = // for usbd_control to print the name of control complete driver void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) { - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { - if (_usbd_driver[i].control_complete == control_complete ) + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->control_complete == control_complete ) { - TU_LOG2(" %s control complete\r\n", _usbd_driver[i].name); + TU_LOG2(" %s control complete\r\n", driver->name); return; } } @@ -309,11 +319,18 @@ bool tud_init (void) _usbd_q = osal_queue_create(&_usbd_qdef); TU_ASSERT(_usbd_q != NULL); + // Get application driver if available + if ( usbd_app_driver_get_cb ) + { + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + } + // Init class drivers - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { - TU_LOG2("%s init\r\n", _usbd_driver[i].name); - _usbd_driver[i].init(); + usbd_class_driver_t const * driver = get_driver(i); + TU_LOG2("%s init\r\n", driver->name); + driver->init(); } // Init device controller driver @@ -333,9 +350,9 @@ static void usbd_reset(uint8_t rhport) usbd_control_reset(); - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) { - if ( _usbd_driver[i].reset ) _usbd_driver[i].reset( rhport ); + get_driver(i)->reset(rhport); } } @@ -420,11 +437,11 @@ void tud_task (void) } else { - uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); + usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); + TU_ASSERT(driver, ); - TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); - _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + TU_LOG2(" %s xfer callback\r\n", driver->name); + driver->xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -438,12 +455,10 @@ void tud_task (void) break; case DCD_EVENT_SOF: - for ( uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++ ) + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) { - if ( _usbd_driver[i].sof ) - { - _usbd_driver[i].sof(event.rhport); - } + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->sof ) driver->sof(event.rhport); } break; @@ -463,11 +478,11 @@ void tud_task (void) //--------------------------------------------------------------------+ // Helper to invoke class driver control request handler -static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request) +static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { - usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); - TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); - return _usbd_driver[drvid].control_request(rhport, request); + usbd_control_set_complete_callback(driver->control_complete); + TU_LOG2(" %s control request\r\n", driver->name); + return driver->control_request(rhport, request); } // This handles the actual request and its response. @@ -580,12 +595,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const itf = tu_u16_low(p_request->wIndex); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); - uint8_t const drvid = _usbd_dev.itf2drv[itf]; - TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); + usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); + TU_VERIFY(driver); // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, drvid, p_request) ) + if ( !invoke_class_control(rhport, driver, p_request) ) { // For GET_INTERFACE, it is mandatory to respond even if the class // driver doesn't use alternate settings. @@ -607,8 +622,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - uint8_t const drvid = _usbd_dev.ep2drv[ep_num][ep_dir]; - bool ret = false; // Handle STD request to endpoint @@ -647,16 +660,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } } - if (drvid < 0xFF) { - TU_ASSERT(drvid < USBD_CLASS_DRIVER_COUNT); - + usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); + + if (driver) + { // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will forward all request targeted endpoint to class drivers after // - For class-type requests: driver is fully responsible to reply to host // - For std-type requests : driver init/re-init internal variable/buffer only, and // must not call tud_control_status(), driver's return value will have no effect. // EP state has already affected (stalled/cleared) - if ( invoke_class_control(rhport, drvid, p_request) ) ret = true; + if ( invoke_class_control(rhport, driver, p_request) ) ret = true; } if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) @@ -708,17 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) uint8_t drv_id; uint16_t drv_len; - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + usbd_class_driver_t const *driver = get_driver(drv_id); drv_len = 0; if ( driver->open(rhport, desc_itf, &drv_len) ) { // Interface number must not be used already - TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", driver->name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -741,7 +755,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + TU_ASSERT( drv_id < TOTAL_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 48188ec99..d6eb289c1 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -33,6 +33,29 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Drivers +//--------------------------------------------------------------------+ + +typedef struct +{ +#if CFG_TUSB_DEBUG >= 2 + char const* name; +#endif + + void (* init ) (void); + void (* reset ) (uint8_t rhport); + bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ +} usbd_class_driver_t; + +// Invoked when initializing device stack to get additional class drivers. +// Can optionally implemented by application to extend/overwrite class driver support. +usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 6f4b6a1d03efa2a1f878e90d523746395be622c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Apr 2020 11:31:27 +0700 Subject: remove the use of TU_VERIFY_HDLR --- src/device/usbd.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 62133bdb8..06e724cb3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -995,12 +995,21 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return + // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - TU_VERIFY_HDLR( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes), _usbd_dev.ep_status[epnum][dir].busy = false); - TU_LOG2("OK\r\n"); - - return true; + if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + _usbd_dev.ep_status[epnum][dir].busy = false; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } } bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) -- cgit v1.3.1 From 63bd8d2e44225341caae6dafb2affb1fe711a9b4 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 7 May 2020 19:00:41 +0800 Subject: device: fix build warning when CFG_TUSB_DEBUG >= 2 The function is defined inside of a function body which generates a warning. Circuit Python treats these warnings as errors, and so refuses to build with debugging enabled: ../../lib/tinyusb/src/device/usbd_control.c: In function 'usbd_control_xfer_cb': ../../lib/tinyusb/src/device/usbd_control.c:195:19: error: nested extern declaration of 'usbd_driver_print_control_complete_name' [-Werror=nested-externs] 195 | extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors make: *** [../../py/mkrules.mk:55: build-simmel/lib/tinyusb/src/device/usbd_control.o] Error 1 Move the declaration to the top of the function to silence this warning. Signed-off-by: Sean Cross --- src/device/usbd_control.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 353a66ad1..db0eb70a7 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -32,6 +32,10 @@ #include "device/usbd_pvt.h" #include "dcd.h" +#if CFG_TUSB_DEBUG >= 2 +extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); +#endif + enum { EDPT_CTRL_OUT = 0x00, @@ -192,7 +196,6 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( _ctrl_xfer.complete_cb ) { #if CFG_TUSB_DEBUG >= 2 - extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif -- cgit v1.3.1 From 88a455a9b99099bf27ce239006ecfd2da3894bcf Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 May 2020 14:31:45 +0700 Subject: added tud_task_event_ready() to check if there is pending events in the tud task without executing it. Useful to check before entering low power mode with WFI/WFE --- src/device/usbd.c | 8 ++++++++ src/device/usbd.h | 3 +++ 2 files changed, 11 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 06e724cb3..f7918c07e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -339,6 +339,14 @@ static void usbd_reset(uint8_t rhport) } } +bool tud_task_event_ready(void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return false; + + return !osal_queue_empty(_usbd_q); +} + /* USB Device Driver task * This top level thread manages all device controller event and delegates events to class-specific drivers. * This should be called periodically within the mainloop or rtos thread. diff --git a/src/device/usbd.h b/src/device/usbd.h index 713bee2b2..ecef63e18 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -47,6 +47,9 @@ bool tud_init (void); // Task function should be called in main/rtos loop void tud_task (void); +// Check if there is pending events need proccessing by tud_task() +bool tud_task_event_ready(void); + // Interrupt handler, name alias to DCD #define tud_int_handler dcd_int_handler -- cgit v1.3.1 From 9be2f1bf3dc2c89bc23eed1e95c06de41ebb0946 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 22 May 2020 12:09:34 +0200 Subject: Add basic UAC2 structure - untested --- src/class/audio/audio.h | 466 ++++++++++++++-- src/class/audio/audio_device.c | 1193 ++++++++++++++++++++++++++++++++++++++++ src/class/audio/audio_device.h | 304 ++++++++++ src/device/usbd.c | 13 + src/device/usbd.h | 37 ++ src/tusb.h | 4 + 6 files changed, 1982 insertions(+), 35 deletions(-) create mode 100644 src/class/audio/audio_device.c create mode 100644 src/class/audio/audio_device.h (limited to 'src/device') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 5bec14d88..f4f460c22 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -35,64 +35,460 @@ #include "common/tusb_common.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + /// Audio Interface Subclass Codes typedef enum { - AUDIO_SUBCLASS_CONTROL = 0x01 , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming + AUDIO_SUBCLASS_UNDEFINED = 0x00, + AUDIO_SUBCLASS_CONTROL , ///< Audio Control + AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming + AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; /// Audio Protocol Codes typedef enum { - AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 - AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 - AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 + AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 + AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 + AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 } audio_protocol_type_t; /// Audio Function Category Codes typedef enum { - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C + AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, + AUDIO_FUNC_HOME_THEATER = 0x02, + AUDIO_FUNC_MICROPHONE = 0x03, + AUDIO_FUNC_HEADSET = 0x04, + AUDIO_FUNC_TELEPHONE = 0x05, + AUDIO_FUNC_CONVERTER = 0x06, + AUDIO_FUNC_SOUND_RECODER = 0x07, + AUDIO_FUNC_IO_BOX = 0x08, + AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, + AUDIO_FUNC_PRO_AUDIO = 0x0A, + AUDIO_FUNC_AUDIO_VIDEO = 0x0B, + AUDIO_FUNC_CONTROL_PANEL = 0x0C, } audio_function_t; -/// Audio Class-Specific AC Interface Descriptor Subtypes +/// Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, + AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, + AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, + AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, + AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, + AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, + AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, +} audio_cs_ac_interface_subtype_t; + +/// Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, + AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, + AUDIO_CS_AS_INTERFACE_DECODER = 0x04, +} audio_cs_as_interface_subtype_t; + +/// Audio Class-Control Values UAC2 +typedef enum +{ + AUDIO_CTRL_NONE = 0x00, ///< No Host access + AUDIO_CTRL_R = 0x01, ///< Host read access only + AUDIO_CTRL_RW = 0x03, ///< Host read write access +} audio_control_t; + +/// Audio Class-Specific AC Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, +} audio_cs_ac_interface_control_pos_t; + +/// Audio Class-Specific AS Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, + AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, +} audio_cs_as_interface_control_pos_t; + +/// Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_DESCRIPTOR_UNDEFINED = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, +} audio_cs_as_iso_data_ep_attribute_t; + +/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, +} audio_cs_as_iso_data_ep_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio_cs_as_iso_data_ep_lock_delay_unit_t; + +/// Audio Class-Clock Source Attributes UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, + AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, + AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, + AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, + AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, +} audio_clock_source_attribute_t; + +/// Audio Class-Clock Source Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, + AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, +} audio_clock_source_control_pos_t; + +/// Audio Class-Clock Selector Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, +} audio_clock_selector_control_pos_t; + +/// Audio Class-Clock Multiplier Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, + AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, +} audio_clock_multiplier_control_pos_t; + +/// Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// Audio Class-Input Terminal Controls UAC2 +typedef enum +{ + AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, + AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, + AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, +} audio_terminal_input_control_pos_t; + +/// Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Audio Class-Output Terminal Controls UAC2 +typedef enum +{ + AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, + AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, +} audio_terminal_output_control_pos_t; + +/// Audio Class-Feature Unit Controls UAC2 typedef enum { - AUDIO_CS_INTERFACE_HEADER = 0x01, - AUDIO_CS_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_interface_subtype_t; + AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, + AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, + AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, + AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, + AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, + AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, + AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, + AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, + AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, + AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, + AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, + AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, + AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, +} audio_feature_unit_control_pos_t; + +/// Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = 0x00000000, + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = 0x00000001, + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 0x00000002, + AUDIO_DATA_FORMAT_TYPE_I_ALAW = 0x00000003, + AUDIO_DATA_FORMAT_TYPE_I_MULAW = 0x00000004, +} audio_data_format_type_I_t; + +/// Audio Class-Audio Channel Configuration UAC2 +typedef enum +{ + AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, + AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, + AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, + AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, + AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, + AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, + AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, + AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, + AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, + AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, + AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, + AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, +} audio_channel_config_t; + +/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. +} audio_desc_cs_ac_interface_t; + +/// AUDIO Clock Source Descriptor (4.7.2.1) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. +} audio_desc_clock_source_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. +} audio_desc_clock_selector_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins +#define audio_desc_clock_selector_n_t(source_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; \ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bClockID ; \ + uint8_t bNrInPins ; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ + } + +/// AUDIO Clock Multiplier Descriptor (4.7.2.3) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. +} audio_desc_clock_multiplier_t; + +/// AUDIO Input Terminal Descriptor(4.7.2.4) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. +} audio_desc_input_terminal_t; + +/// AUDIO Output Terminal Descriptor(4.7.2.5) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. +} audio_desc_output_terminal_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. +} audio_desc_feature_unit_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels +#define audio_desc_feature_unit_n_t(ch_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; /* 6+(ch_num+1)*4 */\ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ + } + +/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. +} audio_desc_cs_as_interface_t; + +/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. +} audio_desc_type_I_format_t; + +/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. +} audio_desc_cs_as_iso_data_ep_t; + /** @} */ #ifdef __cplusplus - } +} #endif #endif diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c new file mode 100644 index 000000000..fbd412564 --- /dev/null +++ b/src/class/audio/audio_device.c @@ -0,0 +1,1193 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber + * + * 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. + */ + +/* + * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! + * It supports multiple TX and RX channels. + * + * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. + * + * */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "audio_device.h" +#include "class/audio/audio.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + +#if CFG_TUD_AUDIO_EPSIZE_IN + uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint8_t ep_fb; // Feedback EP. +#endif + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + uint8_t ep_int_ctr; // Audio control interrupt EP. +#endif + +#if CFG_TUD_AUDIO_N_AS_INT + uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; +#endif + /*------------- From this point, data is not cleared by bus reset -------------*/ + // FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; +#endif +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; +#endif +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t int_ctr_ff_mutex; +#endif +#endif + + // Endpoint Transfer buffers +#if CFG_TUD_AUDIO_EPSIZE_OUT + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + + // TODO: required? + //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // uint16_t fb_val; // Feedback value for asynchronous mode! + //#endif + +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; +#endif + +} audiod_interface_t; + +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) +#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) +#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) +#elif CFG_TUD_AUDIO_EPSIZE_OUT +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) +#elif CFG_TUD_AUDIO_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) +#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) +#endif + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; + +extern const uint16_t tud_audio_desc_lengths[]; + +#if CFG_TUD_AUDIO_EPSIZE_OUT +static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t const* buffer, uint32_t bufsize); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN +static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); +#endif + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); + +static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); + +bool tud_audio_n_mounted(uint8_t itf) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + +#if CFG_TUD_AUDIO_EPSIZE_OUT + if (audio->ep_out == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + if (audio->ep_in == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + if (audio->ep_int_ctr == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (audio->ep_fb == 0) + { + return false; + } +#endif + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO + +uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); +} + +uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); +} + +void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); +} + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + +uint16_t tud_audio_int_ctr_n_available(uint8_t itf) +{ + return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); +} + +uint16_t tud_audio_int_ctr_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +{ + return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); +} + +void tud_audio_int_ctr_n_read_flush (uint8_t itf) +{ + tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); +} + +#endif + +// This function is called once something is received by USB and is responsible for decoding received stream into audio channels. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_RX_FIFO = 0. + +#if CFG_TUD_AUDIO_EPSIZE_OUT + +static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) +{ + switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + +#if CFG_TUD_AUDIO_USE_RX_FIFO + TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); +#else +#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! +#endif + break; + + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed RX was completed + TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + return true; +} + +#endif //CFG_TUD_AUDIO_EPSIZE_OUT + +// The following functions are used in case CFG_TUD_AUDIO_USE_RX_FIFO == 1 +#if CFG_TUD_AUDIO_USE_RX_FIFO +static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) +{ + (void) rhport; + + // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel + if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { + return false; + } + + uint8_t chId = 0; + uint16_t cnt; +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 + uint8_t sample = 0; +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 + uint16_t sample = 0; +#else + uint32_t sample = 0; +#endif + + for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) + { + // Let alignment problems be handled by memcpy + memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); + if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) + { + // Buffer overflow + return false; + } + + if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) + { + chId = 0; + } + } +} } +#endif //CFG_TUD_AUDIO_USE_RX_FIFO + + +#if CFG_TUD_AUDIO_EPSIZE_OUT +TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize) +{ + (void) rhport; + (void) buffer; + (void) bufsize; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_rx_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } + + return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 + +uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->itf_num == 0) { + return 0; + } + + return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); +} + +#endif + + +// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_TX_FIFO = 0. +#if CFG_TUD_AUDIO_EPSIZE_IN +static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + +#if CFG_TUD_AUDIO_USE_TX_FIFO + TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); +#else +#error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! +#endif + break; + + default: + // YOUR ENCODING AND SENDING IS REQUIRED HERE! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed TX was completed + TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); + return true; +} + +#endif //CFG_TUD_AUDIO_EPSIZE_IN + +#if CFG_TUD_AUDIO_USE_TX_FIFO +static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + // We encode directly into IN EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint16_t nSamplesPerChannelToSend = 0xFFFF; + uint8_t cntChannel; + + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) + { + nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; + } + } + + // Check if there is enough + if (nSamplesPerChannelToSend == 0) + { + *n_bytes_copied = 0; + return true; + } + + // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! + if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) + { + nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + + // Encode + uint16_t cntSample; + uint8_t * pBuff = audio->epin_buf; +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 + uint8_t sample; +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 + uint16_t sample; +#else + uint32_t sample; +#endif + + // TODO: Big endianess handling + for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) + { + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + // Get sample from buffer + tu_fifo_read(&audio->tx_ff[cntChannel], &sample); + + // Put it into EP's buffer - Let alignment problems be handled by memcpy + memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + + // Advance pointer + pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + } + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); + *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + return true; +} + +#endif //CFG_TUD_AUDIO_USE_TX_FIFO + +// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +{ + (void) rhport; + (void) audio; + + // Here we need to return the feedback value +#error RETURN YOUR FEEDBACK VALUE HERE! + + TU_VERIFY(tud_audio_fb_done_cb(rhport)); + return 0; +} + +#endif + +// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); + + // TODO: Big endianess handling + uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); + + if (cnt > 0) + { + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); + } + + *n_bytes_copied = cnt; + + TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); + + return true; +} +#endif + +// Callback functions +// Currently the return value has to effect so far. The return value finally is discarded in tud_task(void) in usbd.c - we just incorporate that for later use + +#if CFG_TUD_AUDIO_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) +{ + (void) rhport; + (void) n_bytes_copied; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_tx_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport) +{ + (void) rhport; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_fb_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) +{ + (void) rhport; + (void) n_bytes_copied; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_int_ctr_done_cb could be implemented in the user file + */ + + return true; +} + +#endif + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void audiod_init(void) +{ + uint8_t cnt; + tu_memclr(_audiod_itf, sizeof(_audiod_itf)); + + for(uint8_t i=0; i 0 && CFG_TUD_AUDIO_USE_TX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_BUFSIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); +#endif + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_BUFSIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); +#endif + } +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 + tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); +#endif +#endif + } +} + +void audiod_reset(uint8_t rhport) +{ + (void) rhport; + + for(uint8_t i=0; i 0 && CFG_TUD_AUDIO_USE_TX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_clear(&audio->tx_ff[cnt]); + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_clear(&audio->rx_ff[cnt]); + } +#endif + } +} + +bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + + // Verify version is correct - this check can be omitted + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); + + // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted + if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed + { + TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); + } + + // Alternate setting MUST be zero - this check can be omitted + TU_VERIFY(itf_desc->bAlternateSetting == 0); + + // Find available audio driver interface + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + break; + } + } + + // Verify we found a free one + TU_ASSERT( i < CFG_TUD_AUDIO ); + + // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) + + // Notify caller we read complete descriptor + (*p_length) += tud_audio_desc_lengths[i]; + + return true; +} + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + +#if CFG_TUD_AUDIO_N_AS_INT > 0 + uint8_t const itf = tu_u16_low(p_request->wIndex); + + // Find index of audio streaming interface + uint8_t idxDriver, idxItf; + uint8_t const *dummy; + + TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + + return true; + +#else + (void) p_request; + return false; +#endif +} + +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Here we need to do the following: + + // 1. Find the audio driver interface which was assigned to the given interface which is to be set + // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. + // The audio driver interface is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + + // 2. Close EPs which are currently open + // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them + + // 3. Open new EP + + uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const alt = tu_u16_low(p_request->wValue); + + // Find index of audio streaming interface and index of interface + uint8_t idxDriver, idxItf; + uint8_t const *p_desc; + TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 + if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); + _audiod_itf[idxDriver].ep_out = 0; // Necessary? + + // Close corresponding feedback EP +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); + _audiod_itf[idxDriver].ep_fb = 0; // Necessary? +#endif + } +#endif + + + // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; + + // p_desc starts at required interface with alternate setting zero + while (p_desc < p_desc_end) + { + // Find correct interface + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) + { + // Open EPs + uint8_t foundEPs = 0; + while (foundEPs < ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints && p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + { + TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + { + _audiod_itf[idxDriver].ep_in = ep_addr; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + _audiod_itf[idxDriver].ep_out = ep_addr; + + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + } + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + { + _audiod_itf[idxDriver].ep_fb = ep_addr; + } +#endif + +#endif + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); + } + + // We are done - abort loop + break; + } + + // Increase index, bytes read, and pointer + p_desc = tu_desc_next(p_desc); + } + + // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! + TU_VERIFY(p_desc < p_desc_end); + + // Conduct audio driver function specific stuff + + // HERE DO WHAT YOU HAVE TO DO - E.G. START ADC OR SO + //#error Implementation specific setInterface code required here! + + // Save current alternative interface setting + _audiod_itf[idxDriver].altSetting[idxItf] = alt; + + return true; +} + +bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + return true; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + default: + return false; + } +} + +bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + + // Search for interface belonging to given end point address and proceed as required + uint8_t idxDriver; + for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) + { + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + + // Data transmission of control interrupt finished + if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) + { + // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) + // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? + // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? + + // Load new data + uint16 *n_bytes_copied; + TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) + { + // There is no data left to send, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + } + +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + + // Data transmission of audio packet finished + if (_audiod_itf[idxDriver].ep_in == ep_addr) + { + // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." + // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." + // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. + + // Check if there is data to load into EPs buffer - if not load it with ZLP + // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! + // This is the only place where we can fill something into the EPs buffer! + + // Load new data + uint16_t *n_bytes_copied = NULL; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + + // New audio packet received + if (_audiod_itf[idxDriver].ep_out == ep_addr) + { + // Save into buffer - do whatever has to be done + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + + // prepare for next transmission + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + + return true; + } + + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // Transmission of feedback EP finished + if (_audiod_itf[idxDriver].ep_fb == ep_addr) + { + if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } +#endif +#endif + } + + return false; + +} + +static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +{ + // Loop over audio driver interfaces + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors + uint8_t const * p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *idxDriver = i; + *pp_desc_int = p_desc; + return true; + } + + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); + } + } + } + + return false; +} + +#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO + +// OLD +//// In order that this function works the following is mandatory: +// // - An IAD descriptor is required and has to be placed directly before the Standard AC Interface Descriptor (4.7.1) ALSO if no Audio Streaming interfaces are used! +// // - The Standard AC Interface Descriptor (4.7.1) has to be the first interface listed (required by UAC2 specification) +// // - The alternate interfaces of the Standard AS Interface Descriptor(4.9.1) must be listed in increasing order and alternate 0 must have zero EPs +// +// TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && +// AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); +// +// // Verify version is correct - this check can be omitted +// TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); +// +// // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted +// if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed +// { +// TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); +// } +// +// // Alternate setting MUST be zero - this check can be omitted +// TU_VERIFY(itf_desc->bAlternateSetting == 0); +// +// // Since checks are successful we get the number of interfaces we have to process by exploiting the fact that an IAD descriptor has to be provided directly before this AC descriptor +// // We do not get this value delivered by the stack so we need to hack a little bit - the number of interfaces to be processed is listed in the IAD descriptor with an offset of exactly 5 +// uint8_t nItfs = *(((uint8_t const *) itf_desc) - 5) - 1; // -1 since we already process the (included) AC interface +// +// // Notify caller we have read Standard AC Interface Descriptor (4.7.1) +// (*p_length) = sizeof(tusb_desc_interface_t); +// +// // Go to next descriptor which has to be a Class-Specific AC Interface Header Descriptor(4.7.2) - always present +// audio_desc_cs_ac_interface_t const * p_desc_cs_ac = (audio_desc_cs_ac_interface_t const *) tu_desc_next ( (uint8_t const *) itf_desc ); +// +// // Verify its the correct descriptor - this check can be omitted +// TU_VERIFY(p_desc_cs_ac->bDescriptorType == TUSB_DESC_CS_INTERFACE +// && p_desc_cs_ac->bDescriptorSubType == AUDIO_CS_AC_INTERFACE_HEADER +// && p_desc_cs_ac->bcdADC == 0x0200); +// +// // We do not check the Audio Function Category Codes +// +// // We do not check all the following Clock Source, Unit and Terminal descriptors +// +// // We do not check the latency control +// +// // We jump over all the following descriptor to the next following interface (which should be a Standard AS Interface Descriptor(4.9.1) if nItfs > 0) +// (*p_length) += p_desc_cs_ac->wTotalLength; // Notify caller of read bytes +// itf_desc = (tusb_desc_interface_t const * )(((uint8_t const *)p_desc_cs_ac ) + p_desc_cs_ac->wTotalLength); // Move pointer +// +// // From this point on we have nItfs packs of audio streaming interfaces (consisting of multiple descriptors always starting with a Standard AS Interface Descriptor(4.9.1)) +// +// uint8_t cnt; +// uint8_t nEPs; +// audio_format_type_t formatType; +// uint8_t intNum; +// uint8_t altInt; +// +// for (cnt = 0; cnt < nItfs; cnt++) +// { +// +// // Here starts an unknown number of alternate interfaces - the art here is to find the end of this interface pack. We do not have the total number of descriptor bytes available (not provided by tinyUSB stack for .open() function) so we try to find the end of this interface pack by deducing it from the order and content of the descriptor pack +// while(1) +// { +// // At first this should be a Standard AS Interface Descriptor(4.9.1) - this check can be omitted +// TU_VERIFY(itf_desc->bDescriptorType == TUSB_DESC_INTERFACE && +// itf_desc->bInterfaceClass == TUSB_CLASS_AUDIO && +// itf_desc->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING && +// itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); +// +// // Remember number of EPs this interface has - required for later +// nEPs = itf_desc->bNumEndpoints; +// intNum = itf_desc->bInterfaceNumber; +// altInt = itf_desc->bAlternateSetting; +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // It is possible now that the following interface is again a Standard AS Interface Descriptor(4.9.1) (in case the related terminal has more than zero EPs at all and this is the following alternative interface > 0 - the alternative (that this is not a Standard AS Interface Descriptor(4.9.1) but a Class-Specific AS Interface Descriptor(4.9.2)) could be in case the related terminal has no EPs at all e.g. SPDIF connector +// if (tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE) +// { +// // It is not possible, that a Standard AS Interface Descriptor(4.9.1) ends without a Class-Specific AS Interface Descriptor(4.9.2) +// // hence the next interface has to be an alternative interface with regard to the one we started above - continue +// continue; +// } +// +// // Second, this interface has to be a Class-Specific AS Interface Descriptor(4.9.2) - this check can be omitted +// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && +// ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_AS_GENERAL); +// +// // Remember format type of this interface - required for later +// formatType = ((audio_desc_cs_as_interface_t *) itf_desc)->bFormatType; +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // Every Class-Specific AS Interface Descriptor(4.9.2) defines a format type and thus a format type descriptor e.g. Type I Format Type Descriptor(2.3.1.6 - Audio Formats) should follow - only if the format type is undefined no format type descriptor follows +// if (formatType != AUDIO_FORMAT_TYPE_UNDEFINED) +// { +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Now there might be an encoder/decoder interface - i found no clue if this interface is mandatory (although examples found by google never use this descriptor) or if there is any way to determine if this descriptor is reliably present or not. Problem here: Since we need to find the end of this interface pack and we do not have the total amount of descriptor bytes available here (not given by the tinyUSB stack for the .open() function), we have to make a speculative check if the following is an encoder/decoder interface or not. +// // It could be possible that we ready over the total length of all descriptor bytes here - we simply hope that the combination of descriptor length, type, and sub type does not occur randomly in memory here. The only way to make this check waterproof is to know how many bytes we can read at all but this would be an information we need to be given by tinyUSB! +// if (tu_desc_len((uint8_t const *) itf_desc) == 21 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && (((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_ENCODER || ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_DECODER)) +// { +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Here may be some EP descriptors +// for (uint8_t cntEP = 0; cntEP < nEPs; cntEP++) +// { +// // This check can be omitted +// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_ENDPOINT); +// +// // Here we can find information about our EPs address etc. but in the initialization process we do not set anything, we have to wait for the host to send a setInterface request where the EPs etc. are set up according +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // If the usage type is something else than feedback there is a Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) following up +// if (((tusb_desc_endpoint_t *) itf_desc)->bmAttributes.usage != 0x10) +// { +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// } +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Okay we processed a complete pack - now we have to make a speculative check if the next interface is an alternate interface belonging to the ones processed before - since it is speculative we check a lot to reduce the chances we go wrong and hope for the best +// if (!(tu_desc_len((uint8_t const *) itf_desc) == 9 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE && itf_desc->bInterfaceNumber == intNum && itf_desc->bAlternateSetting == altInt + 1)) +// { +// // The current interface is not a consecutive alternate interface to the one processed above +// break; +// } +// } +// +// } + + +// Here follow the encoding steps + +//#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_UNDEFINED +// +//#error Individual encoding procedure required! +// +//#elif CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_TX == AUDIO_DATA_FORMAT_TYPE_I_PCM +// +//#if CFG_TUD_AUDIO_USE_TX_FIFO +// TU_VERIFY(audio_tx_done_type_I_pcm_cb(rhport, audio, n_bytes_copied)); +//#else +//#error YOUR ENCODING AND SENDING IS REQUIRED HERE! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX not implemented! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! +//#endif +// +// // Call a weak callback here - a possibility for user to get informed TX was completed +// TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); +// return true; + +//#if CFG_TUD_AUDIO_EPSIZE_OUT +//static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { +// +// // Here follow the decoding steps +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_UNDEFINED +// +//#error Individual decoding procedure required! +// +//#elif CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_RX == AUDIO_DATA_FORMAT_TYPE_I_PCM +// +//#if CFG_TUD_AUDIO_USE_RX_FIFO +// TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); +//#else +//#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX not implemented! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! +//#endif +// +// TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); +// return true; +//} +//#endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h new file mode 100644 index 000000000..5354adbd4 --- /dev/null +++ b/src/class/audio/audio_device.h @@ -0,0 +1,304 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) and Reinhard Panhuber + * + * 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_AUDIO_DEVICE_H_ +#define _TUSB_AUDIO_DEVICE_H_ + +#include "assert.h" +#include "common/tusb_common.h" +#include "device/usbd.h" + +#include "audio.h" +#include "tusb_config.h" + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) +#ifndef CFG_TUD_AUDIO_N_AS_INT +#define CFG_TUD_AUDIO_N_AS_INT 0 +#endif + +// Use internal FIFOs - In this case, audio.c implements FIFOs for RX and TX (whatever required) and implements encoding and decoding (parameterized by the defines below). +// For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). +// For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. +// If you disable this you need to fill in desired code into audio_rx_done_cb() and Y on your own, however, this allows for optimizations in byte processing. +#ifndef CFG_TUD_AUDIO_USE_RX_FIFO +#define CFG_TUD_AUDIO_USE_RX_FIFO 0 +#endif + +#ifndef CFG_TUD_AUDIO_USE_TX_FIFO +#define CFG_TUD_AUDIO_USE_TX_FIFO 0 +#endif + +// End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 +#ifndef CFG_TUD_AUDIO_EPSIZE_IN +#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#ifndef CFG_TUD_AUDIO_TX_BUFSIZE +#define CFG_TUD_AUDIO_TX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_IN // Buffer size per channel +#endif +#endif + +#ifndef CFG_TUD_AUDIO_EPSIZE_OUT +#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 +#ifndef CFG_TUD_AUDIO_RX_BUFSIZE +#define CFG_TUD_AUDIO_RX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_OUT // Buffer size per channel +#endif +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +#endif + +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#endif +#endif + +#ifndef CFG_TUD_AUDIO_N_CHANNELS_TX +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#endif + +#ifndef CFG_TUD_AUDIO_N_CHANNELS_RX +#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#endif + +// Audio data format types +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX +#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c +#endif + +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX +#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#endif + +// Audio data format type I specifications +#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I + +// Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +#endif + +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#endif + +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 +#define CFG_TUD_AUDIO_TX_ITEMSIZE 1 +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 +#define CFG_TUD_AUDIO_TX_ITEMSIZE 2 +#else +#define CFG_TUD_AUDIO_TX_ITEMSIZE 4 +#endif + +#endif + +#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I + +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#endif + +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#endif + +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 +#define CFG_TUD_AUDIO_RX_ITEMSIZE 1 +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 +#define CFG_TUD_AUDIO_RX_ITEMSIZE 2 +#else +#define CFG_TUD_AUDIO_RX_ITEMSIZE 4 +#endif + +#endif + +//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); + +// Supported types of this driver: +// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup AUDIO_Serial Serial + * @{ + * \defgroup AUDIO_Serial_Device Device + * @{ */ + +//--------------------------------------------------------------------+ +// Application API (Multiple Interfaces) +// CFG_TUD_AUDIO > 1 +//--------------------------------------------------------------------+ +bool tud_audio_n_mounted (uint8_t itf); + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); +void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_read_flush (uint8_t itf); +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +#endif + +//--------------------------------------------------------------------+ +// Application API (Interface0) +//--------------------------------------------------------------------+ + +inline bool tud_audio_mounted (void); + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +inline uint16_t tud_audio_available (void); +inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +inline void tud_audio_read_flush (void); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +inline uint32_t tud_audio_int_ctr_available (void); +inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); +inline void tud_audio_int_ctr_read_flush (void); +inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN +bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT +bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +bool tud_audio_fb_done_cb(uint8_t rhport); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +#endif + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +inline bool tud_audio_mounted(void) +{ + return tud_audio_n_mounted(0); +} + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +{ + return tud_audio_n_write(0, channelId, buffer, bufsize); +} +#endif // CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +inline uint16_t tud_audio_available(uint8_t channelId) +{ + return tud_audio_n_available(0, channelId); +} + +inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +{ + return tud_audio_n_read(0, channelId, buffer, bufsize); +} + +inline void tud_audio_read_flush(uint8_t channelId) +{ + tud_audio_n_read_flush(0, channelId); +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +inline uint16_t tud_audio_int_ctr_available(void) +{ + return tud_audio_int_ctr_n_available(0); +} + +inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) +{ + return tud_audio_int_ctr_n_read(0, buffer, bufsize); +} + +inline void tud_audio_int_ctr_read_flush(void) +{ + return tud_audio_int_ctr_n_read_flush(0); +} + +inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +{ + return tud_audio_int_ctr_n_write(0, buffer, bufsize); +} +#endif + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void audiod_init (void); +void audiod_reset (uint8_t rhport); +bool audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_AUDIO_DEVICE_H_ */ + +/** @} */ +/** @} */ diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..a19993cad 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -135,6 +135,19 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif +#if CFG_TUD_AUDIO +{ + DRIVER_NAME("AUDIO") + .init = audiod_init, + .reset = audiod_reset, + .open = audiod_open, + .control_request = audiod_control_request, + .control_complete = audiod_control_complete, + .xfer_cb = audiod_xfer_cb, + .sof = NULL +}, +#endif + #if CFG_TUD_MIDI { DRIVER_NAME("MIDI") diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..24a2332e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -307,6 +307,43 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ TUD_MIDI_JACKID_OUT_EMB(1) +//------------- AUDIO -------------// + +// Length of template descriptor (132 bytes) +#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) +#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 + +// AUDIO simple descriptor (UAC2) for 1 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source +#define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ + /* Standard AC Interface Descriptor(4.7.1) */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ + /* Clock Source Descriptor(4.7.2.1) */\ + 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ + /* Input Terminal Descriptor(4.7.2.4) */\ + 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ + /* Output Terminal Descriptor(4.7.2.5) */\ + 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ + /* Feature Unit Descriptor(4.7.2.8) */\ + 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, \ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000)\ //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) diff --git a/src/tusb.h b/src/tusb.h index 55c105121..ecd885c26 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -76,6 +76,10 @@ #include "class/msc/msc_device.h" #endif +#if CFG_TUD_AUDIO + #include "class/audio/audio_device.h" +#endif + #if CFG_TUD_MIDI #include "class/midi/midi_device.h" #endif -- cgit v1.3.1 From d4bf777c943659a4e985ce8514ef077c5bf2b40d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 May 2020 11:01:33 +0700 Subject: try to get synopsys work with OTG HS + external PHY --- src/device/usbd.c | 1 + src/portable/st/synopsys/dcd_synopsys.c | 80 +++++++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..bd892e389 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -384,6 +384,7 @@ void tud_task (void) { case DCD_EVENT_BUS_RESET: usbd_reset(event.rhport); + // TODO DCD should report operational speed (LS/FS/HS) break; case DCD_EVENT_UNPLUGGED: diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b68794712..8ca67dbb4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -99,7 +99,7 @@ static const dcd_rhport_t _dcd_rhport[] = { .regs = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn } #ifdef USB_OTG_HS - ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } + ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } #endif }; @@ -218,16 +218,48 @@ static void end_of_reset(uint8_t rhport) *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { + dcd_disconnect(rhport); + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - // Programming model begins in the last section of the chapter on the USB - // peripheral in each Reference Manual. - usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + // No HNP/SRP (no OTG support), program timeout later. +#if TUD_OPT_HIGH_SPEED // TODO may pass parameter instead of using macro for HighSpeed + if ( rhport == 1 ) + { + // Highspeed with external ULPI PHY + + // deactivate internal PHY + usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; + + // On selected MCUs HS port1 can be used with external PHY via ULPI interface + // Select ULPI highspeed PHY with default external VBUS Indicator and Drive + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | + USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); + + // Turn around time for Highspeed is 0x09 + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + }else +#endif + { + // Turn around programmed for 32+ MHz is 0x06 + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + } + + // Reset core after selecting PHY + // Wait AHB IDLE, reset then wait until it is cleared + while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U) {} + usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} + + // Force device mode + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + + TU_LOG2_LOCATION(); - // No HNP/SRP (no OTG support), program timeout later, turnaround - // programmed for 32+ MHz. - // TODO: PHYSEL is read-only on some cores (STM32F407). Worth gating? - usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + // Restart PHY clock + *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; // Clear all interrupts usb_otg->GINTSTS |= usb_otg->GINTSTS; @@ -241,14 +273,33 @@ void dcd_init (uint8_t rhport) // If USB host misbehaves during status portion of control xfer // (non zero-length packet), send STALL back and discard. Full speed. - dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos); + dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; + +#if TUD_OPT_HIGH_SPEED + if ( rhport == 1 ) + { + // high speed = 0x00 + dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); + + // Transceiver delay, necessary for some ULPI PHYs + dev->DCFG |= (1 << 14); + } +#endif + { + // full speed with internal phy + dev->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); + + // Enable USB transceiver. + usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; + } usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | - USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | - USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); - // Enable USB transceiver. - usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. + usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; } void dcd_int_enable (uint8_t rhport) @@ -739,6 +790,9 @@ void dcd_int_handler(uint8_t rhport) // ENUMDNE detects speed of the link. For full-speed, we // always expect the same value. This interrupt is considered // the end of reset. + + TU_LOG2_HEX(dev->DSTS); + usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; end_of_reset(rhport); dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); -- cgit v1.3.1 From e3404049686adfd934a6444fadf9ae00f1f94f8a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 May 2020 19:01:59 +0700 Subject: changing usbd driver open() return type, add max_len only done with cdc and msc, push this interim for feedback first --- src/class/cdc/cdc_device.c | 26 ++++++++++++++------------ src/class/cdc/cdc_device.h | 12 ++++++------ src/class/msc/msc_device.c | 16 ++++++++++------ src/class/msc/msc_device.h | 12 ++++++------ src/device/usbd.c | 30 ++++++++++++++++++------------ 5 files changed, 54 insertions(+), 42 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 2d8f986ae..a24f348f4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -222,14 +222,16 @@ void cdcd_reset(uint8_t rhport) } } -bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // Only support ACM subclass TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); // Note: 0xFF can be used with RNDIS - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA)); + TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); + + uint16_t len = 0; // Find available interface cdcd_interface_t * p_cdc = NULL; @@ -242,29 +244,29 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t break; } } - TU_ASSERT(p_cdc); + TU_ASSERT(p_cdc, 0); //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + len = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) { - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint if any - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -276,15 +278,15 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_desc = tu_desc_next(p_desc); // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data _prep_out_transaction(cdc_id); - return true; + return len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 69542a3b3..a2523d8d0 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -229,12 +229,12 @@ static inline uint32_t tud_cdc_write_available(void) //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 70ba956aa..9955f2f05 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -154,25 +154,29 @@ void mscd_reset(uint8_t rhport) tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } -bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) +uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // only support SCSI's BOT protocol TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); + MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); + // Max length mus be at least 1 interface + 2 endpoints + TU_VERIFY(max_len >= sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t), 0); + + uint16_t len = 0; mscd_interface_t * p_msc = &_mscd_itf; // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); p_msc->itf_num = itf_desc->bInterfaceNumber; - (*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); // Prepare for Command Block Wrapper - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); - return true; + return len; } // Handle class control request diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 66180777e..30ffd02e1 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -151,12 +151,12 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -bool mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..971417a35 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -85,13 +85,13 @@ typedef struct char const* name; #endif - void (* init ) (void); - void (* reset ) (uint8_t rhport); - bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; static usbd_class_driver_t const _usbd_driver[] = @@ -713,6 +713,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + uint16_t const remaining_len = desc_end-p_desc; + uint8_t drv_id; uint16_t drv_len; @@ -720,13 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) + drv_len = driver->open(rhport, desc_itf, remaining_len); + + if ( drv_len > 0 ) { + // Open successfully, check if length is correct + TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); + // Interface number must not be used already TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", driver->name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -748,8 +754,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + // Failed if cannot find supported driver + TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor -- cgit v1.3.1 From 077437b3dc2772ba87e6d43baf906d29b7539ca5 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 13 May 2020 16:45:01 +0200 Subject: Add non standard request handling in class For some reason bluetooth stack implementations send class requests to device instead of interface. To implement HCI interface over USB non device addressed requests for class need to be handled. --- src/device/usbd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 971417a35..3cbd50644 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -507,6 +507,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { //------------- Device Requests e.g in enumeration -------------// case TUSB_REQ_RCPT_DEVICE: + if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) + { + uint8_t const itf = tu_u16_low(p_request->wIndex); + TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); + + uint8_t const drvid = _usbd_dev.itf2drv[itf]; + TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); + + // forward to class driver: "non-STD request to Interface" + TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); + return true; + } if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Non standard request is not supported -- cgit v1.3.1 From 56d46483e48879cb8a38dc13d7327daa15165754 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 13 May 2020 17:04:10 +0200 Subject: Add bt hci device class Code implements USB transport for bluetooth HCI. --- src/class/bth/bth_device.c | 252 +++++++++++++++++++++++++++++++++++++++++++++ src/class/bth/bth_device.h | 110 ++++++++++++++++++++ src/device/usbd.c | 13 +++ src/device/usbd.h | 54 ++++++++++ src/tusb.h | 4 + src/tusb_option.h | 4 + 6 files changed, 437 insertions(+) create mode 100755 src/class/bth/bth_device.c create mode 100755 src/class/bth/bth_device.h (limited to 'src/device') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c new file mode 100755 index 000000000..04011bcdb --- /dev/null +++ b/src/class/bth/bth_device.c @@ -0,0 +1,252 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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_BTH) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "bth_device.h" +#include +#include + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_ev; + uint8_t ep_acl_in; + uint8_t ep_acl_out; + uint8_t ep_voice[2]; // Not used yet + uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; + +} btd_interface_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; + +static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) +{ + // skip if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep)); + + TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len)); + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +bool tud_bt_event_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_ev, event, event_len); +} + +bool tud_bt_acl_data_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void btd_init(void) +{ + tu_memclr(&_btd_itf, sizeof(_btd_itf)); +} + +void btd_reset(uint8_t rhport) +{ + (void)rhport; +} + +uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + tusb_desc_endpoint_t const *desc_ep; + uint16_t drv_len = 0; + // Size of single alternative of ISO interface + const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); + // Size of hci interface + const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); + // Ensure this is BT Primary Controller + TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + + // Distinguish interface by number of endpoints, as both interface have same class, subclass and protocol + if (itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size) + { + _btd_itf.itf_num = itf_desc->bInterfaceNumber; + + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(dcd_edpt_open(rhport, desc_ep), 0); + _btd_itf.ep_ev = desc_ep->bEndpointAddress; + + // Open endpoint pair + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, + &_btd_itf.ep_acl_in), 0); + + // Prepare for incoming data from host + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + + drv_len = hci_itf_size; + } + else if (itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size) + { + uint8_t dir; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + + for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { + // Make sure rest of alternatives matches + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); + if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || + TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || + TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) + { + // Not an Iso interface instance + break; + } + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + } + } + + return drv_len; +} + +bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); + + return true; +} + +bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) + { + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); + } + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + { + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } + } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); +} + +bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; + + // received new data from host + if (ep_addr == _btd_itf.ep_acl_out) + { + if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); + + // prepare for next data + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); + } + else if (ep_addr == _btd_itf.ep_ev) + { + if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); + } + else if (ep_addr == _btd_itf.ep_acl_in) + { + if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); + } + + return TUSB_ERROR_NONE; +} + +#endif diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h new file mode 100755 index 000000000..5e5468084 --- /dev/null +++ b/src/class/bth/bth_device.h @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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_BTH_DEVICE_H_ +#define _TUSB_BTH_DEVICE_H_ + +#include +#include + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ +#ifndef CFG_TUD_BTH_EVENT_EPSIZE +#define CFG_TUD_BTH_EVENT_EPSIZE 16 +#endif +#ifndef CFG_TUD_BTH_DATA_EPSIZE +#define CFG_TUD_BTH_DATA_EPSIZE 64 +#endif + +typedef struct TU_ATTR_PACKED +{ + uint16_t op_code; + uint8_t param_length; + uint8_t param[255]; +} bt_hci_cmd_t; + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when HCI command was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.1. +// Length of the command is from 3 bytes (2 bytes for OpCode, +// 1 byte for parameter total length) to 258. +TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); + +// Invoked when ACL data was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.2. +// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length) to endpoint size. +TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); + +// Called when event sent with tud_bt_event_send() was delivered to BT stack. +// Controller can release/reuse buffer with Event packet at this point. +TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); + +// Called when ACL data that was sent with tud_bt_acl_data_send() +// was delivered to BT stack. +// Controller can release/reuse buffer with ACL packet at this point. +TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); + +// Bluetooth controller calls this function when it wants to send even packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. +// Event has at least 2 bytes, first is Event code second contains parameter +// total length. Controller can release/reuse event memory after +// tud_bt_event_sent_cb() is called. +bool tud_bt_event_send(void *event, uint16_t event_len); + +// Bluetooth controller calls this to send ACL data packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 +// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length). Upper limit is not limited +// to endpoint size since buffer is allocate by controller +// and must not be reused till tud_bt_acl_data_sent_cb() is called. +bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 3cbd50644..fe392ef6e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,6 +199,19 @@ static usbd_class_driver_t const _usbd_driver[] = .sof = NULL, }, #endif + + #if CFG_TUD_BTH + { + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_request = btd_control_request, + .control_complete = btd_control_complete, + .xfer_cb = btd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..2070b50c6 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -438,6 +438,60 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 +//------------- BT Radio -------------// +#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) +#define TUD_BT_APP_SUBCLASS 0x01 +#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 +#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 + +#ifndef CFG_TUD_BTH_ISO_ALT_COUNT +#define CFG_TUD_BTH_ISO_ALT_COUNT 0 +#endif + +// Length of template descriptor: 30 bytes + number of ISO alternatives * 23 +#define TUD_BTH_DESC_LEN (9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) + +/* Primary Interface */ +#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + +#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + +#define _FIRST(a, ...) a +#define _REST(a, ...) __VA_ARGS__ + +#define TUD_BTH_ISO_ITF_0(_itfnum, ...) +#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + +#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + +// BT Primary controller descriptor +// Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes +#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus } diff --git a/src/tusb.h b/src/tusb.h index 55c105121..defbc54fb 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -95,6 +95,10 @@ #if CFG_TUD_NET #include "class/net/net_device.h" #endif + + #if CFG_TUD_BTH + #include "class/bth/bth_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 9e6a2b532..0a227483f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -219,6 +219,10 @@ #define CFG_TUD_NET 0 #endif +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + //-------------------------------------------------------------------- // HOST OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From d6d29897f38ebc8bc8b660d2749e472b39537b34 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 23:16:16 +0700 Subject: add get device qualifier descriptor --- src/device/usbd.c | 24 +++++++++++++++++++++--- src/device/usbd.h | 10 ++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 971417a35..3af9491e2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -867,9 +867,27 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_DEVICE_QUALIFIER: TU_LOG2(" Device Qualifier\r\n"); - // TODO If not highspeed capable stall this request otherwise - // return the descriptor that could work in highspeed - return false; + // Host sends this request to ask why our device with USB BCD from 2.0 + // but is running at Full/Low Speed. If not highspeed capable stall this request, + // otherwise return the descriptor that could work in highspeed mode + if ( tud_descriptor_device_qualifier_cb ) + { + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + TU_ASSERT(desc_qualifier); + + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]); + }else + { + return false; + } + break; + + case TUSB_DESC_OTHER_SPEED_CONFIG: + TU_LOG2(" Other Speed Configuration\r\n"); + + // After Device Qualifier descriptor is received host will ask for this descriptor + return false; // not supported break; default: return false; diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..9af700886 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -68,6 +68,8 @@ static inline bool tud_ready(void) // Remote wake up host, only if suspended and enabled by host bool tud_remote_wakeup(void); +// Enable pull-up resistor on D+ D- +// Return false on unsupported MCUs static inline bool tud_disconnect(void) { TU_VERIFY(dcd_disconnect); @@ -75,6 +77,8 @@ static inline bool tud_disconnect(void) return true; } +// Disable pull-up resistor on D+ D- +// Return false on unsupported MCUs static inline bool tud_connect(void) { TU_VERIFY(dcd_connect); @@ -110,6 +114,10 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); + // Invoked when device is mounted (configured) TU_ATTR_WEAK void tud_mount_cb(void); @@ -125,6 +133,8 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); + +// Invoked when vendor control request is complete TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); -- cgit v1.3.1 From f771afe6af894a5f3ee029756d4521b56d74c1c0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 31 May 2020 23:43:29 +0700 Subject: fixed EP0 size to 64 since LS is not supported in device mode - set turn-around and report actual speed in Enum Done - add dcd_event_bus_reset() helper to report speed --- src/device/dcd.h | 15 ++++-- src/device/usbd.c | 9 +++- src/portable/st/synopsys/dcd_synopsys.c | 85 ++++++++++++++++----------------- 3 files changed, 62 insertions(+), 47 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 68798c259..a4635346b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -60,11 +60,17 @@ typedef struct TU_ATTR_ALIGNED(4) uint8_t rhport; uint8_t event_id; - union { - // USBD_EVT_SETUP_RECEIVED + union + { + // BUS RESET + struct { + tusb_speed_t speed; + } bus_reset; + + // SETUP_RECEIVED tusb_control_request_t setup_received; - // USBD_EVT_XFER_COMPLETE + // XFER_COMPLETE struct { uint8_t ep_addr; uint8_t result; @@ -143,6 +149,9 @@ extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); // helper to send bus signal event extern void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); +// helper to send bus reset event +extern void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr); + // helper to send setup received extern void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); diff --git a/src/device/usbd.c b/src/device/usbd.c index bd892e389..275792ab9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -920,7 +920,14 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) 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_t event = { .rhport = rhport, .event_id = eid }; + dcd_event_handler(&event, in_isr); +} + +void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; + event.bus_reset.speed = speed; dcd_event_handler(&event, in_isr); } diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index fe6fe5cea..ed16308da 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -109,6 +109,13 @@ static const dcd_rhport_t _dcd_rhport[] = #define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_IN_ENDPOINT_BASE) #define FIFO_BASE(_port, _x) ((volatile uint32_t *) (_dcd_rhport[_port].regs + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) +enum +{ + DCD_HIGH_SPEED = 0, // Highspeed mode + DCD_FULL_SPEED_USE_HS = 1, // Full speed in Highspeed port (probably with internal PHY) + DCD_FULL_SPEED = 3, // Full speed with internal PHY +}; + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM @@ -141,6 +148,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; @@ -183,34 +191,29 @@ static void bus_reset(uint8_t rhport) // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (usb_otg->GRXFSIZ & 0x0000ffffUL); + // Fixed control EP0 size to 64 bytes + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } -static void end_of_reset(uint8_t rhport) +// speed is native DCD speed +static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, uint32_t speed) { - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; - - // TODO set turnaround in GUSBCFG accordingly to the speed - - // Maximum packet size for EP 0 is set for both directions by writing - // DIEPCTL. - if(enum_spd == 0x03) { - // 64 bytes - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - // 8 bytes - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; + if ( speed == DCD_HIGH_SPEED ) + { + // Use fixed 0x09 for Highspeed + usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + } + else + { + // Fullspeed depends on MCU clocks, but we will use 0x06 for 32+ Mhz + usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos); } } @@ -220,7 +223,8 @@ static void end_of_reset(uint8_t rhport) *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { - dcd_disconnect(rhport); + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); @@ -238,16 +242,15 @@ void dcd_init (uint8_t rhport) usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - // Turn around time for Highspeed is 0x09 - usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + set_turnaround(usb_otg, DCD_HIGH_SPEED); } else #endif { - // Turn around programmed for 32+ MHz is 0x06 - usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + set_turnaround(usb_otg, DCD_FULL_SPEED); + + // Enable internal PHY + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; } // Reset core after selecting PHY @@ -256,9 +259,6 @@ void dcd_init (uint8_t rhport) usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} - // Force device mode - usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; - // Restart PHY clock *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; @@ -273,7 +273,7 @@ void dcd_init (uint8_t rhport) USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); // If USB host misbehaves during status portion of control xfer - // (non zero-length packet), send STALL back and discard. Full speed. + // (non zero-length packet), send STALL back and discard. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; #if TUD_OPT_HIGH_SPEED @@ -288,10 +288,10 @@ void dcd_init (uint8_t rhport) else #endif { - // full speed with internal phy + // full speed with internal PHY dev->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); - // Enable USB transceiver. + // Enable internal USB transceiver. usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; } @@ -299,8 +299,8 @@ void dcd_init (uint8_t rhport) USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); - // Programming model begins in the last section of the chapter on the USB - // peripheral in each Reference Manual. + + // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; } @@ -789,15 +789,14 @@ void dcd_int_handler(uint8_t rhport) } if(int_status & USB_OTG_GINTSTS_ENUMDNE) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - - TU_LOG2_HEX(dev->DSTS); + // ENUMDNE is the end of reset where speed of the link is detected usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; - end_of_reset(rhport); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + + uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + + set_turnaround(usb_otg, enum_spd); + dcd_event_bus_reset(rhport, (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true); } if(int_status & USB_OTG_GINTSTS_USBSUSP) -- cgit v1.3.1 From e92118635cc8055a5ca599eaf9919d99a55bf584 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 1 Jun 2020 13:40:18 +0700 Subject: adding speed detect on bus reset --- hw/bsp/stm32h743eval/board.mk | 2 +- src/device/usbd.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index 5c6c6ea4f..cbf37a95d 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -48,7 +48,7 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = stm32h743xi -JLINK_IF = jtag +JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/src/device/usbd.c b/src/device/usbd.c index 275792ab9..eeb5011ec 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -40,7 +40,8 @@ //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ -typedef struct { +typedef struct +{ struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -53,6 +54,8 @@ typedef struct { uint8_t self_powered : 1; // configuration descriptor's attribute }; + uint8_t speed; + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) @@ -384,7 +387,7 @@ void tud_task (void) { case DCD_EVENT_BUS_RESET: usbd_reset(event.rhport); - // TODO DCD should report operational speed (LS/FS/HS) + _usbd_dev.speed = event.bus_reset.speed; break; case DCD_EVENT_UNPLUGGED: -- cgit v1.3.1 From 4362665fb3ec1ef0d749bbcdaabe161ce1c06614 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Jun 2020 12:36:05 +0200 Subject: Fix mic audio descriptor, fix too strict check on IAD desc. in usbd.c --- src/class/audio/audio.h | 6 + src/class/audio/audio_device.c | 8 +- src/class/audio/audio_device.h | 2 +- src/device/usbd.c | 2 +- src/device/usbd.h | 521 +++++++++++++++++++++++++---------------- 5 files changed, 330 insertions(+), 209 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index f4f460c22..022f3118f 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -57,6 +57,12 @@ typedef enum AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; +/// Audio Function Subclass Codes +typedef enum +{ + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; + /// Audio Protocol Codes typedef enum { diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fbd412564..1c9e0494e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -632,7 +632,7 @@ void audiod_reset(uint8_t rhport) } } -bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); @@ -666,9 +666,11 @@ bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_ // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) // Notify caller we read complete descriptor - (*p_length) += tud_audio_desc_lengths[i]; +// (*p_length) += tud_audio_desc_lengths[i]; + // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow + uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - return true; + return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5354adbd4..3e1fa7a92 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -289,7 +289,7 @@ inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) //--------------------------------------------------------------------+ void audiod_init (void); void audiod_reset (uint8_t rhport); -bool audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 26c7d3936..912c922c5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -779,7 +779,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // IAD's first interface number and class/subclass/protocol should match with opened interface TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && - desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && + // desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); for(uint8_t i=1; ibInterfaceCount; i++) diff --git a/src/device/usbd.h b/src/device/usbd.h index 7bc79a6f6..39ad7639e 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -31,7 +31,7 @@ #define _TUSB_USBD_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif #include "common/tusb_common.h" @@ -62,7 +62,7 @@ bool tud_suspended(void); // Check if device is ready to transfer static inline bool tud_ready(void) { - return tud_mounted() && !tud_suspended(); + return tud_mounted() && !tud_suspended(); } // Remote wake up host, only if suspended and enabled by host @@ -72,18 +72,18 @@ bool tud_remote_wakeup(void); // Return false on unsupported MCUs static inline bool tud_disconnect(void) { - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; } // Disable pull-up resistor on D+ D- // Return false on unsupported MCUs static inline bool tud_connect(void) { - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; } // Carry out Data and Status stage of control transfer @@ -146,11 +146,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // total length, number of device caps #define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ - 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num + 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num // Device Capability Platform 128-bit UUID + Data #define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ - 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ + 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ //------------- WebUSB BOS Platform -------------// @@ -159,22 +159,22 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Vendor Code, iLandingPage #define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) #define TUD_BOS_WEBUSB_UUID \ - 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ - 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 + 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ + 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 //------------- Microsoft OS 2.0 Platform -------------// #define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 // Total Length of descriptor set, vendor code #define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) #define TUD_BOS_MS_OS_20_UUID \ - 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ - 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ + 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F //--------------------------------------------------------------------+ // Configuration & Interface Descriptor Templates @@ -185,7 +185,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Config number, interface count, string index, total length, attribute, power in mA #define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// @@ -195,26 +195,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ - /* CDC Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC Call */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Associate */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ + /* CDC Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC Call */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* CDC ACM: support line request */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- MSC -------------// @@ -223,12 +223,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & EP In address, EP size #define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- HID -------------// @@ -238,12 +238,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input only descriptor // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval // Length of template descriptor: 32 bytes #define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) @@ -251,57 +251,57 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ - /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ - /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ - /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ - /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + /* Audio Control (AC) Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ + /* AC Header */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + /* MIDI Streaming (MS) Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ + /* MS Header */\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) #define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 1) + (uint8_t)(((_cablenum) - 1) * 4 + 1) #define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 2) + (uint8_t)(((_cablenum) - 1) * 4 + 2) #define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 3) + (uint8_t)(((_cablenum) - 1) * 4 + 3) #define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 4) + (uint8_t)(((_cablenum) - 1) * 4 + 4) #define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) #define TUD_MIDI_DESC_JACK(_cablenum) \ - /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ - /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ - /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ - /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + /* MS In Jack (Embedded) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ + /* MS In Jack (External) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ + /* MS Out Jack (Embedded), connected to In Jack External */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ + /* MS Out Jack (External), connected to In Jack Embedded */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 #define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack) */\ - (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + /* Endpoint */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables // Length of template descriptor (88 bytes) #define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) @@ -310,50 +310,163 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // - 1 Embedded Jack In connected to 1 External Jack Out // - 1 Embedded Jack out connected to 1 External Jack In #define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ - TUD_MIDI_DESC_JACK(1),\ - TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ - TUD_MIDI_JACKID_IN_EMB(1),\ - TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ - TUD_MIDI_JACKID_OUT_EMB(1) + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) //------------- AUDIO -------------// -// Length of template descriptor (132 bytes) -#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) -#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 +/* Standard Interface Association Descriptor (IAD) */ +#define TUD_AUDIO_DESC_IAD_LEN 8 +#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_PROTOCOL_V2, _stridx + +/* Standard AC Interface Descriptor(4.7.1) */ +#define TUD_AUDIO_DESC_STD_AC_LEN 9 +#define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx + +/* Class-Specific AC Interface Header Descriptor(4.7.2) */ +#define TUD_AUDIO_DESC_CS_AC_LEN 9 +#define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ + TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl + +/* Clock Source Descriptor(4.7.2.1) */ +#define TUD_AUDIO_DESC_CLK_SRC_LEN 8 +#define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ + TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx + +/* Input Terminal Descriptor(4.7.2.4) */ +#define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 +#define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ + TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx + +/* Output Terminal Descriptor(4.7.2.5) */ +#define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 +#define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx + +/* Feature Unit Descriptor(4.7.2.8) */ +// 1 - Channel +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx + +// For more channels, add definitions here + +/* Standard AS Interface Descriptor(4.9.1) */ +#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 +#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, _stridx + +/* Class-Specific AS Interface Descriptor(4.9.2) */ +#define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 +#define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ + TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx + +/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ +#define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 +#define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution + +/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval + +/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ +#define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 +#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces + #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ - /* Standard AC Interface Descriptor(4.7.1) */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ - /* Clock Source Descriptor(4.7.2.1) */\ - 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ - /* Input Terminal Descriptor(4.7.2.4) */\ - 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ - /* Output Terminal Descriptor(4.7.2.5) */\ - 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ - /* Feature Unit Descriptor(4.7.2.8) */\ - 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, \ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000)\ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +// Length of template descriptor (132 bytes) +//#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) +//#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 +// +// // AUDIO simple descriptor (UAC2) for 1 microphone input +// // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source +// #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +// /* Standard Interface Association Descriptor (IAD) */\ +// 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Standard AC Interface Descriptor(4.7.1) */\ +// 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ +// /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ +// 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ +// /* Clock Source Descriptor(4.7.2.1) */\ +// 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ +// /* Input Terminal Descriptor(4.7.2.4) */\ +// 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ +// /* Output Terminal Descriptor(4.7.2.5) */\ +// 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ +// /* Feature Unit Descriptor(4.7.2.8) */\ +// 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ +// /* Standard AS Interface Descriptor(4.9.1) */\ +// /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ +// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Standard AS Interface Descriptor(4.9.1) */\ +// /* Interface 1, Alternate 1 - alternate interface for data streaming */\ +// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Class-Specific AS Interface Descriptor(4.9.2) */\ +// 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00,\ +// /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ +// 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ +// /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ +// 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ +// /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ +// 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000) + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -365,23 +478,23 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, // bulk-in endpoint ID #define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ - /* Interface */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + /* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx #define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u #define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ - /* Endpoint Out */ \ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ - /* Endpoint In */ \ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + /* Endpoint Out */ \ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ + /* Endpoint In */ \ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u #define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) /* optional interrupt endpoint */ \ // _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? #define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ - 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 #define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) @@ -391,12 +504,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & IN address, EP size #define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* 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) @@ -408,10 +521,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // 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) + /* 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) //------------- CDC-ECM -------------// @@ -422,40 +535,40 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-ECM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC-ECM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-ECM Functional Descriptor */\ - 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface (default inactive) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* CDC Data Interface (alternative active) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-ECM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- RNDIS -------------// #if 0 - /* Windows XP */ - #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC - #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL - #define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ +/* Windows XP */ +#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC +#define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +#define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ #else - /* Windows 7+ */ - #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER - #define TUD_RNDIS_ITF_SUBCLASS 0x01 - #define TUD_RNDIS_ITF_PROTOCOL 0x03 +/* Windows 7+ */ +#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER +#define TUD_RNDIS_ITF_SUBCLASS 0x01 +#define TUD_RNDIS_ITF_PROTOCOL 0x03 #endif // Length of template descriptor: 66 bytes @@ -464,26 +577,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // RNDIS Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ - /* CDC-ACM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC Call Management */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* ACM */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- BT Radio -------------// #define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) @@ -500,20 +613,20 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Endpoint In for events */ \ - 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ - /* Endpoint In for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ - /* Endpoint Out for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 #define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ - /* Interface with 2 endpoints */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Isochronous endpoints */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 #define _FIRST(a, ...) a #define _REST(a, ...) __VA_ARGS__ @@ -521,27 +634,27 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_BTH_ISO_ITF_0(_itfnum, ...) #define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ - TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) // BT Primary controller descriptor // Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes #define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ - TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus - } +} #endif #endif /* _TUSB_USBD_H_ */ -- cgit v1.3.1 From 48b2e6cf78a3c3a321715938e40166138ed605f5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Jun 2020 13:51:50 +0200 Subject: Fix too strict checks on subclass and interface of iad descriptor. --- src/device/usbd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 3708a9aff..040155d41 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -765,9 +765,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { // IAD's first interface number and class/subclass/protocol should match with opened interface TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && - desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && - desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From 862d1667f0c7e94af29f92d575a7d14dbe126a66 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:55:52 +0200 Subject: Fix alignment. --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 6e2e5635a..ff127a3c1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -777,8 +777,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if (desc_itf_assoc) { // IAD's first interface number and class/subclass/protocol should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From 3012175351fa1f262533527c0444ce9d44917943 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:57:00 +0200 Subject: Fix alignment. --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 040155d41..f11696e78 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -764,8 +764,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if (desc_itf_assoc) { // IAD's first interface number and class/subclass/protocol should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From b25bbf4776cb992f25faf607077f39810165eebe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:58:16 +0200 Subject: Fix alignment. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f11696e78..e5ff52542 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -764,7 +764,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if (desc_itf_assoc) { // IAD's first interface number and class/subclass/protocol should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) -- cgit v1.3.1 From 95966c22010bf01579f39847624395724298c459 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 14 Jun 2020 18:29:02 +0700 Subject: improve usbd log for control transfer --- src/device/usbd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index eeb5011ec..c337f1be1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -380,17 +380,21 @@ void tud_task (void) if ( !osal_queue_receive(_usbd_q, &event) ) return; - TU_LOG2("USBD %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); - TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); +#if CFG_TUSB_DEBUG >= 2 + if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup + TU_LOG2("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); +#endif switch ( event.event_id ) { case DCD_EVENT_BUS_RESET: + TU_LOG2("\r\n"); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; break; case DCD_EVENT_UNPLUGGED: + TU_LOG2("\r\n"); usbd_reset(event.rhport); // invoke callback @@ -442,14 +446,17 @@ void tud_task (void) break; case DCD_EVENT_SUSPEND: + TU_LOG2("\r\n"); if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: + TU_LOG2("\r\n"); if (tud_resume_cb) tud_resume_cb(); break; case DCD_EVENT_SOF: + TU_LOG2("\r\n"); for ( uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++ ) { if ( _usbd_driver[i].sof ) @@ -460,6 +467,7 @@ void tud_task (void) break; case USBD_EVENT_FUNC_CALL: + TU_LOG2("\r\n"); if ( event.func_call.func ) event.func_call.func(event.func_call.param); break; -- cgit v1.3.1 From bc7e24b659e0d184f3405681af5f13bd4a5094aa Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 14:22:10 +0200 Subject: Fix wrong comment for IAD checks. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index e5ff52542..29b10c0fa 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -763,7 +763,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // If IAD exist, assign all interfaces to the same driver if (desc_itf_assoc) { - // IAD's first interface number and class/subclass/protocol should match with opened interface + // IAD's first interface number and class should match with opened interface TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); -- cgit v1.3.1 From 57b553e023ccac4c623bd7f57a7370fb43411ec1 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Tue, 16 Jun 2020 14:13:30 +0200 Subject: Fix IAR warnings. Pa039 : use of address of unaligned structure member. Pe188: enumerated type mixed with another type. --- src/class/hid/hid_device.c | 4 +++- src/class/msc/msc_device.c | 6 ++++-- src/device/usbd.c | 13 +++++++------ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - 4 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src/device') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2a20bc173..526394d4a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,7 +194,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); // Prepare for output endpoint if (p_hid->ep_out) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b038d00f7..3ddcd4e49 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) // copy first to prevent mis-aligned access uint32_t lba; - memcpy(&lba, &p_rdwr10->lba, 4); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); // lba is in Big Endian format return tu_ntohl(lba); @@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) // copy first to prevent mis-aligned access uint16_t block_count; - memcpy(&block_count, &p_rdwr10->block_count, 2); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); return tu_ntohs(block_count); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 29b10c0fa..03ef655bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -437,7 +437,7 @@ void tud_task (void) if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } else { @@ -445,7 +445,7 @@ void tud_task (void) TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); - _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -846,8 +846,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if (!tud_descriptor_bos_cb) return false; tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uint16_t total_len; - memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } @@ -861,7 +863,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_ASSERT(desc_config); uint16_t total_len; - memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -915,8 +918,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const default: return false; } - - return true; } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c5666421b..b539f4795 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -698,7 +698,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc default: TU_ASSERT(false); - return false; } pcd_set_eptype(USB, epnum, wType); -- cgit v1.3.1 From ada82b840f642681f8012cb2a46aa7577393dd30 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 20 Jun 2020 10:51:21 +0200 Subject: Get update from tinyusb. --- src/class/hid/hid_device.c | 4 +++- src/class/msc/msc_device.c | 6 ++++-- src/device/usbd.c | 21 ++++++++++----------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - 4 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/device') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2a20bc173..526394d4a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,7 +194,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); // Prepare for output endpoint if (p_hid->ep_out) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b038d00f7..3ddcd4e49 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) // copy first to prevent mis-aligned access uint32_t lba; - memcpy(&lba, &p_rdwr10->lba, 4); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); // lba is in Big Endian format return tu_ntohl(lba); @@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) // copy first to prevent mis-aligned access uint16_t block_count; - memcpy(&block_count, &p_rdwr10->block_count, 2); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); return tu_ntohs(block_count); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 3708a9aff..03ef655bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -437,7 +437,7 @@ void tud_task (void) if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } else { @@ -445,7 +445,7 @@ void tud_task (void) TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); - _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -763,11 +763,9 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // If IAD exist, assign all interfaces to the same driver if (desc_itf_assoc) { - // IAD's first interface number and class/subclass/protocol should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && - desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && - desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + // IAD's first interface number and class should match with opened interface + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { @@ -848,8 +846,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if (!tud_descriptor_bos_cb) return false; tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uint16_t total_len; - memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } @@ -863,7 +863,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_ASSERT(desc_config); uint16_t total_len; - memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -917,8 +918,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const default: return false; } - - return true; } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c5666421b..b539f4795 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -698,7 +698,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc default: TU_ASSERT(false); - return false; } pcd_set_eptype(USB, epnum, wType); -- cgit v1.3.1 From 706413f7510a78e262cf3cb398256e06fadbd500 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 00:44:09 +0700 Subject: add tud_speed_get() - define both fs and hs configuration descriptor - rename CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE with default size of 64 for FS, and 512 for HS --- .../device/cdc_dual_ports/src/usb_descriptors.c | 48 +++++++++++++++++----- examples/device/cdc_msc/src/usb_descriptors.c | 28 +++++++++++-- .../device/webusb_serial/src/usb_descriptors.c | 6 +-- examples/rules.mk | 8 +++- src/class/cdc/cdc_device.c | 14 +++---- src/class/cdc/cdc_device.h | 4 +- src/device/usbd.c | 5 +++ src/device/usbd.h | 3 ++ tools/build_all.py | 2 +- 9 files changed, 90 insertions(+), 28 deletions(-) (limited to 'src/device') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index a4674b7a9..a27a2cdbd 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -74,10 +74,10 @@ uint8_t const * tud_descriptor_device_cb(void) //--------------------------------------------------------------------+ enum { - ITF_NUM_CDC1 = 0, - ITF_NUM_CDC_DATA1, - ITF_NUM_CDC2, - ITF_NUM_CDC_DATA2, + ITF_NUM_CDC_0 = 0, + ITF_NUM_CDC_0_DATA, + ITF_NUM_CDC_1, + ITF_NUM_CDC_1_DATA, ITF_NUM_TOTAL }; @@ -86,30 +86,58 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x84 + #define EPNUM_CDC_1_DATA 0x05 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x83 + #define EPNUM_CDC_1_DATA 0x04 #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC2, 4, 0x83, 8, EPNUM_CDC + 2, 0x80 | (EPNUM_CDC + 2), TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 512), + + // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 9a4d71f24..447dc2644 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -114,18 +114,32 @@ enum #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor @@ -133,7 +147,13 @@ uint8_t const desc_configuration[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index a39b34c3c..935731c0b 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -86,10 +86,10 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 5 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 3 #endif @@ -99,7 +99,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC_0, 0x80 | EPNUM_CDC_0, TUD_OPT_HIGH_SPEED ? 512 : 64), // Interface number, string index, EP Out & IN address, EP size TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR, 0x80 | EPNUM_VENDOR, TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/rules.mk b/examples/rules.mk index eeb548d08..dacb81363 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -131,8 +131,14 @@ size: $(BUILD)/$(BOARD)-firmware.elf @$(SIZE) $< -@echo '' +.PHONY: clean clean: - rm -rf $(BUILD) + $(RM) -rf $(BUILD) + +# Print out the value of a make variable. +# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile +print-%: + @echo $* = $($*) # Flash binary using Jlink ifeq ($(OS),Windows_NT) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 4d6e57878..89326f71d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -61,8 +61,8 @@ typedef struct #endif // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; }cdcd_interface_t; @@ -82,9 +82,9 @@ static void _prep_out_transaction (uint8_t itf) // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) ) + if ( max_read >= sizeof(p_cdc->epout_buf) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf)); + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); } } @@ -148,7 +148,7 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) #if 0 // TODO issue with circuitpython's REPL // flush if queue more than endpoint size - if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EPSIZE ) + if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) { tud_cdc_n_write_flush(itf); } @@ -164,7 +164,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) // skip if previous transfer not complete yet TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); + uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected @@ -420,7 +420,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 897fd272b..39ccf6b76 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -34,8 +34,8 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_CDC_EPSIZE -#define CFG_TUD_CDC_EPSIZE 64 +#ifndef CFG_TUD_CDC_EP_BUFSIZE +#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index b607f5939..f59b19427 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -294,6 +294,11 @@ void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ +tusb_speed_t tud_speed_get(void) +{ + return (tusb_speed_t) _usbd_dev.speed; +} + bool tud_mounted(void) { return _usbd_dev.configured; diff --git a/src/device/usbd.h b/src/device/usbd.h index e9b82747a..d9facf719 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -53,6 +53,9 @@ bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD #define tud_int_handler dcd_int_handler +// Get current bus speed +tusb_speed_t tud_speed_get(void); + // Check if device is connected and configured bool tud_mounted(void); diff --git a/tools/build_all.py b/tools/build_all.py index 25cdc9778..af57cdd5c 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -38,7 +38,7 @@ all_boards.sort() def build_example(example, board): subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, + return subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def build_size(example, board): -- cgit v1.3.1 From d0f3d039332cf22637d191cc62bed620c4f14dce Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 17 Jul 2020 08:40:10 +0200 Subject: Intermediate commit. --- src/class/audio/audio.h | 332 ++++++++++++++++++++++++++++++----------- src/class/audio/audio_device.c | 268 ++++++++++++++++++++++++++++++--- src/class/audio/audio_device.h | 21 +++ src/device/usbd.h | 43 +----- src/tusb_option.h | 6 +- 5 files changed, 525 insertions(+), 145 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 022f3118f..f1784a006 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -38,17 +38,22 @@ extern "C" { #endif -/// Isochronous End Point Attributes +/// Audio Device Class Codes + +/// A.2 - Audio Function Subclass Codes typedef enum { - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point -} tusb_iso_ep_attribute_t; + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; -/// Audio Interface Subclass Codes +/// A.3 - Audio Function Protocol Codes +typedef enum +{ + AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_function_protocol_code_t; + +/// A.5 - Audio Interface Subclass Codes typedef enum { AUDIO_SUBCLASS_UNDEFINED = 0x00, @@ -57,23 +62,17 @@ typedef enum AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; -/// Audio Function Subclass Codes -typedef enum -{ - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; - -/// Audio Protocol Codes +/// A.6 - Audio Interface Protocol Codes typedef enum { - AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 - AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 - AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 -} audio_protocol_type_t; + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_interface_protocol_code_t; -/// Audio Function Category Codes +/// A.7 - Audio Function Category Codes typedef enum { + AUDIO_FUNC_UNDEF = 0x00, AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, AUDIO_FUNC_HOME_THEATER = 0x02, AUDIO_FUNC_MICROPHONE = 0x03, @@ -86,9 +85,10 @@ typedef enum AUDIO_FUNC_PRO_AUDIO = 0x0A, AUDIO_FUNC_AUDIO_VIDEO = 0x0B, AUDIO_FUNC_CONTROL_PANEL = 0x0C, -} audio_function_t; + AUDIO_FUNC_OTHER = 0xFF, +} audio_function_code_t; -/// Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 typedef enum { AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, @@ -107,7 +107,7 @@ typedef enum AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, } audio_cs_ac_interface_subtype_t; -/// Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 typedef enum { AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, @@ -117,6 +117,150 @@ typedef enum AUDIO_CS_AS_INTERFACE_DECODER = 0x04, } audio_cs_as_interface_subtype_t; +/// A.11 - Effect Unit Effect Types +typedef enum +{ + AUDIO_EFFECT_TYPE_UNDEF = 0x00, + AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, + AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, + AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, + AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, +} audio_effect_unit_effect_type_t; + +/// A.12 - Processing Unit Process Types +typedef enum +{ + AUDIO_PROCESS_TYPE_UNDEF = 0x00, + AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, + AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, + AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, +} audio_processing_unit_process_type_t; + +/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// A.14 - Audio Class-Specific Request Codes +typedef enum +{ + AUDIO_CS_REQ_UNDEF = 0x00, + AUDIO_CS_REQ_CUR = 0x01, + AUDIO_CS_REQ_RANGE = 0x02, + AUDIO_CS_REQ_MEM = 0x03, +} audio_cs_req_t; + +/// A.17 - Control Selector Codes + +/// A.17.1 - Clock Source Control Selectors +typedef enum +{ + AUDIO_CLK_SRC_CTRL_UNDEF = 0x00, + AUDIO_CLK_SRC_CTRL_SAM_FREQ = 0x01, + AUDIO_CLK_SRC_CTRL_CLK_VALID = 0x02, +} audio_clock_src_control_selector_t; + +/// A.17.7 - Feature Unit Control Selectors +typedef enum +{ + AUDIO_FU_CTRL_UNDEF = 0x00, + AUDIO_FU_CTRL_MUTE = 0x01, + AUDIO_FU_CTRL_VOLUME = 0x02, + AUDIO_FU_CTRL_BASS = 0x03, + AUDIO_FU_CTRL_MID = 0x04, + AUDIO_FU_CTRL_TREBLE = 0x05, + AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO_FU_CTRL_AGC = 0x07, + AUDIO_FU_CTRL_DELAY = 0x08, + AUDIO_FU_CTRL_BASS_BOOST = 0x09, + AUDIO_FU_CTRL_LOUDNESS = 0x0A, + AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, + AUDIO_FU_CTRL_GAIN_PAD = 0x0C, + AUDIO_FU_CTRL_INVERTER = 0x0D, + AUDIO_FU_CTRL_UNDERFLOW = 0x0E, + AUDIO_FU_CTRL_OVERVLOW = 0x0F, + AUDIO_FU_CTRL_LATENCY = 0x10, +} audio_feature_unit_control_selector_t; + +// Rest is yet to be implemented! + +/// Terminal Types + +/// 2.1 - Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// 2.2 - Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// 2.3 - Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Rest is yet to be implemented + +/// Additional Audio Device Class Codes - Source: Audio Data Formats + +/// A.1 - Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), +} audio_data_format_type_I_t; + +/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification + +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + /// Audio Class-Control Values UAC2 typedef enum { @@ -138,13 +282,6 @@ typedef enum AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, } audio_cs_as_interface_control_pos_t; -/// Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_DESCRIPTOR_UNDEFINED = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; - /// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 typedef enum { @@ -198,26 +335,6 @@ typedef enum AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, } audio_clock_multiplier_control_pos_t; -/// Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - /// Audio Class-Input Terminal Controls UAC2 typedef enum { @@ -229,19 +346,6 @@ typedef enum AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, } audio_terminal_input_control_pos_t; -/// Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - /// Audio Class-Output Terminal Controls UAC2 typedef enum { @@ -272,29 +376,6 @@ typedef enum AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, } audio_feature_unit_control_pos_t; -/// Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; - -/// Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = 0x00000000, - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = 0x00000001, - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 0x00000002, - AUDIO_DATA_FORMAT_TYPE_I_ALAW = 0x00000003, - AUDIO_DATA_FORMAT_TYPE_I_MULAW = 0x00000004, -} audio_data_format_type_I_t; - /// Audio Class-Audio Channel Configuration UAC2 typedef enum { @@ -490,6 +571,85 @@ typedef struct TU_ATTR_PACKED uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; +//// 5.2.3 Control Request Parameter Block Layout + +// 5.2.3.1 1-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_1_t; + +// 5.2.3.2 2-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_2_t; + +// 5.2.3.3 4-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_4_t; + +// 5.2.3.1 1-byte Control RANGE Parameter Block +//#define audio_control_range_1_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_1_t; + +// 5.2.3.2 2-byte Control RANGE Parameter Block +//#define audio_control_range_2_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_2_t; + +// 5.2.3.3 4-byte Control RANGE Parameter Block +//#define audio_control_range_4_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_4_t; /** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1c9e0494e..67c94837a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -152,6 +152,9 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID); +static bool audiod_verify_itf_exists(uint8_t itf); +static bool audiod_verify_ep_exists(uint8_t ep); bool tud_audio_n_mounted(uint8_t itf) { @@ -638,7 +641,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed @@ -666,7 +669,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) // Notify caller we read complete descriptor -// (*p_length) += tud_audio_desc_lengths[i]; + // (*p_length) += tud_audio_desc_lengths[i]; // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor @@ -675,8 +678,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - #if CFG_TUD_AUDIO_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); @@ -690,6 +691,7 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * return true; #else + (void) rhport; (void) p_request; return false; #endif @@ -805,21 +807,85 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! TU_VERIFY(p_desc < p_desc_end); - // Conduct audio driver function specific stuff - - // HERE DO WHAT YOU HAVE TO DO - E.G. START ADC OR SO - //#error Implementation specific setInterface code required here! + // Invoke callback + if (tud_audio_set_itf_cb) + { + if (!tud_audio_set_itf_cb(rhport, p_request)) + { + return false; + } + } // Save current alternative interface setting _audiod_itf[idxDriver].altSetting[idxItf] = alt; + tud_control_status(rhport, p_request); + return true; } +// Invoked when class request DATA stage is finished. +// return false to stall control EP (e.g Host send non-sense DATA) bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - (void) p_request; + // Handle audio class specific set requests + if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + if (entityID != 0) + { + // Invoke callback + if (tud_audio_set_req_entity_cb && tud_audio_set_req_entity_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + else + { + // Invoke callback + if (tud_audio_set_req_itf_cb && tud_audio_set_req_itf_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Invoke callback + if (tud_audio_set_req_ep_cb && tud_audio_set_req_ep_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + + break; + + // Unknown/Unsupported recipient + default: TU_BREAKPOINT(); return false; + } + } return true; } @@ -829,17 +895,103 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req { (void) rhport; - switch (p_request->bRequest) + // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + { + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + // Handle class requests + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + if (entityID != 0) + { + TU_VERIFY(audiod_verify_entity_exists(itf, entityID)); + + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + } + } + else + { + TU_VERIFY(audiod_verify_itf_exists(itf)); + + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); + // Verify if EP is present - This check may be omitted if we trust the host not to send rubbish + TU_VERIFY(audiod_verify_ep_exists(ep)); - default: + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + } + + break; + + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // Host expects an answer - in case no callback function is present we stall the request return false; } + + // There went something wrong + TU_BREAKPOINT(); + return false; } bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -936,19 +1088,22 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } +// This helper function finds for a given interface number the index of the attached driver interface, the index of the interface in the audio function +// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and +// finally a pointer to the std. AS interface, where the pointer always points to the start i.e. alternate interface zero. static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (!_audiod_itf[i].p_desc) + if (_audiod_itf[i].p_desc) { // Get pointer at end uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; // Advance past AC descriptors - uint8_t const * p_desc = tu_desc_next(_audiod_itf[i].p_desc); + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; uint8_t tmp = 0; @@ -973,6 +1128,83 @@ static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t return false; } +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + // Look for the correct driver by checking if the unique standard AC interface number fits + if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + + while (p_desc < p_desc_end) + { + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_itf_exists(uint8_t itf) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at beginning and end + uint8_t const *p_desc = _audiod_itf[i].p_desc; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_ep_exists(uint8_t ep) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors - EP we look for are streaming EPs + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO // OLD diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 3e1fa7a92..95b361acd 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -229,6 +229,27 @@ bool tud_audio_fb_done_cb(uint8_t rhport); TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); #endif +// Invoked when audio set interface request received +TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an EP +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an interface +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an entity +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an EP +TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an interface +TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an entity +TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 39ad7639e..fa0be803c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -322,12 +322,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 #define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ #define TUD_AUDIO_DESC_STD_AC_LEN 9 #define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AC Interface Header Descriptor(4.7.2) */ #define TUD_AUDIO_DESC_CS_AC_LEN 9 @@ -360,7 +360,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Standard AS Interface Descriptor(4.9.1) */ #define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 #define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AS Interface Descriptor(4.9.2) */ #define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 @@ -431,43 +431,6 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) -// Length of template descriptor (132 bytes) -//#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) -//#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 -// -// // AUDIO simple descriptor (UAC2) for 1 microphone input -// // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -// #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ -// /* Standard Interface Association Descriptor (IAD) */\ -// 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Standard AC Interface Descriptor(4.7.1) */\ -// 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ -// /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ -// 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ -// /* Clock Source Descriptor(4.7.2.1) */\ -// 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ -// /* Input Terminal Descriptor(4.7.2.4) */\ -// 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ -// /* Output Terminal Descriptor(4.7.2.5) */\ -// 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ -// /* Feature Unit Descriptor(4.7.2.8) */\ -// 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ -// /* Standard AS Interface Descriptor(4.9.1) */\ -// /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ -// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Standard AS Interface Descriptor(4.9.1) */\ -// /* Interface 1, Alternate 1 - alternate interface for data streaming */\ -// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Class-Specific AS Interface Descriptor(4.9.2) */\ -// 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00,\ -// /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ -// 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ -// /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ -// 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ -// /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ -// 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000) - - //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u diff --git a/src/tusb_option.h b/src/tusb_option.h index 0a227483f..cc91b1863 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -163,7 +163,7 @@ // Debug enable to print out error message #ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 0 + #define CFG_TUSB_DEBUG 2 #endif // place data in accessible RAM for usb controller @@ -199,6 +199,10 @@ #define CFG_TUD_HID 0 #endif +#ifndef CFG_TUD_AUDIO + #define CFG_TUD_AUDIO 0 +#endif + #ifndef CFG_TUD_MIDI #define CFG_TUD_MIDI 0 #endif -- cgit v1.3.1 From 5cd654838ba590ab49b637ead744cc0bae671946 Mon Sep 17 00:00:00 2001 From: Chang Feng Date: Sun, 19 Jul 2020 19:13:17 +0800 Subject: Remove 0xEE index string if statement & change TU_ASSERT to TU_VERIFY Signed-off-by: Chang Feng --- src/device/usbd.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index b607f5939..afd46b8ce 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -886,20 +886,11 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user - if ( desc_index == 0xEE ) - { - // The 0xEE index string is a Microsoft OS Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - return false; - } - else - { - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); - TU_ASSERT(desc_str); + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); + TU_VERIFY(desc_str); - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); - } + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); break; case TUSB_DESC_DEVICE_QUALIFIER: -- cgit v1.3.1 From 503c15217edad86426db4792364b88b35ec04d31 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Jul 2020 09:20:45 +0700 Subject: example to call tud_init() after freeRTOS kernel is started add note for usb init when using with RTOS --- examples/device/cdc_msc_freertos/src/main.c | 5 ++++- examples/device/hid_composite_freertos/src/main.c | 5 ++++- src/device/usbd.h | 2 ++ src/host/usbh.h | 3 +++ src/tusb.h | 2 ++ 5 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index a847f4915..1371b84c3 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -83,7 +83,6 @@ void cdc_task(void* params); int main(void) { board_init(); - tusb_init(); // soft timer for blinky blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); @@ -116,6 +115,10 @@ void usb_device_task(void* param) { (void) param; + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + // RTOS forever loop while (1) { diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 8a8570d60..de065ee64 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -79,7 +79,6 @@ void hid_task(void* params); int main(void) { board_init(); - tusb_init(); // soft timer for blinky blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); @@ -112,6 +111,10 @@ void usb_device_task(void* param) { (void) param; + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + // RTOS forever loop while (1) { diff --git a/src/device/usbd.h b/src/device/usbd.h index d9facf719..098e94075 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -42,6 +42,8 @@ //--------------------------------------------------------------------+ // Init device stack +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tud_init (void); // Task function should be called in main/rtos loop diff --git a/src/host/usbh.h b/src/host/usbh.h index 42a2bd095..fe39a19f4 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -91,6 +91,9 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ + +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool usbh_init(void); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); diff --git a/src/tusb.h b/src/tusb.h index defbc54fb..c252a5789 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -109,6 +109,8 @@ * @{ */ // Initialize device/host stack +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tusb_init(void); // Check if stack is initialized -- cgit v1.3.1 From 01903a4a6d0eb8a7260029133cc94a62d969092e Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 27 Jul 2020 21:03:20 +0200 Subject: Implement dynamic reallocation of RX and TX fifos for EP0. Tested with EP0 size 8/16/32/64. --- src/device/dcd.h | 4 + src/device/usbd.c | 17 +++-- src/portable/st/synopsys/dcd_synopsys.c | 126 +++++++++++++++++++------------- 3 files changed, 91 insertions(+), 56 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index a4635346b..ff05f26cc 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -115,6 +115,10 @@ void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; +// Invoked when a set configuration request was received +// Helper to allow for dynamic EP buffer allocation according to configuration descriptor +TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg); + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 20d4925d2..2164eb3f5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -46,7 +46,6 @@ typedef struct { volatile uint8_t connected : 1; volatile uint8_t addressed : 1; - volatile uint8_t configured : 1; volatile uint8_t suspended : 1; uint8_t remote_wakeup_en : 1; // enable/disable by host @@ -54,6 +53,7 @@ typedef struct uint8_t self_powered : 1; // configuration descriptor's attribute }; + volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) @@ -314,7 +314,7 @@ tusb_speed_t tud_speed_get(void) bool tud_mounted(void) { - return _usbd_dev.configured; + return _usbd_dev.cfg_num ? 1 : 0; } bool tud_suspended(void) @@ -583,8 +583,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_GET_CONFIGURATION: { - uint8_t cfgnum = _usbd_dev.configured ? 1 : 0; - tud_control_xfer(rhport, p_request, &cfgnum, 1); + uint8_t cfg_num = _usbd_dev.cfg_num; + tud_control_xfer(rhport, p_request, &cfg_num, 1); } break; @@ -592,9 +592,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { uint8_t const cfg_num = (uint8_t) p_request->wValue; - if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); + if ( !_usbd_dev.cfg_num && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.configured = cfg_num ? 1 : 0; + _usbd_dev.cfg_num = cfg_num; tud_control_status(rhport, p_request); } @@ -746,6 +746,9 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1 TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); + // Allow for dynamic allocation of EP buffer for current configuration - only one configuration may be active according to USB specification + if (dcd_alloc_mem_for_conf) TU_ASSERT(dcd_alloc_mem_for_conf(rhport, desc_cfg)); + // Parse configuration descriptor _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0; @@ -951,7 +954,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) case DCD_EVENT_UNPLUGGED: _usbd_dev.connected = 0; _usbd_dev.addressed = 0; - _usbd_dev.configured = 0; + _usbd_dev.cfg_num = 0; _usbd_dev.suspended = 0; osal_queue_send(_usbd_q, event, in_isr); break; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5bfb6789c..75e6097fd 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -156,7 +156,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); +// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -209,24 +209,24 @@ static void bus_reset(uint8_t rhport) // We rework this here and initialize the FIFOs here only for the USB reset case. The rest is done once a // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. - _allocated_fifo_words = 16 + 2 + 10; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + // Found by trial: 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6 - not quite sure where 1 + 6 comes from but this works for 8/16/32/64 EP0 size + _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + +// _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + usb_otg->DIEPTXF0_HNPTXFSIZ = (CFG_TUD_ENDPOINT0_SIZE/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += 16; - - // Fixed control EP0 size to 64 bytes - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + _allocated_fifo_words += CFG_TUD_ENDPOINT0_SIZE/4; // Set SETUP packet count to 3 out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + //#if TUD_OPT_HIGH_SPEED // _allocated_fifo_words = 271 + 2*EP_MAX; //#else @@ -243,8 +243,8 @@ static void bus_reset(uint8_t rhport) // // TU_LOG2_INT(_allocated_fifo_words); // // // Fixed control EP0 size to 64 bytes -//// in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); -//// xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; +// in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); +// xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; // // // Set SETUP packet count to 3 // out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); @@ -253,7 +253,7 @@ static void bus_reset(uint8_t rhport) } // Required after new configuration received in case EP0 max packet size has changed -static bool set_EP0_max_pkt_size(uint8_t maxPktSize) +static void set_EP0_max_pkt_size() { USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -264,51 +264,34 @@ static bool set_EP0_max_pkt_size(uint8_t maxPktSize) switch (enum_spd) { case 0x00: // High speed - always 64 byte - if (maxPktSize == 64) - { - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - return true; - } - - return false; // Only 64 bytes are valid + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + break; case 0x03: // Full speed - switch (maxPktSize) - { - case 8: - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; - break; - - case 16: - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; - break; - - case 32: - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; - break; - - case 64: - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - break; - - default: - return false; // Other sizes are not valid - } - - return true; +#if CFG_TUD_ENDPOINT0_SIZE == 64 + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; +#elif CFG_TUD_ENDPOINT0_SIZE == 32 + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; +#elif CFG_TUD_ENDPOINT0_SIZE == 16 + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; +#elif CFG_TUD_ENDPOINT0_SIZE == 8 + in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; +#else +# error CFG_TUD_ENDPOINT0_SIZE MUST be 8, 16, 32, or 64! +#endif + break; default: // Low speed - always 8 bytes in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = 8; xfer_status[0][TUSB_DIR_IN].max_size = 8; - return true; } } @@ -1022,6 +1005,8 @@ void dcd_int_handler(uint8_t rhport) set_turnaround(usb_otg, speed); + set_EP0_max_pkt_size(); + dcd_event_bus_reset(rhport, speed, true); } @@ -1086,4 +1071,47 @@ void dcd_int_handler(uint8_t rhport) } } +TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg) +{ + (void) rhport; + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + +// for(uint8_t n = 0; n < EP_MAX; n++) { +// out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; +// } + + out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; + + // Deactivate Interrupts? + dev->DAINTMSK &= ~((1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos)); + dev->DOEPMSK &= ~(USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM); + dev->DIEPMSK &= ~(USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM); + + // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); + + // Reconfigure RX buffer and EP0 TX buffer + _allocated_fifo_words = 47 + 2*EP_MAX; + + usb_otg->GRXFSIZ = _allocated_fifo_words; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + + _allocated_fifo_words += 16; + +// usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + + // Enable interrupts + dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; + dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; + + // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + + return true; +} + #endif -- cgit v1.3.1 From acde49ccc97466f603dc7face7ab70ea10d38ee3 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 1 Aug 2020 20:14:58 +0700 Subject: enable pull-up in dcd_init() instead of usbd --- docs/porting.md | 2 +- src/device/usbd.c | 1 - src/portable/dialog/da146xx/dcd_da146xx.c | 4 ++-- src/portable/espressif/esp32s2/dcd_esp32s2.c | 4 ++-- src/portable/microchip/samg/dcd_samg.c | 3 +-- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 ++ src/portable/nxp/transdimension/dcd_transdimension.c | 3 ++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- src/portable/st/synopsys/dcd_synopsys.c | 2 ++ src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 3 +++ test/test/device/msc/test_msc_device.c | 1 - test/test/device/usbd/test_usbd.c | 1 - 12 files changed, 17 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/docs/porting.md b/docs/porting.md index 473768450..d3c688a81 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -62,7 +62,7 @@ All of the code for the low-level device API is in `src/portable//USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; tusb_vbus_changed((CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0); + + dcd_connect(rhport); } void dcd_int_enable(uint8_t rhport) diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 755e06701..58d92e728 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -165,8 +165,6 @@ static void enum_done_processing(void) *------------------------------------------------------------------*/ void dcd_init(uint8_t rhport) { - (void)rhport; - ESP_LOGV(TAG, "DCD init - Start"); // A. Disconnect @@ -204,6 +202,8 @@ void dcd_init(uint8_t rhport) USB_ENUMDONEMSK_M | USB_RESETDETMSK_M | USB_DISCONNINTMSK_M; // host most only + + dcd_connect(rhport); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 4a8ed53f3..2b64df50b 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -154,9 +154,8 @@ static void bus_reset(void) // Initialize controller to device mode void dcd_init (uint8_t rhport) { - (void) rhport; - tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); + dcd_connect(rhport); } // Enable device interrupt diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index f7a59a808..39c5e6638 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -181,6 +181,8 @@ void dcd_init(uint8_t rhport) LPC_USB->UDCAH = (uint32_t) _dcd.udca; LPC_USB->DMAIntEn = (DMA_INT_END_OF_XFER_MASK /*| DMA_INT_NEW_DD_REQUEST_MASK*/ | DMA_INT_ERROR_MASK); + dcd_connect(rhport); + // Clear pending IRQ NVIC_ClearPendingIRQ(USB_IRQn); } diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 46751cf5d..755e7635e 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -345,7 +345,8 @@ void dcd_init(uint8_t rhport) dcd_reg->USBSTS = dcd_reg->USBSTS; dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_RESET | INTR_SUSPEND /*| INTR_SOF*/; - dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 + dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 + dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect } void dcd_int_enable(uint8_t rhport) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index da184abe7..32179874e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -205,7 +205,6 @@ static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { void dcd_init (uint8_t rhport) { - (void)rhport; /* Clocks should already be enabled */ /* Use __HAL_RCC_USB_CLK_ENABLE(); to enable the clocks before calling this function */ @@ -244,7 +243,8 @@ void dcd_init (uint8_t rhport) USB->CNTR |= USB_CNTR_RESETM | (USE_SOF ? USB_CNTR_SOFM : 0) | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); - // Data-line pull-up is left disconnected. + // Enable pull-up if supported + if ( dcd_connect ) dcd_connect(rhport); } // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index f4430f582..a284c0384 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -453,6 +453,8 @@ void dcd_init (uint8_t rhport) // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + + dcd_connect(rhport); } void dcd_int_enable (uint8_t rhport) diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 8672050f0..b6951efef 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -134,6 +134,9 @@ void dcd_init (uint8_t rhport) // Enable reset and wait for it before continuing. USBIE |= RSTRIE; + // Enable pullup. + USBCNF |= PUR_EN; + USBKEYPID = 0; } diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 0382fb327..a01ef153a 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -199,7 +199,6 @@ void setUp(void) if ( !tusb_inited() ) { dcd_init_Expect(rhport); - dcd_connect_Expect(rhport); tusb_init(); } diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index 1bb32c1e5..06372b2e4 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -127,7 +127,6 @@ void setUp(void) { mscd_init_Expect(); dcd_init_Expect(rhport); - dcd_connect_Expect(rhport); tusb_init(); } } -- cgit v1.3.1 From 01b9b77d3b94ed83931d6a51c1b357f03f188e76 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Aug 2020 14:47:32 +0700 Subject: allow application driver to overwrite built-in one - position application driver before built-in - remove dcd.h from public include. --- src/class/msc/msc_device.c | 1 + src/class/usbtmc/usbtmc_device.c | 1 - src/device/usbd.c | 47 +++++++++++++++++++++++----------------- src/device/usbd.h | 16 +++----------- 4 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src/device') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9b79b68a7..f3f2e536e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -31,6 +31,7 @@ #include "common/tusb_common.h" #include "msc_device.h" #include "device/usbd_pvt.h" +#include "device/dcd.h" // for faking dcd_event_xfer_complete //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index a3ff76079..bc5f23f42 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -80,7 +80,6 @@ #include #include "usbtmc.h" #include "usbtmc_device.h" -#include "device/dcd.h" #include "device/usbd.h" #include "osal/osal.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 7fc7189a5..6b91048b6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -203,30 +203,30 @@ static usbd_class_driver_t const _usbd_driver[] = #endif }; -enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; +enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; // Additional class drivers implemented by application static usbd_class_driver_t const * _app_driver = NULL; static uint8_t _app_driver_count = 0; -// virtually joins built-in and application drivers together -// All drivers = built-in + application +// virtually joins built-in and application drivers together. +// Application is positioned first to allow overwriting built-in ones. static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { - // Built-in drivers - if (drvid < USBD_CLASS_DRIVER_COUNT) return &_usbd_driver[drvid]; - - // App drivers + // Application drivers if ( usbd_app_driver_get_cb ) { - drvid -= USBD_CLASS_DRIVER_COUNT; if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + drvid -= _app_driver_count; } + // Built-in drivers + if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; + return NULL; } -#define TOTAL_DRIVER_COUNT (USBD_CLASS_DRIVER_COUNT+_app_driver_count) +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) //--------------------------------------------------------------------+ // DCD Event @@ -245,6 +245,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); +// from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); @@ -252,7 +253,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, //--------------------------------------------------------------------+ -// Debugging +// Debug //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 static char const* const _usbd_event_str[DCD_EVENT_COUNT] = @@ -327,6 +328,20 @@ bool tud_remote_wakeup(void) return true; } +bool tud_disconnect(void) +{ + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; +} + +bool tud_connect(void) +{ + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; +} + //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ @@ -593,7 +608,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const cfg_num = (uint8_t) p_request->wValue; if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.configured = cfg_num ? 1 : 0; tud_control_status(rhport, p_request); @@ -688,18 +702,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_CLEAR_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_clear_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_clear_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; case TUSB_REQ_SET_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; @@ -773,7 +781,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = get_driver(drv_id); - uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); if ( drv_len > 0 ) diff --git a/src/device/usbd.h b/src/device/usbd.h index 098e94075..5338be157 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -35,7 +35,6 @@ #endif #include "common/tusb_common.h" -#include "dcd.h" //--------------------------------------------------------------------+ // Application API @@ -53,6 +52,7 @@ void tud_task (void); bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD +extern void dcd_int_handler(uint8_t rhport); #define tud_int_handler dcd_int_handler // Get current bus speed @@ -75,21 +75,11 @@ bool tud_remote_wakeup(void); // Enable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_disconnect(void) -{ - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; -} +bool tud_disconnect(void); // Disable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_connect(void) -{ - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; -} +bool tud_connect(void); // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only -- cgit v1.3.1 From a9d362185b5985062ce3f1a618a67938d9c9d5f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Aug 2020 15:06:19 +0700 Subject: update note for app driver list mustbe accesible at all time. --- src/device/usbd_pvt.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/device') diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index e430a81d9..a5d223329 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -54,6 +54,7 @@ typedef struct // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. +// Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; //--------------------------------------------------------------------+ -- cgit v1.3.1 From 1d83ad0ebb6c263736b0dadec80c9406563a5199 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 13:12:09 +0700 Subject: rename tuh_isr/hcd_isr to tuh_int_handler/hcd_int_handler --- hw/bsp/ea4088qs/ea4088qs.c | 2 +- hw/bsp/ea4357/ea4357.c | 4 ++-- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/mbed1768/mbed1768.c | 2 +- hw/bsp/mcb1800/mcb1800.c | 4 ++-- hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c | 2 +- hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c | 2 +- hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c | 2 +- hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c | 4 ++-- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 4 ++-- hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c | 4 ++-- hw/bsp/ngx4330/ngx4330.c | 4 ++-- hw/bsp/teensy_40/teensy40.c | 4 ++-- src/device/dcd.h | 6 +++--- src/host/ehci/ehci.c | 2 +- src/host/hcd.h | 9 +++------ src/host/ohci/ohci.c | 2 +- src/host/usbh.h | 3 ++- 18 files changed, 30 insertions(+), 32 deletions(-) (limited to 'src/device') diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 00db1a299..df76bb92a 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -33,7 +33,7 @@ void USB_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index f41ba5ab9..69d2c3cc1 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -246,7 +246,7 @@ void board_init(void) void USB0_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -257,7 +257,7 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 5ec4fac23..0d5e98e9e 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -33,7 +33,7 @@ void USB_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index 0dfd05c81..17004cfe0 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -147,7 +147,7 @@ void board_init(void) void USB_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index b57385985..a17ac5c3b 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -33,7 +33,7 @@ void USB0_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -44,7 +44,7 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c index c682ace8d..1c4b1798c 100644 --- a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c +++ b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c @@ -121,7 +121,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c index 214077a4a..2b1f3cc80 100644 --- a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c +++ b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c @@ -121,7 +121,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c index f32ec5401..273f3a0c9 100644 --- a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c +++ b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c @@ -120,7 +120,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c index be0ae3ea8..1042bcfe7 100644 --- a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c +++ b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c @@ -124,7 +124,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -135,7 +135,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index be0ae3ea8..1042bcfe7 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -124,7 +124,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -135,7 +135,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c index be0ae3ea8..1042bcfe7 100644 --- a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c +++ b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c @@ -124,7 +124,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -135,7 +135,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index b1908fc38..dda3bc092 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -231,7 +231,7 @@ void board_init(void) void USB0_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -242,7 +242,7 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index f45a98ef3..30fdedd27 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -125,7 +125,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -136,7 +136,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/src/device/dcd.h b/src/device/dcd.h index a4635346b..776f782b8 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -87,9 +87,9 @@ typedef struct TU_ATTR_ALIGNED(4) //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); -/*------------------------------------------------------------------*/ -/* Device API - *------------------------------------------------------------------*/ +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ // Initialize controller to device mode void dcd_init (uint8_t rhport); diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index e2ead7b08..295da4566 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -648,7 +648,7 @@ static void xfer_error_isr(uint8_t hostid) } //------------- Host Controller Driver's Interrupt Handler -------------// -void hcd_isr(uint8_t rhport) +void hcd_int_handler(uint8_t rhport) { ehci_registers_t* regs = ehci_data.regs; diff --git a/src/host/hcd.h b/src/host/hcd.h index f2ca0a1d6..24cc62501 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -84,10 +84,10 @@ enum { #endif //--------------------------------------------------------------------+ -// HCD API +// Controller & Port API //--------------------------------------------------------------------+ bool hcd_init(void); -void hcd_isr(uint8_t hostid); +void hcd_int_handler(uint8_t rhport); void hcd_int_enable (uint8_t rhport); void hcd_int_disable(uint8_t rhport); @@ -100,7 +100,6 @@ static inline uint32_t hcd_frame_number(uint8_t rhport) return hcd_uframe_number(rhport) >> 3; } -// PORT API /// return the current connect status of roothub port bool hcd_port_connect_status(uint8_t hostid); void hcd_port_reset(uint8_t hostid); @@ -144,9 +143,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -#if 0 -tusb_error_t hcd_pipe_cancel(); -#endif +// tusb_error_t hcd_pipe_cancel(); #ifdef __cplusplus } diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 5ee5fe8c4..114f52e7d 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -606,7 +606,7 @@ static void done_queue_isr(uint8_t hostid) } } -void hcd_isr(uint8_t hostid) +void hcd_int_handler(uint8_t hostid) { uint32_t const int_en = OHCI_REG->interrupt_enable; uint32_t const int_status = OHCI_REG->interrupt_status & int_en; diff --git a/src/host/usbh.h b/src/host/usbh.h index 39e7a4e0d..27193d378 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -73,7 +73,8 @@ typedef struct { void tuh_task(void); // Interrupt handler, name alias to HCD -#define tuh_isr hcd_isr +extern void hcd_int_handler(uint8_t rhport); +#define tuh_int_handler hcd_int_handler tusb_device_state_t tuh_device_get_state (uint8_t dev_addr); static inline bool tuh_device_is_configured(uint8_t dev_addr) -- cgit v1.3.1 From 4d57b4ea336d0ba89b97b388aa02f15c2d947a2a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 13:57:07 +0700 Subject: clean up --- src/device/usbd.h | 2 -- src/host/usbh.c | 12 ++++-------- src/host/usbh.h | 9 +++++---- src/tusb.c | 2 +- tools/build_esp32s.py | 16 ++++++++++------ 5 files changed, 20 insertions(+), 21 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index 5338be157..bbdd1be99 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -41,8 +41,6 @@ //--------------------------------------------------------------------+ // Init device stack -// Note: when using with RTOS, this should be called after scheduler/kernel is started. -// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tud_init (void); // Task function should be called in main/rtos loop diff --git a/src/host/usbh.c b/src/host/usbh.c index 58550c93b..b6df6bad8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -116,7 +116,7 @@ enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // Event queue -// role device/host is used by OS NONE for mutex (disable usb isr) only +// role device/host is used by OS NONE for mutex (disable usb isr) OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; @@ -137,7 +137,6 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) return (tusb_device_state_t) _usbh_devices[dev_addr].state; } - static inline void osal_task_delay(uint32_t msec) { (void) msec; @@ -149,7 +148,7 @@ static inline void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ -bool usbh_init(void) +bool tuh_init(void) { tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); @@ -385,13 +384,10 @@ bool enum_task(hcd_event_t* event) #endif }; - // for OSAL_NONE local variable won't retain value after blocking service sem_wait/queue_recv - static uint8_t configure_selected = 1; // TODO move - usbh_device_t* dev0 = &_usbh_devices[0]; tusb_control_request_t request; - dev0->rhport = event->rhport; // TODO refractor integrate to device_pool + dev0->rhport = event->rhport; // TODO refractor integrate to device_pool dev0->hub_addr = event->attach.hub_addr; dev0->hub_port = event->attach.hub_port; dev0->state = TUSB_DEVICE_STATE_UNPLUG; @@ -552,7 +548,7 @@ bool enum_task(hcd_event_t* event) new_dev->product_id = ((tusb_desc_device_t*) _usbh_ctrl_buf)->idProduct; new_dev->configure_count = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bNumConfigurations; - configure_selected = get_configure_number_for_device((tusb_desc_device_t*) _usbh_ctrl_buf); + uint8_t const configure_selected = get_configure_number_for_device((tusb_desc_device_t*) _usbh_ctrl_buf); TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// diff --git a/src/host/usbh.h b/src/host/usbh.h index 27193d378..1930dc20b 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -70,6 +70,11 @@ typedef struct { //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ + +// Init host stack +bool tuh_init(void); + +// Task function should be called in main/rtos loop void tuh_task(void); // Interrupt handler, name alias to HCD @@ -97,11 +102,7 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ -// Note: when using with RTOS, this should be called after scheduler/kernel is started. -// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. -bool usbh_init(void); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); - bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); #ifdef __cplusplus diff --git a/src/tusb.c b/src/tusb.c index 1bc134dba..ae1bc47e3 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -43,7 +43,7 @@ bool tusb_init(void) if (_initialized) return true; #if TUSB_OPT_HOST_ENABLED - TU_ASSERT( usbh_init() ); // init host stack + TU_ASSERT( tuh_init() ); // init host stack #endif #if TUSB_OPT_DEVICE_ENABLED diff --git a/tools/build_esp32s.py b/tools/build_esp32s.py index 9600b6145..44364806b 100644 --- a/tools/build_esp32s.py +++ b/tools/build_esp32s.py @@ -4,6 +4,10 @@ import sys import subprocess import time +SUCCEEDED = "\033[32msucceeded\033[0m" +FAILED = "\033[31mfailed\033[0m" +SKIPPED = "\033[33mskipped\033[0m" + success_count = 0 fail_count = 0 skip_count = 0 @@ -11,7 +15,7 @@ exit_status = 0 total_time = time.monotonic() -build_format = '| {:23} | {:30} | {:9} | {:7} | {:6} | {:6} |' +build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' build_separator = '-' * 100 # 1st Argument is Example, build all examples if not existed @@ -58,7 +62,7 @@ def skip_example(example, board): return 0 print(build_separator) -print(build_format.format('Example', 'Board', 'Result', 'Time', 'Flash', 'SRAM')) +print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) print(build_separator) for example in all_examples: @@ -70,19 +74,19 @@ for example in all_examples: # Check if board is skipped if skip_example(example, board): - success = "\033[33mskipped\033[0m " + success = SKIPPED skip_count += 1 print(build_format.format(example, board, success, '-', flash_size, sram_size)) else: build_result = build_example(example, board) if build_result.returncode == 0: - success = "\033[32msucceeded\033[0m" + success = SUCCEEDED success_count += 1 (flash_size, sram_size) = build_size(example, board) else: exit_status = build_result.returncode - success = "\033[31mfailed\033[0m " + success = FAILED fail_count += 1 build_duration = time.monotonic() - start_time @@ -95,7 +99,7 @@ for example in all_examples: total_time = time.monotonic() - total_time print(build_separator) -print("Build Sumamary: {} \033[32msucceeded\033[0m, {} \033[31mfailed\033[0m, {} \033[33mskipped\033[0m and took {:.2f}s".format(success_count, fail_count, skip_count, total_time)) +print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) print(build_separator) sys.exit(exit_status) -- cgit v1.3.1 From b8b95e84944b4c07cc9c9f4a7e4d53e6256b42f0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 15:45:03 +0700 Subject: add in_isr to all hcd event functions --- src/device/dcd.h | 2 +- src/host/ehci/ehci.c | 8 ++++---- src/host/hcd.h | 30 ++++++++++++++++-------------- src/host/hub.c | 2 +- src/host/ohci/ohci.c | 6 +++--- src/host/usbh.c | 14 +++++++------- 6 files changed, 32 insertions(+), 30 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 776f782b8..a5c485f9e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -140,7 +140,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ -// Event API (Implemented by device stack) +// Event API (implemented by stack) //--------------------------------------------------------------------+ // Called by DCD to notify device stack diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 295da4566..c2d5ebf7b 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -489,10 +489,10 @@ static void port_connect_status_change_isr(uint8_t hostid) if (ehci_data.regs->portsc_bm.current_connect_status) { hcd_port_reset(hostid); - hcd_event_device_attach(hostid); + hcd_event_device_attach(hostid, true); }else // device unplugged { - hcd_event_device_remove(hostid); + hcd_event_device_remove(hostid, true); } } @@ -512,7 +512,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) { // end of request // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); p_qhd->total_xferred_bytes = 0; } } @@ -599,7 +599,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, error_event, true); p_qhd->total_xferred_bytes = 0; } diff --git a/src/host/hcd.h b/src/host/hcd.h index da530421d..eebf2c801 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -109,20 +109,6 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid); // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr); -//--------------------------------------------------------------------+ -// Event function -//--------------------------------------------------------------------+ -void hcd_event_handler(hcd_event_t const* event, bool in_isr); - -// Helper to send device attach event -void hcd_event_device_attach(uint8_t rhport); - -// Helper to send device removal event -void hcd_event_device_remove(uint8_t rhport); - -// Helper to send USB transfer event -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - //--------------------------------------------------------------------+ // Endpoints API //--------------------------------------------------------------------+ @@ -145,6 +131,22 @@ bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t // tusb_error_t hcd_pipe_cancel(); +//--------------------------------------------------------------------+ +// Event API (implemented by stack) +//--------------------------------------------------------------------+ + +// Called by HCD to notify stack +extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); + +// Helper to send device attach event +extern void hcd_event_device_attach(uint8_t rhport, bool in_isr); + +// Helper to send device removal event +extern void hcd_event_device_remove(uint8_t rhport, bool in_isr); + +// Helper to send USB transfer event +extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr); + #ifdef __cplusplus } #endif diff --git a/src/host/hub.c b/src/host/hub.c index 4fb28b72f..f88056c92 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -223,7 +223,7 @@ void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_ event.attach.hub_port = port; hcd_event_handler(&event, true); - break; // handle one port at a time, next port if any will be handled in the next cycle + break; // TODO handle one port at a time, next port if any will be handled in the next cycle } } // NOTE: next status transfer is queued by usbh.c after handling this request diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 114f52e7d..87da374d5 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -599,7 +599,7 @@ static void done_queue_isr(uint8_t hostid) hcd_event_xfer_complete(p_ed->dev_addr, tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), - event, xferred_bytes); + xferred_bytes, event, true); } td_head = (ohci_td_item_t*) td_head->next; @@ -632,10 +632,10 @@ void hcd_int_handler(uint8_t hostid) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; - hcd_event_device_attach(0); + hcd_event_device_attach(hostid, true); }else { - hcd_event_device_remove(0); + hcd_event_device_remove(hostid, true); } } diff --git a/src/host/usbh.c b/src/host/usbh.c index da163f9e4..6304b6b48 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -268,7 +268,7 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr) } // interrupt caused by a TD (with IOC=1) in pipe of class class_code -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, uint32_t xferred_bytes) +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { usbh_device_t* dev = &_usbh_devices[ dev_addr ]; @@ -276,7 +276,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, { dev->control.pipe_status = result; // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary - osal_semaphore_post( dev->control.sem_hdl, true ); + osal_semaphore_post( dev->control.sem_hdl, true ); // FIXME post within ISR } else { @@ -293,11 +293,11 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, } }; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } } -void hcd_event_device_attach(uint8_t rhport) +void hcd_event_device_attach(uint8_t rhport, bool in_isr) { hcd_event_t event = { @@ -308,10 +308,10 @@ void hcd_event_device_attach(uint8_t rhport) event.attach.hub_addr = 0; event.attach.hub_port = 0; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } -void hcd_event_device_remove(uint8_t hostid) +void hcd_event_device_remove(uint8_t hostid, bool in_isr) { hcd_event_t event = { @@ -322,7 +322,7 @@ void hcd_event_device_remove(uint8_t hostid) event.attach.hub_addr = 0; event.attach.hub_port = 0; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } -- cgit v1.3.1 From 8b9893cadab88fa4abd17d5b9856e0d08ef03796 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 15:48:11 +0700 Subject: introduce optional usbd_edpt_claim, usbd_edpt_release which can be used to gain exclusive access to usbd_edpt_xfer --- src/class/cdc/cdc_device.c | 38 ++++++++++++++++--------- src/device/usbd.c | 71 +++++++++++++++++++++++++++++++++++++++++++++- src/device/usbd_pvt.h | 6 ++++ 3 files changed, 101 insertions(+), 14 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b4ebfc92e..cd8904042 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -77,8 +77,8 @@ static void _prep_out_transaction (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return; + // claim endpoint + TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); @@ -161,17 +161,29 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // skip if previous transfer not complete yet - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); + // No data to send + if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; - uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - if ( count ) + uint8_t const rhport = TUD_OPT_RHPORT; + + // claim the endpoint first + TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + + // we can be blocked by another write()/write_flush() from other thread. + // causing us to attempt to transfer on an busy endpoint. + uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); + + if ( count && tud_cdc_n_connected(itf) ) { - TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + // Note: data is dropped if terminal is not connected + usbd_edpt_release(rhport, p_cdc->ep_in); + return 0; } - - return count; } uint32_t tud_cdc_n_write_available (uint8_t itf) @@ -194,7 +206,7 @@ void cdcd_init(void) p_cdc->wanted_char = -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 - p_cdc->line_coding.bit_rate = 115200; + p_cdc->line_coding.bit_rate = 115200; p_cdc->line_coding.stop_bits = 0; p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; @@ -421,10 +433,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( 0 == tud_cdc_n_write_flush(itf) ) { - // There is no data left, a ZLP should be sent if + // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) + if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 6b91048b6..25d3748e1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -63,9 +63,11 @@ typedef struct { volatile bool busy : 1; volatile bool stalled : 1; + volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[8][2]; + }usbd_device_t; static usbd_device_t _usbd_dev; @@ -237,6 +239,13 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); static osal_queue_t _usbd_q; +// Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE +static osal_mutex_def_t _ubsd_mutexdef; +static osal_mutex_t _usbd_mutex; +#endif + + //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ @@ -351,9 +360,15 @@ bool tud_init (void) tu_varclr(&_usbd_dev); +#if CFG_TUSB_OS != OPT_OS_NONE + // Init device mutex + _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); + TU_ASSERT(_usbd_mutex); +#endif + // Init device queue & task _usbd_q = osal_queue_create(&_usbd_qdef); - TU_ASSERT(_usbd_q != NULL); + TU_ASSERT(_usbd_q); // Get application driver if available if ( usbd_app_driver_get_cb ) @@ -478,6 +493,7 @@ void tud_task (void) TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; + _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; if ( 0 == epnum ) { @@ -1076,6 +1092,56 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) return dcd_edpt_open(rhport, desc_ep); } +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -1083,6 +1149,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + // Attempt to transfer on busy or not claimed (skip now) endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0 /*&& _usbd_dev.ep_status[epnum][dir].claimed == 1*/); + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a5d223329..5fa9a72a5 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,6 +70,12 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Claim an endpoint before submitting a transfer +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); + +// Release an endpoint without submitting a transfer +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 33f0a18523accfcdebf186f33271dd92f8681b56 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:25:31 +0700 Subject: update cdc edpt read --- src/class/cdc/cdc_device.c | 12 +++++------- src/device/usbd.c | 2 ++ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index cd8904042..317355ed7 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -77,15 +77,13 @@ static void _prep_out_transaction (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + // Prepare for incoming data but only allow what we can store in the ring buffer. + uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); + TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); + // claim endpoint TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= sizeof(p_cdc->epout_buf) ) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); - } + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); } //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 25d3748e1..5a7d72124 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1162,7 +1162,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; }else { + // DCD error, mark endpoint as ready to allow next transfer _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = 0; TU_LOG2("failed\r\n"); TU_BREAKPOINT(); return false; -- cgit v1.3.1 From 801f8b5b38b90cb3e15d0a1bb2accae58cde6130 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Sep 2020 23:32:08 +0700 Subject: update claim edpt for hid and midi --- src/class/cdc/cdc_device.c | 41 +++++++++++++++++++++++------------------ src/class/hid/hid_device.c | 13 ++++++++----- src/class/midi/midi_device.c | 27 +++++++++++++++++++++------ src/device/usbd_pvt.h | 3 ++- 4 files changed, 54 insertions(+), 30 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 0792e745d..6c1bf6bb2 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -73,17 +73,17 @@ typedef struct //--------------------------------------------------------------------+ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; -static void _prep_out_transaction (uint8_t itf) +static void _prep_out_transaction (cdcd_interface_t* p_cdc) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); - // claim endpoint - TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + // claim endpoint and submit transfer + if ( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out) ) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + } } //--------------------------------------------------------------------+ @@ -121,8 +121,9 @@ uint32_t tud_cdc_n_available(uint8_t itf) uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { - uint32_t num_read = tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize); - _prep_out_transaction(itf); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize); + _prep_out_transaction(p_cdc); return num_read; } @@ -133,8 +134,9 @@ bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr) void tud_cdc_n_read_flush (uint8_t itf) { - tu_fifo_clear(&_cdcd_itf[itf].rx_ff); - _prep_out_transaction(itf); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + tu_fifo_clear(&p_cdc->rx_ff); + _prep_out_transaction(p_cdc); } //--------------------------------------------------------------------+ @@ -142,11 +144,12 @@ void tud_cdc_n_read_flush (uint8_t itf) //--------------------------------------------------------------------+ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) { - uint16_t ret = tu_fifo_write_n(&_cdcd_itf[itf].tx_ff, buffer, bufsize); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); #if 0 // TODO issue with circuitpython's REPL // flush if queue more than endpoint size - if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) + if ( tu_fifo_count(&p_cdc->tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) { tud_cdc_n_write_flush(itf); } @@ -164,7 +167,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint8_t const rhport = TUD_OPT_RHPORT; - // Claim the endpoint first + // Claim the endpoint TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); // Pull data from FIFO @@ -242,8 +245,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Find available interface cdcd_interface_t * p_cdc = NULL; - uint8_t cdc_id; - for(cdc_id=0; cdc_idrx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction - _prep_out_transaction(itf); + _prep_out_transaction(p_cdc); } // Data sent to host, we continue to fetch from tx fifo to send. @@ -435,7 +437,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { - usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) + { + usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + } } } } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index c46fc591a..10267d734 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -72,18 +72,21 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ bool tud_hid_ready(void) { - uint8_t itf = 0; + uint8_t const itf = 0; uint8_t const ep_in = _hidd_itf[itf].ep_in; - return tud_ready() && (ep_in != 0) && usbd_edpt_ready(TUD_OPT_RHPORT, ep_in); + return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) { - TU_VERIFY( tud_hid_ready() ); - - uint8_t itf = 0; + uint8_t const rhport = 0; + uint8_t const itf = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; + // claim endpoint + TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); + + // prepare data if (report_id) { len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 376b3670a..00b1bde92 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -153,15 +153,25 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu static uint32_t write_flush(midid_interface_t* midi) { + // No data to send + if ( !tu_fifo_count(&midi->tx_ff) ) return 0; + + uint8_t const rhport = TUD_OPT_RHPORT; + // skip if previous transfer not complete - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); + TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); if (count > 0) { - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) ); + TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, midi->ep_in); + return 0; } - return count; } uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) @@ -405,17 +415,22 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 if (tud_midi_rx_cb) tud_midi_rx_cb(itf); // prepare for next + // TODO for now ep_out is not used by public API therefore there is no race condition, + // and does not need to claim like ep_in TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false); } else if ( ep_addr == p_midi->ep_in ) { if (0 == write_flush(p_midi)) { - // There is no data left, a ZLP should be sent if + // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) + if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) + { + usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + } } } } diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 5fa9a72a5..09b285581 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,7 +70,8 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Claim an endpoint before submitting a transfer +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); // Release an endpoint without submitting a transfer -- cgit v1.3.1 From ce4a9b9c3ad15a8a714959c89c7a39ba67970cfd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Sep 2020 00:14:07 +0700 Subject: clean up --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 5a7d72124..8fc0092eb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1149,8 +1149,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - // Attempt to transfer on busy or not claimed (skip now) endpoint, sound like an race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0 /*&& _usbd_dev.ep_status[epnum][dir].claimed == 1*/); + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy -- cgit v1.3.1 From 23e6ee2ea2e69f09b43c9f7736b95560a6e9ef7b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Sep 2020 22:14:31 +0700 Subject: cdc device: claim endpoint before checking fifo availability - add pre-check to reduce mutex lock in usbd_edpt_claim --- src/class/cdc/cdc_device.c | 23 ++++++++++++++++++----- src/device/usbd.c | 5 ++++- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6c1bf6bb2..e39adc5fa 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -75,14 +75,27 @@ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static void _prep_out_transaction (cdcd_interface_t* p_cdc) { + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); + // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); - TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); + // TODO Actually we can still carry out the transfer, keeping count of received bytes + // and slowly move it to the FIFO when read(). + // This pre-check reduces endpoint claiming + TU_VERIFY(available >= sizeof(p_cdc->epout_buf), ); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out), ); - // claim endpoint and submit transfer - if ( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out) ) + // fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&p_cdc->rx_ff); + + if ( available >= sizeof(p_cdc->epout_buf) ) { + usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + }else { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, p_cdc->ep_out); } } diff --git a/src/device/usbd.c b/src/device/usbd.c index 8fc0092eb..dfe30578e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1100,11 +1100,14 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); #if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); #endif // can only claim the endpoint if it is not busy and not claimed yet. - bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); + bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); if (ret) { _usbd_dev.ep_status[epnum][dir].claimed = 1; -- cgit v1.3.1 From 9c0d15fc43818282b6a92432e675dd214e51735e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Sep 2020 22:23:59 +0700 Subject: more const --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index dfe30578e..d1e984a0e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1132,7 +1132,7 @@ bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) #endif // can only release the endpoint if it is claimed and not busy - bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); + bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); if (ret) { _usbd_dev.ep_status[epnum][dir].claimed = 0; -- cgit v1.3.1 From 2ace98e943831784e6c9d81258babce2b7b3221c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 11:28:05 +0200 Subject: audio_device: Update explicit feedback support Feedback can be specified by the user code and will be sent at feedback endpoint specified interval. --- src/class/audio/audio_device.c | 76 ++++++++++++++++++++++++++++++++---------- src/class/audio/audio_device.h | 5 +++ src/device/usbd.h | 5 +++ 3 files changed, 68 insertions(+), 18 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 181703f75..1b9cfe13a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -121,10 +121,9 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_OUT CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - // TODO: required? - //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! - //#endif +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#endif #endif @@ -643,18 +642,51 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) { - (void) rhport; - (void) audio; + uint8_t fb[4]; + uint16_t len; - // Here we need to return the feedback value -#error RETURN YOUR FEEDBACK VALUE HERE! + if (audio->fb_val == 0) + { + len = 0; + return true; + } + else + { + len = 4; + // Here we need to return the feedback value + if (rhport == 0) + { + // For FS format is 10.14 + fb[0] = (audio->fb_val >> 2) & 0xFF; + fb[1] = (audio->fb_val >> 10) & 0xFF; + fb[2] = (audio->fb_val >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + fb[3] = 0; + } + else + { + // For HS format is 16.16 + fb[0] = (audio->fb_val >> 0) & 0xFF; + fb[1] = (audio->fb_val >> 8) & 0xFF; + fb[2] = (audio->fb_val >> 16) & 0xFF; + fb[3] = (audio->fb_val >> 24) & 0xFF; + } + return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len); + } - if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return 0; } +//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +//{ +// (void) rhport; +// (void) audio; +// +// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); +// return 0; +//} + #endif // This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send @@ -918,7 +950,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback { _audiod_itf[idxDriver].ep_fb = ep_addr; @@ -1215,13 +1247,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // Transmission of feedback EP finished if (_audiod_itf[idxDriver].ep_fb == ep_addr) { - if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } + if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return true; + return audio_fb_send(rhport, &_audiod_itf[idxDriver]); } #endif #endif @@ -1403,4 +1431,16 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) return false; } +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback) +{ + audiod_interface_t *audio = &_audiod_itf[0]; + + audio->fb_val = feedback; + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true); + + return audio_fb_send(rhport, audio); +} +#endif + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2f48955f2..f4029a84c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -259,6 +259,11 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_ #if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); +// User code should call this function with feedback value in 16.16 format for FS and HS. +// Value will be corrected for FS to 10.14 format automatically. +// (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). +// Feedback value will be sent at FB endpoint interval till it's changed. +bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/device/usbd.h b/src/device/usbd.h index 43af25076..a450bca7c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -377,6 +377,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) +/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -- cgit v1.3.1 From f55437d8898f46e6deee273306179c2a7f3f9b5d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 14:32:38 +0200 Subject: audio: Add descriptor for mono speaker This provides descriptor for mono speaker with explicit feedback. --- src/device/usbd.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index a450bca7c..7363159a4 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -431,6 +431,56 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) +// AUDIO simple descriptor (UAC2) for mono speaker +// - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source + +#define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) + +#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u -- cgit v1.3.1 From 13a9cbde7957de2d87731a85dcc0c7ea756e71b7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 29 Sep 2020 23:30:35 +0200 Subject: Change AUDIO_FUNC_PROTOCOL_CODE_UNDEF for midi in usbd.h --- src/device/usbd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index 7363159a4..07156c079 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -260,11 +260,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ /* AC Header */\ 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ /* MS Header */\ 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) -- cgit v1.3.1 From b2ce7a39b0d0b941ad7edb63f527b223568caa47 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:23:56 +0200 Subject: device: Make number of endpoints configurable Currently number of endpoints was hard coded to 8. NRF52 has 9 IN and 9 OUT endpoints. ISO endpoints are 0x08 and 0x88 and without this change those two ISO endpoint could not be used. --- src/device/usbd.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index d1e984a0e..3a6ce9b6c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -37,6 +37,10 @@ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif +#ifndef CFG_TUD_EP_MAX +#define CFG_TUD_EP_MAX 9 +#endif + //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ @@ -57,7 +61,7 @@ typedef struct uint8_t speed; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED { @@ -66,7 +70,7 @@ typedef struct volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[8][2]; + }ep_status[CFG_TUD_EP_MAX][2]; }usbd_device_t; @@ -249,7 +253,7 @@ static osal_mutex_t _usbd_mutex; //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -842,7 +846,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // Helper marking endpoint of interface belongs to class driver -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) +static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) { uint16_t len = 0; -- cgit v1.3.1 From 603ce17696dfb930f93649d82a87702fd89f303f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 1 Oct 2020 17:49:30 +0200 Subject: Change AUDIO_CS_INTERFACE_HEADER to AUDIO_CS_AC_INTERFACE_HEADER --- src/device/usbd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index 07156c079..69cb5319d 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -262,7 +262,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Audio Control (AC) Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ /* MIDI Streaming (MS) Interface */\ 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ /* MS Header */\ -- cgit v1.3.1 From 74a1404bea4a2cf4fd8ecb4ce227f19ba9fbe1a0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Oct 2020 13:36:27 +0700 Subject: tab -> spaces --- src/device/usbd.h | 506 +++++++++++++++++++++++++++--------------------------- 1 file changed, 253 insertions(+), 253 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index 69cb5319d..1b0f0cbd3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -67,7 +67,7 @@ bool tud_suspended(void); // Check if device is ready to transfer static inline bool tud_ready(void) { - return tud_mounted() && !tud_suspended(); + return tud_mounted() && !tud_suspended(); } // Remote wake up host, only if suspended and enabled by host @@ -141,11 +141,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // total length, number of device caps #define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ - 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num + 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num // Device Capability Platform 128-bit UUID + Data #define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ - 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ + 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ //------------- WebUSB BOS Platform -------------// @@ -154,22 +154,22 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Vendor Code, iLandingPage #define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) #define TUD_BOS_WEBUSB_UUID \ - 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ - 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 + 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ + 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 //------------- Microsoft OS 2.0 Platform -------------// #define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 // Total Length of descriptor set, vendor code #define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) #define TUD_BOS_MS_OS_20_UUID \ - 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ - 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ + 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F //--------------------------------------------------------------------+ // Configuration & Interface Descriptor Templates @@ -180,7 +180,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Config number, interface count, string index, total length, attribute, power in mA #define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// @@ -190,26 +190,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ - /* CDC Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC Call */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Associate */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ + /* CDC Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC Call */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* CDC ACM: support line request */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- MSC -------------// @@ -218,12 +218,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & EP In address, EP size #define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- HID -------------// @@ -233,12 +233,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input only descriptor // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval // Length of template descriptor: 32 bytes #define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) @@ -246,57 +246,57 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ - /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ - /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ - /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ - /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + /* Audio Control (AC) Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ + /* AC Header */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + /* MIDI Streaming (MS) Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ + /* MS Header */\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) #define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 1) + (uint8_t)(((_cablenum) - 1) * 4 + 1) #define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 2) + (uint8_t)(((_cablenum) - 1) * 4 + 2) #define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 3) + (uint8_t)(((_cablenum) - 1) * 4 + 3) #define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 4) + (uint8_t)(((_cablenum) - 1) * 4 + 4) #define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) #define TUD_MIDI_DESC_JACK(_cablenum) \ - /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ - /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ - /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ - /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + /* MS In Jack (Embedded) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ + /* MS In Jack (External) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ + /* MS Out Jack (Embedded), connected to In Jack External */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ + /* MS Out Jack (External), connected to In Jack Embedded */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 #define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack) */\ - (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + /* Endpoint */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables // Length of template descriptor (88 bytes) #define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) @@ -305,181 +305,181 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // - 1 Embedded Jack In connected to 1 External Jack Out // - 1 Embedded Jack out connected to 1 External Jack In #define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ - TUD_MIDI_DESC_JACK(1),\ - TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ - TUD_MIDI_JACKID_IN_EMB(1),\ - TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ - TUD_MIDI_JACKID_OUT_EMB(1) + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) //------------- AUDIO -------------// /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 #define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ #define TUD_AUDIO_DESC_STD_AC_LEN 9 #define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AC Interface Header Descriptor(4.7.2) */ #define TUD_AUDIO_DESC_CS_AC_LEN 9 #define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ - TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl + TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl /* Clock Source Descriptor(4.7.2.1) */ #define TUD_AUDIO_DESC_CLK_SRC_LEN 8 #define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ - TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx + TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx /* Input Terminal Descriptor(4.7.2.4) */ #define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 #define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ - TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx + TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx /* Output Terminal Descriptor(4.7.2.5) */ #define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 #define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ - TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx + TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx /* Feature Unit Descriptor(4.7.2.8) */ // 1 - Channel #define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 #define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx // For more channels, add definitions here /* Standard AS Interface Descriptor(4.9.1) */ #define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 #define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AS Interface Descriptor(4.9.2) */ #define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 #define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ - TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx + TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ #define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 #define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 #define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ #define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 #define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ - TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source #define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) #define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) // AUDIO simple descriptor (UAC2) for mono speaker // - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source #define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) #define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ - /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -491,23 +491,23 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, // bulk-in endpoint ID #define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ - /* Interface */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + /* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx #define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u #define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ - /* Endpoint Out */ \ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ - /* Endpoint In */ \ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + /* Endpoint Out */ \ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ + /* Endpoint In */ \ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u #define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) /* optional interrupt endpoint */ \ // _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? #define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ - 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 #define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) @@ -517,12 +517,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & IN address, EP size #define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* 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) @@ -534,10 +534,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // 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) + /* 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) //------------- CDC-ECM -------------// @@ -548,26 +548,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-ECM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC-ECM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-ECM Functional Descriptor */\ - 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface (default inactive) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* CDC Data Interface (alternative active) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-ECM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- RNDIS -------------// @@ -590,26 +590,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // RNDIS Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ - /* CDC-ACM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC Call Management */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* ACM */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- BT Radio -------------// #define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) @@ -626,20 +626,20 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Endpoint In for events */ \ - 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ - /* Endpoint In for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ - /* Endpoint Out for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 #define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ - /* Interface with 2 endpoints */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Isochronous endpoints */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 #define _FIRST(a, ...) a #define _REST(a, ...) __VA_ARGS__ @@ -647,24 +647,24 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_BTH_ISO_ITF_0(_itfnum, ...) #define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ - TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) // BT Primary controller descriptor // Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes #define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ - TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus } -- cgit v1.3.1 From 032e84c9befa0797f6a6faf86fbfdff13ec77bbe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 9 Oct 2020 19:50:05 +0200 Subject: Revert dcd_alloc_mem_for_conf() but keep changes from @kasjer for ISO EP Add tud_audio_set_itf_close_EP_cb() --- src/class/audio/audio_device.c | 6 +- src/class/audio/audio_device.h | 3 + src/device/dcd.h | 4 - src/device/usbd.c | 3 - src/portable/st/synopsys/dcd_synopsys.c | 469 ++++++++------------------------ 5 files changed, 115 insertions(+), 370 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0f501bb6e..2c8ba300d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -876,6 +876,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? } #endif @@ -928,7 +932,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * _audiod_itf[idxDriver].ep_in = ep_addr; _audiod_itf[idxDriver].ep_in_as_intf_num = itf; - // Invoke callback and trigger data generation - if not already running + // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d2f8155db..d86232720 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -272,6 +272,9 @@ TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_c // Invoked when audio set interface request received TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +// Invoked when audio set interface request received which closes an EP +TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); + // Invoked when audio class specific set request received for an EP TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); diff --git a/src/device/dcd.h b/src/device/dcd.h index c00e3c06d..776f782b8 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -115,10 +115,6 @@ void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; -// Invoked when a set configuration request was received -// Helper to allow for dynamic EP buffer allocation according to configuration descriptor -TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg); - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index d6d77dff2..90edc3dde 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -786,9 +786,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1 TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); - // Allow for dynamic allocation of EP buffer for current configuration - only one configuration may be active according to USB specification - if (dcd_alloc_mem_for_conf) TU_ASSERT(dcd_alloc_mem_for_conf(rhport, desc_cfg)); - // Parse configuration descriptor _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5a89bb386..ca306ff8f 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -47,53 +47,53 @@ #if TUSB_OPT_DEVICE_ENABLED && \ ( (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ ) // EP_MAX : Max number of bi-directional endpoints including EP0 // EP_FIFO_SIZE : Size of dedicated USB SRAM #if CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - #define EP_MAX_FS 4 - #define EP_FIFO_SIZE_FS 1280 +#include "stm32f1xx.h" +#define EP_MAX_FS 4 +#define EP_FIFO_SIZE_FS 1280 #elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE +#include "stm32f2xx.h" +#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE - #define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE +#include "stm32f4xx.h" +#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE +#define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - #define EP_MAX_FS 9 - #define EP_FIFO_SIZE_FS 4096 - #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 +#include "stm32h7xx.h" +#define EP_MAX_FS 9 +#define EP_FIFO_SIZE_FS 4096 +#define EP_MAX_HS 9 +#define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 - #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 +#include "stm32f7xx.h" +#define EP_MAX_FS 6 +#define EP_FIFO_SIZE_FS 1280 +#define EP_MAX_HS 9 +#define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 +#include "stm32l4xx.h" +#define EP_MAX_FS 6 +#define EP_FIFO_SIZE_FS 1280 #else - #error "Unsupported MCUs" +#error "Unsupported MCUs" #endif @@ -105,16 +105,16 @@ // On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS #if TUD_OPT_RHPORT == 0 - #define EP_MAX EP_MAX_FS - #define EP_FIFO_SIZE EP_FIFO_SIZE_FS - #define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE - #define RHPORT_IRQn OTG_FS_IRQn +#define EP_MAX EP_MAX_FS +#define EP_FIFO_SIZE EP_FIFO_SIZE_FS +#define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE +#define RHPORT_IRQn OTG_FS_IRQn #else - #define EP_MAX EP_MAX_HS - #define EP_FIFO_SIZE EP_FIFO_SIZE_HS - #define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE - #define RHPORT_IRQn OTG_HS_IRQn +#define EP_MAX EP_MAX_HS +#define EP_FIFO_SIZE EP_FIFO_SIZE_HS +#define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE +#define RHPORT_IRQn OTG_HS_IRQn #endif #define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE) @@ -145,7 +145,7 @@ typedef struct TU_ATTR_PACKED { // The codes assigned to those fields, according to the USB specification, can be neatly used as indices. uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt - ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! + ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! } ep_sz_tt_report_t; typedef volatile uint32_t * usb_fifo_t; @@ -167,7 +167,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - // USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -217,93 +217,28 @@ static void bus_reset(uint8_t rhport) // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to // overwrite this. - // We rework this here and initialize the FIFOs here only for the USB reset case. The rest is done once a - // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. - - // Found by trial: 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6 - not quite sure where 1 + 6 comes from but this works for 8/16/32/64 EP0 size - _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) - - // _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) +#if TUD_OPT_HIGH_SPEED + _allocated_fifo_words = 271 + 2*EP_MAX; +#else + _allocated_fifo_words = 47 + 2*EP_MAX; +#endif usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (CFG_TUD_ENDPOINT0_SIZE/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += CFG_TUD_ENDPOINT0_SIZE/4; + _allocated_fifo_words += 16; - // Set SETUP packet count to 3 - out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - - usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + // TU_LOG2_INT(_allocated_fifo_words); + // Fixed control EP0 size to 64 bytes + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - //#if TUD_OPT_HIGH_SPEED - // _allocated_fifo_words = 271 + 2*EP_MAX; - //#else - // _allocated_fifo_words = 47 + 2*EP_MAX; - //#endif - // - // usb_otg->GRXFSIZ = _allocated_fifo_words; - // - // // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - // usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - // - // _allocated_fifo_words += 16; - // - // // TU_LOG2_INT(_allocated_fifo_words); - // - // // Fixed control EP0 size to 64 bytes - // in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - // xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - // - // // Set SETUP packet count to 3 - // out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - // - // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; -} - -// Required after new configuration received in case EP0 max packet size has changed -static void set_EP0_max_pkt_size(void) -{ - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - - uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL. - switch (enum_spd) - { - case 0x00: // High speed - always 64 byte - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - break; - - case 0x03: // Full speed -#if CFG_TUD_ENDPOINT0_SIZE == 64 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; -#elif CFG_TUD_ENDPOINT0_SIZE == 32 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; -#elif CFG_TUD_ENDPOINT0_SIZE == 16 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; -#elif CFG_TUD_ENDPOINT0_SIZE == 8 - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; -#else -# error CFG_TUD_ENDPOINT0_SIZE MUST be 8, 16, 32, or 64! -#endif - break; + out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - default: // Low speed - always 8 bytes - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } + usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } // Set turn-around timeout according to link speed @@ -536,8 +471,8 @@ void dcd_init (uint8_t rhport) if ( rhport == 0 ) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | - USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | - USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; @@ -594,7 +529,7 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { -// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -620,15 +555,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if(dir == TUSB_DIR_OUT) { out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); + (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); } else { - // FIFO allocation done in dcd_alloc_mem_for_conf() - // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // @@ -654,35 +587,35 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // - Interrupt is EPSize // - Bulk/ISO is max(EPSize, remaining-fifo / non-opened-EPIN) -// uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; -// uint16_t fifo_size = desc_edpt->wMaxPacketSize.size / 4; -// -// if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) -// { -// uint8_t opened = 0; -// for(uint8_t i = 0; i < EP_MAX; i++) -// { -// if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; -// } -// -// // EP Size or equally divided of remaining whichever is larger -// fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); -// } -// -// // FIFO overflows, we probably need a better allocating scheme -// TU_ASSERT(fifo_size <= fifo_remaining); -// -// // DIEPTXF starts at FIFO #1. -// // Both TXFD and TXSA are in unit of 32-bit words. -// usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; -// -// _allocated_fifo_words += fifo_size; + uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; + uint16_t fifo_size = (desc_edpt->wMaxPacketSize.size + 3) / 4; // +3 for rounding up to next full word + + if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) + { + uint8_t opened = 0; + for(uint8_t i = 0; i < EP_MAX; i++) + { + if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; + } + + // EP Size or equally divided of remaining whichever is larger + fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); + } + + // FIFO overflows, we probably need a better allocating scheme + TU_ASSERT(fifo_size <= fifo_remaining); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; + + _allocated_fifo_words += fifo_size; in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | - (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); + (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); } @@ -780,7 +713,20 @@ static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) */ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + dcd_edpt_disable(rhport, ep_addr, false); + if (dir == TUSB_DIR_IN) + { + uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; + uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; + // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. + TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); + _allocated_fifo_words -= fifo_size; + } } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) @@ -892,7 +838,7 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ switch(pktsts) { case 0x01: // Global OUT NAK (Interrupt) - break; + break; case 0x02: // Out packet recvd { @@ -920,18 +866,18 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ case 0x04: // Setup packet done (Interrupt) out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - break; + break; case 0x06: // Setup packet recvd // We can receive up to three setup packets in succession, but // only the last one is valid. _setup_packet[0] = (* rx_fifo); _setup_packet[1] = (* rx_fifo); - break; + break; default: // Invalid TU_BREAKPOINT(); - break; + break; } } @@ -1049,9 +995,6 @@ void dcd_int_handler(uint8_t rhport) tusb_speed_t const speed = get_speed(rhport); set_turnaround(usb_otg, speed); - - set_EP0_max_pkt_size(); - dcd_event_bus_reset(rhport, speed, true); } @@ -1115,209 +1058,11 @@ void dcd_int_handler(uint8_t rhport) handle_epin_ints(rhport, dev, in_ep); } - // Check for Incomplete isochronous IN transfer - if(int_status & USB_OTG_GINTSTS_IISOIXFR) { - TU_LOG2(" IISOIXFR!\r\n"); - } -} - -// Helper function which parses through the current configuration descriptors to find the biggest EPs in size. -static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg, ep_sz_tt_report_t * p_report) -{ - (void) rhport; - - // tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! - - // EP0 sizes and usages are fixed - p_report->ep_size[0][TUSB_DIR_OUT] = p_report->ep_size[0][TUSB_DIR_IN] = CFG_TUD_ENDPOINT0_SIZE; - p_report->ep_transfer_type[0][TUSB_DIR_OUT][TUSB_XFER_CONTROL] = p_report->ep_transfer_type[0][TUSB_DIR_IN][TUSB_XFER_CONTROL] = true; - - // Parse interface descriptor - uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; - - uint8_t addr; - - while( p_desc < desc_end ) - { - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) - { - - addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - // Verify values - this checks may be omitted in case we trust the descriptors to be okay - TU_VERIFY(tu_edpt_number(addr) < EP_MAX); - TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); - TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); - - p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); - p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; - } - p_desc = tu_desc_next(p_desc); // Proceed - } - return true; -} - -// Setup FIFO buffers at configuration time. -// The idea is to use this information such that the FIFOs need to be configured only once -// at configuration time and no more later. This makes it easy in case you want to close and open EPs for different -// purposes at any time (without taking care of other active EPs). You also avoid the nasty need of defragmenting -// the TX buffers, which is likely to happen. -// Certainly, this function does not allow for the highest possible flexibility as it only works in the worst case -// (all biggest EPs can be active at the same time). However, this should not be a problem for almost all applications. - -// Spare space is assigned equally divided to bulk and interrupt EPs. -// Pure isochronous EPs do not get any spare space as it does not make any sense. -TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg) -{ - (void) rhport; - - USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - - // for(uint8_t n = 0; n < EP_MAX; n++) { - // out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - // } - - out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - - // Deactivate Interrupts? - dev->DAINTMSK &= ~((1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos)); - dev->DOEPMSK &= ~(USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM); - dev->DIEPMSK &= ~(USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM); - - // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); - - // Determine maximum required spaces for individual EPs and what kind of usage (control, bulk, etc.) they are used for - ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type - TU_VERIFY(get_ep_size_report(rhport, desc_cfg, &report)); - - // With that information, set the following up: - // The RX buffer size (as it is a shared buffer here) is set to the sum of the two biggest out EPs plus all the required extra words used for setup packets etc. - // This should work well for all kinds of applications - - // Determine number of used out EPs of current configuration and size of two biggest out EPs - uint8_t nUsedOutEPs = 0, cnt_ep, cnt_tt; - uint16_t sz[2] = {0, 0}; - uint16_t fifo_depth; - - for (cnt_ep = 0; cnt_ep < EP_MAX; cnt_ep++) - { - for (cnt_tt = 0; cnt_tt <= TUSB_XFER_INTERRUPT; cnt_tt++) - { - if (report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt]) - { - nUsedOutEPs++; - break; - } - } - - fifo_depth = report.ep_size[cnt_ep][TUSB_DIR_OUT] / 4 + 1; - if (sz[0] < fifo_depth) - { - sz[1] = sz[0]; - sz[0] = fifo_depth; - } - else if (sz[1] < report.ep_size[cnt_ep][TUSB_DIR_OUT]) - { - sz[1] = fifo_depth; - } - } - - // For configuration use the approach as explained in bus_reset() - _allocated_fifo_words = 13 + 1 + 1 + 2 * nUsedOutEPs + sz[0] + sz[1] + 2; // again, i do not really know why we need + 2 but otherwise it does not work - - usb_otg->GRXFSIZ = _allocated_fifo_words; - - // Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word ) - fifo_depth = report.ep_size[0][TUSB_DIR_IN] / 4; - fifo_depth = tu_max16(16, fifo_depth); - usb_otg->DIEPTXF0_HNPTXFSIZ = (fifo_depth << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - - _allocated_fifo_words += fifo_depth; - - // For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that: - // - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more. - // Furthermore, double buffering is not possible (for this silicon) since once FIFO was written to and transmit bit was set you are - // not allowed to write to the FIFO any more until transmit was done. So you can not send something and buffer the next frame in the - // meantime into the buffer. TODO: check for high speed and uC types which can do this! - // - Interrupt EPs only get EP size as FIFO size - // - Bulk and control (other than EP0 - this is possible) get spare space equally divided - those profit the most from extra space - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + w + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + w + GRXFSIZ - // | IN FIFO 1 | - // --------------- w + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // In FIFO is allocated by following rules: - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - // - Offset: allocated so far - // - Size - as described above - - // Determine required numbers - // Remaining space available in bytes - uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; - - // Required space by EPs in words, number of bulk and control EPs - uint16_t ep_sz_total = 0; - // Number of bulk and control EPs - uint8_t nbc = 0; - // EP0 is already taken care of so exclude that here - for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) - { - fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4; // Since we need full words take care of remainders! - if (fifo_depth > 0 && fifo_depth < 16) fifo_depth = 16; // Minimum FIFO depth is 16 - ep_sz_total += fifo_depth; - nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]); - } - - if (ep_sz_total > fifo_remaining) - { - // Too less space available to apply this allocation scheme - return false and set a flag such that a different approach may be used TODO: introduce flag - return false; - } - - uint16_t extra_space = nbc > 0 ? (fifo_remaining - ep_sz_total) / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused - - // Setup FIFOs - for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) - { - // If EP is used - if (report.ep_size[cnt_ep][TUSB_DIR_IN] > 0) - { - fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4 + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0); - fifo_depth = tu_max16(16, fifo_depth); - usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_depth << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += fifo_depth; - } - } - - // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; - - // Enable interrupts - dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); - dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; - dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; - - // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; - - out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_CNAK; - - return true; +// // Check for Incomplete isochronous IN transfer +// if(int_status & USB_OTG_GINTSTS_IISOIXFR) { +// printf(" IISOIXFR!\r\n"); +//// TU_LOG2(" IISOIXFR!\r\n"); +// } } #endif -- cgit v1.3.1 From 87b989e8b4b497713cc4b88103dc6dfadc43e149 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Oct 2020 00:35:38 +0700 Subject: add usbh_edpt_claim/release implement USBH_EVENT_FUNC_CALL --- src/device/dcd.h | 2 +- src/host/hcd.h | 11 ++++++++ src/host/usbh.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- src/host/usbh.h | 9 ++++-- src/host/usbh_control.c | 8 +++++- src/host/usbh_hcd.h | 23 ++++++++++++++- 6 files changed, 120 insertions(+), 8 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index a5c485f9e..b7e5a8da0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -77,7 +77,7 @@ typedef struct TU_ATTR_ALIGNED(4) uint32_t len; }xfer_complete; - // USBD_EVENT_FUNC_CALL + // FUNC_CALL struct { void (*func) (void*); void* param; diff --git a/src/host/hcd.h b/src/host/hcd.h index ba3035300..db98f6110 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -45,6 +45,11 @@ typedef enum HCD_EVENT_DEVICE_ATTACH, HCD_EVENT_DEVICE_REMOVE, HCD_EVENT_XFER_COMPLETE, + + // Not an HCD event, just a convenient way to defer ISR function + USBH_EVENT_FUNC_CALL, + + HCD_EVENT_COUNT } hcd_eventid_t; typedef struct @@ -67,6 +72,12 @@ typedef struct uint8_t result; uint32_t len; } xfer_complete; + + // FUNC_CALL + struct { + void (*func) (void*); + void* param; + }func_call; }; } hcd_event_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index 4932e662c..595024b9c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -169,6 +169,11 @@ bool tuh_init(void) dev->control.sem_hdl = osal_semaphore_create(&dev->control.sem_def); TU_ASSERT(dev->control.sem_hdl != NULL); +#if CFG_TUSB_OS != OPT_OS_NONE + dev->mutex = osal_mutex_create(&dev->mutexdef); + TU_ASSERT(dev->mutex); +#endif + memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping } @@ -187,6 +192,8 @@ bool tuh_init(void) } //------------- USBH control transfer -------------// + +// TODO remove bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -216,6 +223,58 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 return true; } +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -402,6 +461,8 @@ void tuh_task(void) switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: + // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating + // one device before enumerating another one. TU_LOG2("USBH DEVICE ATTACH\r\n"); enum_new_device(&event); break; @@ -443,6 +504,10 @@ void tuh_task(void) } break; + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + default: break; } } @@ -465,6 +530,8 @@ static uint8_t get_new_address(void) // is a lengthy process with a seires of control transfer to configure // newly attached device. Each step is handled by a function in this // section +// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating +// one device before enumerating another one. //--------------------------------------------------------------------+ static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -785,7 +852,7 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - // Check if class is supportedVe + // Check if class is supported uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { @@ -799,6 +866,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura } else { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + // Interface number must not be used already TODO alternate interface TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; @@ -813,8 +882,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { uint16_t itf_len = 0; - TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); - TU_ASSERT( usbh_class_drivers[drv_id].open(dev->rhport, dev_addr, desc_itf, &itf_len) ); + TU_LOG2("%s open\r\n", driver->name); + TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 814770722..fde1dd11c 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -65,6 +65,7 @@ typedef struct { } usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -106,11 +107,15 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ -bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); - bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); // TODO remove later + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 595c011f5..70800eba6 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -58,6 +58,8 @@ static usbh_control_xfer_t _ctrl_xfer; bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) { + // TODO need to claim the endpoint first + usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; @@ -83,6 +85,10 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) ep_addr; + (void) xferred_bytes; + + usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; @@ -106,7 +112,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); return true; } - __attribute__((fallthrough)); + __attribute__((fallthrough)); case STAGE_DATA: _ctrl_xfer.stage = STAGE_ACK; diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index f203f3baa..20348eed1 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -40,6 +40,10 @@ #include "common/tusb_common.h" #include "osal/osal.h" +#ifndef CFG_TUH_EP_MAX +#define CFG_TUH_EP_MAX 9 +#endif + //--------------------------------------------------------------------+ // USBH-HCD common data structure //--------------------------------------------------------------------+ @@ -80,7 +84,24 @@ typedef struct { } control; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + + struct TU_ATTR_PACKED + { + volatile bool busy : 1; + volatile bool stalled : 1; + volatile bool claimed : 1; + + // TODO merge ep2drv here, 4-bit should be sufficient + }ep_status[CFG_TUH_EP_MAX][2]; + + +// Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_def_t mutexdef; + osal_mutex_t mutex; +#endif + } usbh_device_t; extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address -- cgit v1.3.1 From 8669fd738313e296c376312ba22945a003d81a4f Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Thu, 15 Oct 2020 15:34:12 +0200 Subject: audio: Add two channel feature unit descriptor Feature unit descriptor size depends on number of channels. So far only single channel feature unit was present. This change adds feature unit descriptor for two channels. --- src/device/usbd.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index 1b0f0cbd3..d48f37eb0 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -350,6 +350,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx +// 2 - Channels +#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) +#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx + // For more channels, add definitions here /* Standard AS Interface Descriptor(4.9.1) */ -- cgit v1.3.1 From 3ea813875034be8878d3f01a740c377ebb6c8306 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 31 Oct 2020 10:57:53 -0600 Subject: Rename CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL This was a confusing name; "Ethernet control model" (CDC ECM) and "network control model" (CDC NCM) are two separate USB subclasses. --- src/class/cdc/cdc.h | 2 +- src/class/net/net_device.c | 6 +++--- src/device/usbd.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f0488acbb..2c044ac7f 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -63,7 +63,7 @@ typedef enum CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL , ///< Telephone Control Model [USBPSTN1.2] CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL , ///< Multi-Channel Control Model [USBISDN1.2] CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL , ///< CAPI Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2] + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2] CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL , ///< ATM Networking Control Model [USBATM1.2] CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL , ///< Wireless Handset Control Model [USBWMC1.1] CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT , ///< Device Management [USBWMC1.1] diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 65fd1ab53..3a45a9b99 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -141,9 +141,9 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); - bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0x00 == itf_desc->bInterfaceProtocol); + bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0x00 == itf_desc->bInterfaceProtocol); TU_VERIFY(is_rndis || is_ecm, 0); diff --git a/src/device/usbd.h b/src/device/usbd.h index d48f37eb0..0a446fdc2 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -554,9 +554,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, 0,\ /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, _desc_stridx,\ /* CDC-ECM Header */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC-ECM Union */\ -- cgit v1.3.1 From 3c31d0805130e9551f97afae94f765b5d032991b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 21:01:33 +0700 Subject: merge class driver control_request & control_complete to control_xfer_cb() migrated msc_device --- src/class/msc/msc_device.c | 19 ++++++------------- src/class/msc/msc_device.h | 3 +-- src/common/tusb_types.h | 7 +++++++ src/device/usbd.c | 39 +++++++++++++++++++-------------------- src/device/usbd.h | 2 +- src/device/usbd_control.c | 8 ++++---- src/device/usbd_pvt.h | 5 ++++- 7 files changed, 42 insertions(+), 41 deletions(-) (limited to 'src/device') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index f3f2e536e..cfb8a43a3 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -186,10 +186,14 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request) { + // nothing to do with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) return true; + // Handle class request only TU_VERIFY(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); @@ -219,17 +223,6 @@ bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque return true; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool mscd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - (void) request; - - // nothing to do - return true; -} - // return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) // In case of a failed status, sense key must be set for reason of failure int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 3aa93ffd7..f1e6c40f4 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -161,8 +161,7 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); void mscd_init (void); void mscd_reset (uint8_t rhport); uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index d6b6ea627..5ab15aa3c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -250,6 +250,13 @@ typedef enum MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 } microsoft_os_20_type_t; +enum +{ + CONTROL_STAGE_SETUP, + CONTROL_STAGE_DATA, + CONTROL_STAGE_ACK +}; + //--------------------------------------------------------------------+ // USB Descriptors //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 90edc3dde..02f631dea 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -97,7 +97,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, - .control_request = cdcd_control_request, + .control_xfer_cb = cdcd_control_request, .control_complete = cdcd_control_complete, .xfer_cb = cdcd_xfer_cb, .sof = NULL @@ -110,8 +110,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = mscd_init, .reset = mscd_reset, .open = mscd_open, - .control_request = mscd_control_request, - .control_complete = mscd_control_complete, + .control_xfer_cb = mscd_control_xfer_cb, .xfer_cb = mscd_xfer_cb, .sof = NULL }, @@ -123,7 +122,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = hidd_init, .reset = hidd_reset, .open = hidd_open, - .control_request = hidd_control_request, + .control_xfer_cb = hidd_control_request, .control_complete = hidd_control_complete, .xfer_cb = hidd_xfer_cb, .sof = NULL @@ -134,9 +133,9 @@ static usbd_class_driver_t const _usbd_driver[] = { DRIVER_NAME("AUDIO") .init = audiod_init, - .reset = audiod_reset, + .reset = audiod_reset, .open = audiod_open, - .control_request = audiod_control_request, + .control_xfer_cb = audiod_control_request, .control_complete = audiod_control_complete, .xfer_cb = audiod_xfer_cb, .sof = NULL @@ -149,7 +148,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = midid_init, .open = midid_open, .reset = midid_reset, - .control_request = midid_control_request, + .control_xfer_cb = midid_control_request, .control_complete = midid_control_complete, .xfer_cb = midid_xfer_cb, .sof = NULL @@ -162,7 +161,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = vendord_init, .reset = vendord_reset, .open = vendord_open, - .control_request = tud_vendor_control_request_cb, + .control_xfer_cb = tud_vendor_control_request_cb, .control_complete = tud_vendor_control_complete_cb, .xfer_cb = vendord_xfer_cb, .sof = NULL @@ -175,7 +174,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, - .control_request = usbtmcd_control_request_cb, + .control_xfer_cb = usbtmcd_control_request_cb, .control_complete = usbtmcd_control_complete_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL @@ -188,7 +187,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, - .control_request = dfu_rtd_control_request, + .control_xfer_cb = dfu_rtd_control_request, .control_complete = dfu_rtd_control_complete, .xfer_cb = dfu_rtd_xfer_cb, .sof = NULL @@ -201,7 +200,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = netd_init, .reset = netd_reset, .open = netd_open, - .control_request = netd_control_request, + .control_xfer_cb = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, .sof = NULL, @@ -214,7 +213,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = btd_init, .reset = btd_reset, .open = btd_open, - .control_request = btd_control_request, + .control_xfer_cb = btd_control_request, .control_complete = btd_control_complete, .xfer_cb = btd_xfer_cb, .sof = NULL @@ -274,7 +273,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); @@ -313,12 +312,12 @@ static char const* const _tusb_std_request_str[] = }; // for usbd_control to print the name of control complete driver -void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) +void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { usbd_class_driver_t const * driver = get_driver(i); - if ( driver->control_complete == control_complete ) + if ( driver->control_xfer_cb == callback ) { TU_LOG2(" %s control complete\r\n", driver->name); return; @@ -565,9 +564,9 @@ void tud_task (void) // Helper to invoke class driver control request handler static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { - usbd_control_set_complete_callback(driver->control_complete); + usbd_control_set_complete_callback(driver->control_xfer_cb); TU_LOG2(" %s control request\r\n", driver->name); - return driver->control_request(rhport, request); + return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); } // This handles the actual request and its response. @@ -581,10 +580,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(tud_vendor_control_request_cb); + TU_VERIFY(tud_vendor_control_xfer_cb); - if (tud_vendor_control_complete_cb) usbd_control_set_complete_callback(tud_vendor_control_complete_cb); - return tud_vendor_control_request_cb(rhport, p_request); + usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); + return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 diff --git a/src/device/usbd.h b/src/device/usbd.h index e88f64ba8..cf7e9f0db 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -125,7 +125,7 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE -TU_ATTR_WEAK bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); +TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); // Invoked when vendor control request is complete TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index db0eb70a7..f1edad376 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -33,7 +33,7 @@ #include "dcd.h" #if CFG_TUSB_DEBUG >= 2 -extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); +extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif enum @@ -50,7 +50,7 @@ typedef struct uint16_t data_len; uint16_t total_xferred; - bool (*complete_cb) (uint8_t, tusb_control_request_t const *); + usbd_control_xfer_cb_t complete_cb; } usbd_control_xfer_t; static usbd_control_xfer_t _ctrl_xfer; @@ -146,7 +146,7 @@ void usbd_control_reset(void) } // TODO may find a better way -void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ) +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) { _ctrl_xfer.complete_cb = fp; } @@ -199,7 +199,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif - is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request); + is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); } if ( is_ok ) diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 09b285581..57331041b 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -46,7 +46,7 @@ typedef struct void (* init ) (void); void (* reset ) (uint8_t rhport); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void (* sof ) (uint8_t rhport); /* optional */ @@ -57,6 +57,9 @@ typedef struct // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + +typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -- cgit v1.3.1 From dd07fecc5f37c85b87060c7f7158d26ff19757a6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 21:26:06 +0700 Subject: migrate cdc_device to new control_xfer_cb --- src/class/cdc/cdc_device.c | 85 +++++++++++++++++++--------------------------- src/class/cdc/cdc_device.h | 11 +++--- src/class/msc/msc_device.h | 10 +++--- src/device/usbd.c | 3 +- src/device/usbd_control.c | 9 +++++ 5 files changed, 55 insertions(+), 63 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e54b7d260..2933dcd3d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -315,38 +315,10 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool cdcd_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); - - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; - - // Identify which interface to use - for ( ; ; itf++, p_cdc++) - { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - - if ( p_cdc->itf_num == request->wIndex ) break; - } - - // Invoke callback - if ( CDC_REQUEST_SET_LINE_CODING == request->bRequest ) - { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } - - return true; -} - -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { // Handle class request only TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); @@ -365,34 +337,47 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: - TU_LOG2(" Set Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Set Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } + else if ( stage == CONTROL_STAGE_ACK) + { + if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + } break; case CDC_REQUEST_GET_LINE_CODING: - TU_LOG2(" Get Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Get Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: - { - // CDC PSTN v1.2 section 6.3.12 - // Bit 0: Indicates if DTE is present or not. - // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) - // Bit 1: Carrier control for half-duplex modems. - // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) - bool const dtr = tu_bit_test(request->wValue, 0); - bool const rts = tu_bit_test(request->wValue, 1); - - p_cdc->line_state = (uint8_t) request->wValue; + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + // CDC PSTN v1.2 section 6.3.12 + // Bit 0: Indicates if DTE is present or not. + // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) + // Bit 1: Carrier control for half-duplex modems. + // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + bool const dtr = tu_bit_test(request->wValue, 0); + bool const rts = tu_bit_test(request->wValue, 1); - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); + p_cdc->line_state = (uint8_t) request->wValue; - tud_control_status(rhport, request); + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); - } + // Invoke callback + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + } break; default: return false; // stall unsupported request diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 3c679c48e..3e68e2a88 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -236,12 +236,11 @@ static inline uint32_t tud_cdc_write_available(void) //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index f1e6c40f4..469f2f2f7 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -158,11 +158,11 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 02f631dea..dbe11d380 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -97,8 +97,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, - .control_xfer_cb = cdcd_control_request, - .control_complete = cdcd_control_complete, + .control_xfer_cb = cdcd_control_xfer_cb, .xfer_cb = cdcd_xfer_cb, .sof = NULL }, diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f1edad376..bb631320a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -171,7 +171,16 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) { TU_ASSERT(0 == xferred_bytes); + + // invoke optional dcd hook if available if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + + if (_ctrl_xfer.complete_cb) + { + // TODO refactor with usbd_driver_print_control_complete_name + _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); + } + return true; } -- cgit v1.3.1 From dc9a30983982717b1a0e8b48833fca841de5e70e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 22:00:49 +0700 Subject: migrate hid device to new control xfer cb --- src/class/hid/hid_device.c | 190 +++++++++++++++++++++++---------------------- src/class/hid/hid_device.h | 11 ++- src/device/usbd.c | 3 +- 3 files changed, 102 insertions(+), 102 deletions(-) (limited to 'src/device') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 11da5f220..1f03f8862 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -211,9 +211,10 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 return drv_len; } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); @@ -225,27 +226,29 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { //------------- STD Request -------------// - uint8_t const desc_type = tu_u16_high(request->wValue); - uint8_t const desc_index = tu_u16_low (request->wValue); - (void) desc_index; - - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) - { - TU_VERIFY(p_hid->hid_descriptor != NULL); - TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); - } - else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) - { - uint8_t const * desc_report = tud_hid_descriptor_report_cb( - #if CFG_TUD_HID > 1 - hid_itf // TODO for backward compatible callback, remove later when appropriate - #endif - ); - tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); - } - else + if ( stage == CONTROL_STAGE_SETUP ) { - return false; // stall unsupported request + uint8_t const desc_type = tu_u16_high(request->wValue); + //uint8_t const desc_index = tu_u16_low (request->wValue); + + if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) + { + TU_VERIFY(p_hid->hid_descriptor != NULL); + TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); + } + else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) + { + uint8_t const * desc_report = tud_hid_descriptor_report_cb( + #if CFG_TUD_HID > 1 + hid_itf // TODO for backward compatible callback, remove later when appropriate + #endif + ); + tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); + } + else + { + return false; // stall unsupported request + } } } else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) @@ -254,70 +257,98 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request switch( request->bRequest ) { case HID_REQ_CONTROL_GET_REPORT: - { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); + if ( stage == CONTROL_STAGE_SETUP ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength - ); - TU_ASSERT( xferlen > 0 ); + uint16_t xferlen = tud_hid_get_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength + ); + TU_ASSERT( xferlen > 0 ); - tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); - } + tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); + } break; case HID_REQ_CONTROL_SET_REPORT: - TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); - tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); + tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + tud_hid_set_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength + ); + } break; case HID_REQ_CONTROL_SET_IDLE: - p_hid->idle_rate = tu_u16_high(request->wValue); - if ( tud_hid_set_idle_cb ) + if ( stage == CONTROL_STAGE_SETUP ) { - // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->idle_rate) - ); + p_hid->idle_rate = tu_u16_high(request->wValue); + if ( tud_hid_set_idle_cb ) + { + // stall request if callback return false + TU_VERIFY( tud_hid_set_idle_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->idle_rate) + ); + } + + tud_control_status(rhport, request); } - - tud_control_status(rhport, request); break; case HID_REQ_CONTROL_GET_IDLE: - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + if ( stage == CONTROL_STAGE_SETUP ) + { + // TODO idle rate of report + tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + } break; case HID_REQ_CONTROL_GET_PROTOCOL: - { - uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); // 0 is Boot, 1 is Report protocol - tud_control_xfer(rhport, request, &protocol, 1); - } + if ( stage == CONTROL_STAGE_SETUP ) + { + // 0 is Boot, 1 is Report protocol + uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); + tud_control_xfer(rhport, request, &protocol, 1); + } break; case HID_REQ_CONTROL_SET_PROTOCOL: - p_hid->boot_mode = 1 - request->wValue; // 0 is Boot, 1 is Report protocol - - if (tud_hid_boot_mode_cb) + if ( stage == CONTROL_STAGE_SETUP ) { - tud_hid_boot_mode_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->boot_mode - ); + // 0 is Boot, 1 is Report protocol + p_hid->boot_mode = 1 - request->wValue; + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if (tud_hid_boot_mode_cb) + { + tud_hid_boot_mode_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->boot_mode + ); + } } - - tud_control_status(rhport, request); break; default: return false; // stall unsupported request @@ -330,35 +361,6 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request return true; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - uint8_t const hid_itf = get_index_by_itfnum((uint8_t) p_request->wIndex); - TU_VERIFY(hid_itf < CFG_TUD_HID); - - hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; - - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - p_request->bRequest == HID_REQ_CONTROL_SET_REPORT) - { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(p_request->wValue); - uint8_t const report_id = tu_u16_low(p_request->wValue); - - tud_hid_set_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength - ); - } - - return true; -} - bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index d5b5b7296..2d4c59d8f 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -359,12 +359,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hidd_init (void); +void hidd_reset (uint8_t rhport); +uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index dbe11d380..1e6722ffb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -121,8 +121,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = hidd_init, .reset = hidd_reset, .open = hidd_open, - .control_xfer_cb = hidd_control_request, - .control_complete = hidd_control_complete, + .control_xfer_cb = hidd_control_xfer_cb, .xfer_cb = hidd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From e2abb089f4e96cd7731bc97067566541090a1eda Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:30:36 +0700 Subject: migrate midi device to new control xfer cb --- src/class/midi/midi_device.c | 12 +++--------- src/class/midi/midi_device.h | 11 +++++------ src/device/usbd.c | 3 +-- 3 files changed, 9 insertions(+), 17 deletions(-) (limited to 'src/device') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index a07acf0b8..b61df59aa 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -375,17 +375,11 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint return drv_len; } -bool midid_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { (void) rhport; - (void) p_request; - return true; -} - -bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - (void) p_request; + (void) stage; + (void) request; // driver doesn't support any request yet return false; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index b8fb55cc2..9235448f2 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -142,12 +142,11 @@ static inline bool tud_midi_send (uint8_t const packet[4]) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void midid_init (void); +void midid_reset (uint8_t rhport); +uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 1e6722ffb..3686ec28c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -146,8 +146,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = midid_init, .open = midid_open, .reset = midid_reset, - .control_xfer_cb = midid_control_request, - .control_complete = midid_control_complete, + .control_xfer_cb = midid_control_xfer_cb, .xfer_cb = midid_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 8813f9d3b8a997e7a16c61a094f117a50c6ae435 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:32:16 +0700 Subject: clean up --- src/class/midi/midi_device.c | 3 + src/device/usbd.c | 146 +++++++++++++++++++++---------------------- 2 files changed, 76 insertions(+), 73 deletions(-) (limited to 'src/device') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index b61df59aa..ce4c9cafe 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -375,6 +375,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint return drv_len; } +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { (void) rhport; diff --git a/src/device/usbd.c b/src/device/usbd.c index 3686ec28c..bea41b592 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -93,43 +93,43 @@ static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC { - DRIVER_NAME("CDC") - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL + DRIVER_NAME("CDC") + .init = cdcd_init, + .reset = cdcd_reset, + .open = cdcd_open, + .control_xfer_cb = cdcd_control_xfer_cb, + .xfer_cb = cdcd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_MSC { - DRIVER_NAME("MSC") - .init = mscd_init, - .reset = mscd_reset, - .open = mscd_open, - .control_xfer_cb = mscd_control_xfer_cb, - .xfer_cb = mscd_xfer_cb, - .sof = NULL + DRIVER_NAME("MSC") + .init = mscd_init, + .reset = mscd_reset, + .open = mscd_open, + .control_xfer_cb = mscd_control_xfer_cb, + .xfer_cb = mscd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_HID { - DRIVER_NAME("HID") - .init = hidd_init, - .reset = hidd_reset, - .open = hidd_open, - .control_xfer_cb = hidd_control_xfer_cb, - .xfer_cb = hidd_xfer_cb, - .sof = NULL + DRIVER_NAME("HID") + .init = hidd_init, + .reset = hidd_reset, + .open = hidd_open, + .control_xfer_cb = hidd_control_xfer_cb, + .xfer_cb = hidd_xfer_cb, + .sof = NULL }, #endif -#if CFG_TUD_AUDIO -{ - DRIVER_NAME("AUDIO") + #if CFG_TUD_AUDIO + { + DRIVER_NAME("AUDIO") .init = audiod_init, .reset = audiod_reset, .open = audiod_open, @@ -137,83 +137,83 @@ static usbd_class_driver_t const _usbd_driver[] = .control_complete = audiod_control_complete, .xfer_cb = audiod_xfer_cb, .sof = NULL -}, -#endif + }, + #endif #if CFG_TUD_MIDI { - DRIVER_NAME("MIDI") - .init = midid_init, - .open = midid_open, - .reset = midid_reset, - .control_xfer_cb = midid_control_xfer_cb, - .xfer_cb = midid_xfer_cb, - .sof = NULL + DRIVER_NAME("MIDI") + .init = midid_init, + .open = midid_open, + .reset = midid_reset, + .control_xfer_cb = midid_control_xfer_cb, + .xfer_cb = midid_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_VENDOR { - DRIVER_NAME("VENDOR") - .init = vendord_init, - .reset = vendord_reset, - .open = vendord_open, - .control_xfer_cb = tud_vendor_control_request_cb, - .control_complete = tud_vendor_control_complete_cb, - .xfer_cb = vendord_xfer_cb, - .sof = NULL + DRIVER_NAME("VENDOR") + .init = vendord_init, + .reset = vendord_reset, + .open = vendord_open, + .control_xfer_cb = tud_vendor_control_request_cb, + .control_complete = tud_vendor_control_complete_cb, + .xfer_cb = vendord_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_USBTMC { - DRIVER_NAME("TMC") - .init = usbtmcd_init_cb, - .reset = usbtmcd_reset_cb, - .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_request_cb, - .control_complete = usbtmcd_control_complete_cb, - .xfer_cb = usbtmcd_xfer_cb, - .sof = NULL + DRIVER_NAME("TMC") + .init = usbtmcd_init_cb, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_xfer_cb = usbtmcd_control_request_cb, + .control_complete = usbtmcd_control_complete_cb, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_DFU_RT { - DRIVER_NAME("DFU-RT") - .init = dfu_rtd_init, - .reset = dfu_rtd_reset, - .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_request, - .control_complete = dfu_rtd_control_complete, - .xfer_cb = dfu_rtd_xfer_cb, - .sof = NULL + DRIVER_NAME("DFU-RT") + .init = dfu_rtd_init, + .reset = dfu_rtd_reset, + .open = dfu_rtd_open, + .control_xfer_cb = dfu_rtd_control_request, + .control_complete = dfu_rtd_control_complete, + .xfer_cb = dfu_rtd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_NET { - DRIVER_NAME("NET") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_xfer_cb = netd_control_request, - .control_complete = netd_control_complete, - .xfer_cb = netd_xfer_cb, - .sof = NULL, + DRIVER_NAME("NET") + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_xfer_cb = netd_control_request, + .control_complete = netd_control_complete, + .xfer_cb = netd_xfer_cb, + .sof = NULL, }, #endif #if CFG_TUD_BTH { - DRIVER_NAME("BTH") - .init = btd_init, - .reset = btd_reset, - .open = btd_open, - .control_xfer_cb = btd_control_request, - .control_complete = btd_control_complete, - .xfer_cb = btd_xfer_cb, - .sof = NULL + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_xfer_cb = btd_control_request, + .control_complete = btd_control_complete, + .xfer_cb = btd_xfer_cb, + .sof = NULL }, #endif }; -- cgit v1.3.1 From 7df979673db0e2e268c576a8a4d738069cf5e32b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:38:56 +0700 Subject: migrate usbtmc device to new control xfer cb --- src/class/usbtmc/usbtmc_device.c | 17 +++++++---------- src/class/usbtmc/usbtmc_device.h | 3 +-- src/device/usbd.c | 3 +-- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'src/device') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index bc5f23f42..88776d169 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -575,7 +575,13 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint return false; } -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) { +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // nothing to do with DATA and ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (CFG_TUD_USBTMC_ENABLE_488) @@ -855,13 +861,4 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(false); } -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request) -{ - (void)rhport; - //------------- Class Specific Request -------------// - TU_ASSERT (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - return true; -} - #endif /* CFG_TUD_TSMC */ diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index a6b5e4cca..622800315 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -111,8 +111,7 @@ bool tud_usbtmc_start_bus_read(void); uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); void usbtmcd_reset_cb(uint8_t rhport); bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); void usbtmcd_init_cb(void); /************************************************************ diff --git a/src/device/usbd.c b/src/device/usbd.c index bea41b592..1d328ad5f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -171,8 +171,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_request_cb, - .control_complete = usbtmcd_control_complete_cb, + .control_xfer_cb = usbtmcd_control_xfer_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 3cc1979adbfb8f91ce4a938573e729e8b80d4627 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:42:32 +0700 Subject: migrate dfu runtime device to new control xfer cb --- src/class/dfu/dfu_rt_device.c | 15 ++++++--------- src/class/dfu/dfu_rt_device.h | 3 +-- src/device/usbd.c | 3 +-- 3 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index d4c3ecb62..38644615a 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -85,17 +85,14 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui return drv_len; } -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - (void) rhport; - (void) request; + // nothing to do with DATA and ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; - // nothing to do - return true; -} - -bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request) -{ TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 91ead88c6..643e25d8f 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -66,8 +66,7 @@ TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb conventi void dfu_rtd_init(void); void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -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_control_xfer_cb(uint8_t rhport, uint8_t stage, 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 diff --git a/src/device/usbd.c b/src/device/usbd.c index 1d328ad5f..b629a1ff8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -183,8 +183,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_request, - .control_complete = dfu_rtd_control_complete, + .control_xfer_cb = dfu_rtd_control_xfer_cb, .xfer_cb = dfu_rtd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 61ad7bef7140d8e06343a5ce4e15d3a2fe7f158a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:50:11 +0700 Subject: migrate vendor device to new control xfer cb --- examples/device/webusb_serial/src/main.c | 19 +++++++------------ src/device/usbd.c | 3 +-- src/device/usbd.h | 4 ---- 3 files changed, 8 insertions(+), 18 deletions(-) (limited to 'src/device') diff --git a/examples/device/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c index e1a098048..9309bbf6e 100644 --- a/examples/device/webusb_serial/src/main.c +++ b/examples/device/webusb_serial/src/main.c @@ -143,9 +143,14 @@ void tud_resume_cb(void) // WebUSB use vendor class //--------------------------------------------------------------------+ -// Invoked when received VENDOR control request -bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { + // nothing to with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP ) return true; + switch (request->bRequest) { case VENDOR_REQUEST_WEBUSB: @@ -194,16 +199,6 @@ bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const return true; } -// Invoked when DATA Stage of VENDOR's request is complete -bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - (void) request; - - // nothing to do - return true; -} - void webserial_task(void) { if ( web_serial_connected ) diff --git a/src/device/usbd.c b/src/device/usbd.c index b629a1ff8..9773245c8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -158,8 +158,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = vendord_init, .reset = vendord_reset, .open = vendord_open, - .control_xfer_cb = tud_vendor_control_request_cb, - .control_complete = tud_vendor_control_complete_cb, + .control_xfer_cb = tud_vendor_control_xfer_cb, .xfer_cb = vendord_xfer_cb, .sof = NULL }, diff --git a/src/device/usbd.h b/src/device/usbd.h index cf7e9f0db..ef248e4ca 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -127,10 +127,6 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -// Invoked when vendor control request is complete -TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); - - //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ -- cgit v1.3.1 From 9f853685ae06c4eac03b277d61440de28d5ba41a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:13:58 +0700 Subject: migrate bth device to new control xfer cb --- src/class/bth/bth_device.c | 54 +++++++++++++++++++++++----------------------- src/class/bth/bth_device.h | 11 +++++----- src/device/usbd.c | 3 +-- 3 files changed, 33 insertions(+), 35 deletions(-) (limited to 'src/device') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 252e20e37..c63b994e2 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -186,43 +186,43 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ return drv_len; } -bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request) +bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { (void)rhport; - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); - - return true; -} - -bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request) -{ - (void)rhport; - - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { - // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + if ( stage == CONTROL_STAGE_SETUP ) { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) { - // TODO: Set interface it would involve changing size of endpoint size + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); } - else + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { - // HCI command packet for Primary Controller function in a composite device - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); } - else return false; - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); + return true; } bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index 5e5468084..1b90d0915 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -96,12 +96,11 @@ bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void btd_init (void); -void btd_reset (uint8_t rhport); -uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 9773245c8..5639e1354 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -207,8 +207,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = btd_init, .reset = btd_reset, .open = btd_open, - .control_xfer_cb = btd_control_request, - .control_complete = btd_control_complete, + .control_xfer_cb = btd_control_xfer_cb, .xfer_cb = btd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From c4bc8b25613a74f932202047751d4cc73c0254bd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:59:33 +0700 Subject: migrate net device to new control xfer cb --- src/class/net/net_device.c | 177 ++++++++++++++++++++++----------------------- src/class/net/net_device.h | 13 ++-- src/device/usbd.c | 3 +- 3 files changed, 94 insertions(+), 99 deletions(-) (limited to 'src/device') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 3a45a9b99..ce1131223 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -220,26 +220,6 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send nonsense DATA) -bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - - // Handle RNDIS class control OUT only - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.direction == TUSB_DIR_OUT && - _netd_itf.itf_num == request->wIndex) - { - if ( !_netd_itf.ecm_mode ) - { - rndis_class_set_handler(notify.rndis_buf, request->wLength); - } - } - - return true; -} - static void ecm_report(bool nc) { notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; @@ -247,99 +227,116 @@ static void ecm_report(bool nc) netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - switch ( request->bmRequestType_bit.type ) + if ( stage == CONTROL_STAGE_SETUP ) { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); + case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); - } - break; + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } + break; - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; + case TUSB_REQ_SET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - // ACM-ECM only: qequest to enable/disable network activities - TU_VERIFY(_netd_itf.ecm_mode); + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); - _netd_itf.itf_data_alt = req_alt; + _netd_itf.itf_data_alt = req_alt; - if ( _netd_itf.itf_data_alt ) - { - // TODO since we don't actually close endpoint - // hack here to not re-open it - if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + if ( _netd_itf.itf_data_alt ) + { + // TODO since we don't actually close endpoint + // hack here to not re-open it + if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + { + TU_ASSERT(_netd_itf.ecm_desc_epdata); + TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + // TODO should be merge with RNDIS's after endpoint opened + // Also should have opposite callback for application to disable network !! + tud_network_init_cb(); + can_xmit = true; // we are ready to transmit a packet + tud_network_recv_renew(); // prepare for incoming packets + } + }else { - TU_ASSERT(_netd_itf.ecm_desc_epdata); - TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - - // TODO should be merge with RNDIS's after endpoint opened - // Also should have opposite callback for application to disable network !! - tud_network_init_cb(); - can_xmit = true; // we are ready to transmit a packet - tud_network_recv_renew(); // prepare for incoming packets + // TODO close the endpoint pair + // For now pretend that we did, this should have no harm since host won't try to + // communicate with the endpoints again + // _netd_itf.ep_in = _netd_itf.ep_out = 0 } - }else - { - // TODO close the endpoint pair - // For now pretend that we did, this should have no harm since host won't try to - // communicate with the endpoints again - // _netd_itf.ep_in = _netd_itf.ep_out = 0 + + tud_control_status(rhport, request); } + break; - tud_control_status(rhport, request); + // unsupported request + default: return false; } - break; + break; - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (_netd_itf.itf_num == request->wIndex); + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (_netd_itf.itf_num == request->wIndex); - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + if (_netd_itf.ecm_mode) { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } } else { - tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } } - } - break; + break; - // unsupported request - default: return false; + // unsupported request + default: return false; + } + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // Handle RNDIS class control OUT only + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.direction == TUSB_DIR_OUT && + _netd_itf.itf_num == request->wIndex) + { + if ( !_netd_itf.ecm_mode ) + { + rndis_class_set_handler(notify.rndis_buf, request->wLength); + } + } } return true; diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 795b2f9e3..38c47d647 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,13 +73,12 @@ void tud_network_xmit(void *ref, uint16_t arg); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); +void netd_init (void); +void netd_reset (uint8_t rhport); +uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 5639e1354..4d2b44005 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -194,8 +194,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = netd_init, .reset = netd_reset, .open = netd_open, - .control_xfer_cb = netd_control_request, - .control_complete = netd_control_complete, + .control_xfer_cb = netd_control_xfer_cb, .xfer_cb = netd_xfer_cb, .sof = NULL, }, -- cgit v1.3.1 From cebb375eac0d560b53341012aa69ae2a54f4fbaf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 17:20:05 +0700 Subject: migrate audio device to new control xfer cb --- src/class/audio/audio_device.c | 18 ++++++++++++++++-- src/class/audio/audio_device.h | 9 ++++----- src/device/usbd.c | 3 +-- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2c8ba300d..8581925e4 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -989,7 +989,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Invoked when class request DATA stage is finished. // return false to stall control EP (e.g Host send non-sense DATA) -bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) @@ -1065,7 +1065,7 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re // Handle class control request // return false to stall control endpoint (e.g unsupported request) -bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { (void) rhport; @@ -1175,6 +1175,20 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req return false; } +bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + return audiod_control_request(rhport, request); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + return audiod_control_complete(rhport, request); + } + + return true; +} + bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d86232720..5061501ce 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -384,11 +384,10 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t b //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 4d2b44005..15174f2ab 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -133,8 +133,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = audiod_init, .reset = audiod_reset, .open = audiod_open, - .control_xfer_cb = audiod_control_request, - .control_complete = audiod_control_complete, + .control_xfer_cb = audiod_control_xfer_cb, .xfer_cb = audiod_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From e4144d8b47b438ff57a09c54de49e7e6c68d9343 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 17:21:01 +0700 Subject: remove control_complete --- src/device/usbd_pvt.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 57331041b..212c3a202 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -47,7 +47,6 @@ typedef struct void (* reset ) (uint8_t rhport); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; -- cgit v1.3.1 From 148eea141798cd9aefea49aaedc06c885ab7a3aa Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Nov 2020 21:49:12 +0700 Subject: add tud_connected() which return true as long as we receive the very first SETUP packet from host. --- src/device/usbd.c | 7 ++++++- src/device/usbd.h | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 15174f2ab..4ecc2a2f9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -326,9 +326,14 @@ tusb_speed_t tud_speed_get(void) return (tusb_speed_t) _usbd_dev.speed; } +bool tud_connected(void) +{ + return _usbd_dev.connected; +} + bool tud_mounted(void) { - return _usbd_dev.cfg_num ? 1 : 0; + return _usbd_dev.cfg_num ? true : false; } bool tud_suspended(void) diff --git a/src/device/usbd.h b/src/device/usbd.h index ef248e4ca..360567743 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -56,6 +56,9 @@ extern void dcd_int_handler(uint8_t rhport); // Get current bus speed tusb_speed_t tud_speed_get(void); +// Check if device is connected (may not mounted/configured yet) +bool tud_connected(void); + // Check if device is connected and configured bool tud_mounted(void); -- cgit v1.3.1 From b3c0d417ef2b2d2ff3d00b7cdf623436ec7abf97 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 20 Dec 2020 23:06:32 +0100 Subject: Fix error if "Required Prototype" is selected. Signed-off-by: HiFiPhile --- src/class/msc/msc_device.c | 348 +++++++++++++++++++++++---------------------- src/common/tusb_compiler.h | 1 + src/device/usbd_control.c | 8 ++ 3 files changed, 184 insertions(+), 173 deletions(-) (limited to 'src/device') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a4ea5f6fb..194f4d3cb 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -71,6 +71,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); @@ -223,179 +224,6 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t return true; } -// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) -// In case of a failed status, sense key must be set for reason of failure -int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) -{ - (void) bufsize; // TODO refractor later - int32_t resplen; - - switch ( scsi_cmd[0] ) - { - case SCSI_CMD_TEST_UNIT_READY: - resplen = 0; - if ( !tud_msc_test_unit_ready_cb(lun) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - break; - - case SCSI_CMD_START_STOP_UNIT: - resplen = 0; - - if (tud_msc_start_stop_cb) - { - scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; - if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - } - break; - - case SCSI_CMD_READ_CAPACITY_10: - { - uint32_t block_count; - uint32_t block_size; - uint16_t block_size_u16; - - tud_msc_capacity_cb(lun, &block_count, &block_size_u16); - block_size = (uint32_t) block_size_u16; - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - scsi_read_capacity10_resp_t read_capa10; - - read_capa10.last_lba = tu_htonl(block_count-1); - read_capa10.block_size = tu_htonl(block_size); - - resplen = sizeof(read_capa10); - memcpy(buffer, &read_capa10, resplen); - } - } - break; - - case SCSI_CMD_READ_FORMAT_CAPACITY: - { - scsi_read_format_capacity_data_t read_fmt_capa = - { - .list_length = 8, - .block_num = 0, - .descriptor_type = 2, // formatted media - .block_size_u16 = 0 - }; - - uint32_t block_count; - uint16_t block_size; - - tud_msc_capacity_cb(lun, &block_count, &block_size); - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - read_fmt_capa.block_num = tu_htonl(block_count); - read_fmt_capa.block_size_u16 = tu_htons(block_size); - - resplen = sizeof(read_fmt_capa); - memcpy(buffer, &read_fmt_capa, resplen); - } - } - break; - - case SCSI_CMD_INQUIRY: - { - scsi_inquiry_resp_t inquiry_rsp = - { - .is_removable = 1, - .version = 2, - .response_data_format = 2, - }; - - // vendor_id, product_id, product_rev is space padded string - memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); - memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); - memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - - tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - - resplen = sizeof(inquiry_rsp); - memcpy(buffer, &inquiry_rsp, resplen); - } - break; - - case SCSI_CMD_MODE_SENSE_6: - { - scsi_mode_sense6_resp_t mode_resp = - { - .data_len = 3, - .medium_type = 0, - .write_protected = false, - .reserved = 0, - .block_descriptor_len = 0 // no block descriptor are included - }; - - bool writable = true; - if (tud_msc_is_writable_cb) { - writable = tud_msc_is_writable_cb(lun); - } - mode_resp.write_protected = !writable; - - resplen = sizeof(mode_resp); - memcpy(buffer, &mode_resp, resplen); - } - break; - - case SCSI_CMD_REQUEST_SENSE: - { - scsi_sense_fixed_resp_t sense_rsp = - { - .response_code = 0x70, - .valid = 1 - }; - - sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - - sense_rsp.sense_key = _mscd_itf.sense_key; - sense_rsp.add_sense_code = _mscd_itf.add_sense_code; - sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; - - resplen = sizeof(sense_rsp); - memcpy(buffer, &sense_rsp, resplen); - - // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); - } - break; - - default: resplen = -1; break; - } - - return resplen; -} - bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { mscd_interface_t* p_msc = &_mscd_itf; @@ -640,6 +468,180 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t /*------------------------------------------------------------------*/ /* SCSI Command Process *------------------------------------------------------------------*/ + +// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) +// In case of a failed status, sense key must be set for reason of failure +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) +{ + (void) bufsize; // TODO refractor later + int32_t resplen; + + switch ( scsi_cmd[0] ) + { + case SCSI_CMD_TEST_UNIT_READY: + resplen = 0; + if ( !tud_msc_test_unit_ready_cb(lun) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + break; + + case SCSI_CMD_START_STOP_UNIT: + resplen = 0; + + if (tud_msc_start_stop_cb) + { + scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + } + break; + + case SCSI_CMD_READ_CAPACITY_10: + { + uint32_t block_count; + uint32_t block_size; + uint16_t block_size_u16; + + tud_msc_capacity_cb(lun, &block_count, &block_size_u16); + block_size = (uint32_t) block_size_u16; + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + scsi_read_capacity10_resp_t read_capa10; + + read_capa10.last_lba = tu_htonl(block_count-1); + read_capa10.block_size = tu_htonl(block_size); + + resplen = sizeof(read_capa10); + memcpy(buffer, &read_capa10, resplen); + } + } + break; + + case SCSI_CMD_READ_FORMAT_CAPACITY: + { + scsi_read_format_capacity_data_t read_fmt_capa = + { + .list_length = 8, + .block_num = 0, + .descriptor_type = 2, // formatted media + .block_size_u16 = 0 + }; + + uint32_t block_count; + uint16_t block_size; + + tud_msc_capacity_cb(lun, &block_count, &block_size); + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + read_fmt_capa.block_num = tu_htonl(block_count); + read_fmt_capa.block_size_u16 = tu_htons(block_size); + + resplen = sizeof(read_fmt_capa); + memcpy(buffer, &read_fmt_capa, resplen); + } + } + break; + + case SCSI_CMD_INQUIRY: + { + scsi_inquiry_resp_t inquiry_rsp = + { + .is_removable = 1, + .version = 2, + .response_data_format = 2, + }; + + // vendor_id, product_id, product_rev is space padded string + memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); + memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); + memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); + + tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); + + resplen = sizeof(inquiry_rsp); + memcpy(buffer, &inquiry_rsp, resplen); + } + break; + + case SCSI_CMD_MODE_SENSE_6: + { + scsi_mode_sense6_resp_t mode_resp = + { + .data_len = 3, + .medium_type = 0, + .write_protected = false, + .reserved = 0, + .block_descriptor_len = 0 // no block descriptor are included + }; + + bool writable = true; + if (tud_msc_is_writable_cb) { + writable = tud_msc_is_writable_cb(lun); + } + mode_resp.write_protected = !writable; + + resplen = sizeof(mode_resp); + memcpy(buffer, &mode_resp, resplen); + } + break; + + case SCSI_CMD_REQUEST_SENSE: + { + scsi_sense_fixed_resp_t sense_rsp = + { + .response_code = 0x70, + .valid = 1 + }; + + sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; + + sense_rsp.sense_key = _mscd_itf.sense_key; + sense_rsp.add_sense_code = _mscd_itf.add_sense_code; + sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; + + resplen = sizeof(sense_rsp); + memcpy(buffer, &sense_rsp, resplen); + + // Clear sense data after copy + tud_msc_set_sense(lun, 0, 0, 0); + } + break; + + default: resplen = -1; break; + } + + return resplen; +} + static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { msc_cbw_t const * p_cbw = &p_msc->cbw; diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 505542078..22c8366ab 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -102,6 +102,7 @@ #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) #elif defined(__ICCARM__) + #include #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index bb631320a..8ed0ad1c0 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -140,6 +140,14 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // USBD API //--------------------------------------------------------------------+ +//--------------------------------------------------------------------+ +// Prototypes +//--------------------------------------------------------------------+ +void usbd_control_reset(void); +void usbd_control_set_request(tusb_control_request_t const *request); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void usbd_control_reset(void) { tu_varclr(&_ctrl_xfer); -- cgit v1.3.1 From c8dc7f807f5f954a0f1ed12b15454018559115cc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Dec 2020 11:48:48 +0100 Subject: Fix more warnings. Signed-off-by: HiFiPhile --- src/device/usbd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 4ecc2a2f9..791d533ae 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -517,7 +517,7 @@ void tud_task (void) TU_ASSERT(driver, ); TU_LOG2(" %s xfer callback\r\n", driver->name); - driver->xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -933,6 +933,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_STRING: + { TU_LOG2(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user @@ -941,6 +942,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); + } break; case TUSB_DESC_DEVICE_QUALIFIER: -- cgit v1.3.1 From 09d8ead4b86049260dd6ee7e61d137b6bdccaa28 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 4 Jan 2021 12:02:08 +0100 Subject: Start changes - not yet finished --- src/device/usbd.c | 29 ++++++++++++++++++++++++ src/device/usbd_pvt.h | 3 +++ src/portable/st/synopsys/dcd_synopsys.c | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 791d533ae..55e76bb66 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1188,6 +1188,35 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return + // and usbd task can preempt and clear the busy + _usbd_dev.ep_status[epnum][dir].busy = true; + + if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // DCD error, mark endpoint as ready to allow next transfer + _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 212c3a202..de2f37281 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -72,6 +72,9 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Submit a usb ISO transfer by use of a FIFO (ring buffer) +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); + // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 35c814460..0aee6a919 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -28,6 +28,7 @@ */ #include "tusb_option.h" +#include "tusb_fifo.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on @@ -134,6 +135,7 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { uint8_t * buffer; + tu_fifo_t * ff; uint16_t total_len; uint16_t max_size; uint8_t interval; @@ -659,6 +661,38 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; // Indicates a FIFO shall be used + xfer->ff = ff; + xfer->total_len = total_bytes; + + // EP0 can only handle one packet + if(epnum == 0) { + ep0_pending[dir] = total_bytes; + // Schedule the first transaction for EP0 transfer + edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); + return true; + } + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t const short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if(short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + + return true; +} + static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) { (void) rhport; @@ -849,6 +883,9 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ { xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + + // TODO: TAKE CARE OF ISO FIFO! + // Read packet off RxFIFO read_fifo_packet(rhport, xfer->buffer, bcnt); @@ -960,6 +997,8 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT break; } + // TODO: TAKE CARE OF ISO FIFO! + // Push packet to Tx-FIFO write_fifo_packet(rhport, n, xfer->buffer, packet_size); -- cgit v1.3.1 From 6e6e6265e4feb797ddbd835dc1bee865d04219e6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 22:34:36 +0700 Subject: use dcd_event_bus_reset() with speed to replace bus_signal --- src/device/usbd.c | 18 ++++++++++++++++++ src/portable/dialog/da146xx/dcd_da146xx.c | 7 +++---- src/portable/espressif/esp32s2/dcd_esp32s2.c | 1 - src/portable/microchip/samd/dcd_samd.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 3 +-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nxp/khci/dcd_khci.c | 2 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 9 --------- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 6 +++--- src/portable/valentyusb/eptri/dcd_eptri.c | 2 +- test/test/device/msc/test_msc_device.c | 2 +- test/test/support/tusb_config.h | 6 +++--- 17 files changed, 39 insertions(+), 33 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 791d533ae..f6b00563d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1103,6 +1103,24 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + if (TUSB_XFER_ISOCHRONOUS == desc_ep->bmAttributes.xfer) + { + TU_ASSERT(desc_ep->wMaxPacketSize.size <= (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023)); + } + else + { + uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 512 : 64); + + if (TUSB_XFER_BULK == desc_ep->bmAttributes.xfer) + { + // Bulk must be EXACTLY 512/64 bytes + TU_ASSERT(desc_ep->wMaxPacketSize.size == max_epsize); + }else + { + TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + } + } + return dcd_edpt_open(rhport, desc_ep); } diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 42ba867d7..59f728d08 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -664,7 +664,7 @@ static void handle_bus_reset(void) (void)USB->USB_ALTEV_REG; _dcd.in_reset = true; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); USB->USB_DMA_CTRL_REG = 0; USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | @@ -821,14 +821,13 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { + (void)rhport; + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); uint8_t iso_mask = 0; - - (void)rhport; - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 1023); TU_ASSERT(epnum < EP_MAX); xfer->max_packet_size = desc_edpt->wMaxPacketSize.size; diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index cd66af805..703841759 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -252,7 +252,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 68a15672a..3cff92fcd 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -387,7 +387,7 @@ void dcd_int_handler (uint8_t rhport) USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTFLAG_WAKEUP | USB_DEVICE_INTFLAG_SUSPEND; bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } // Handle SETUP packet diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 2b64df50b..2f9f1097f 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -338,7 +338,7 @@ void dcd_int_handler(uint8_t rhport) if (intr_status & UDP_ISR_ENDBUSRES_Msk) { bus_reset(); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } // SOF diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index b85d3776f..d9fe2b6ae 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -533,7 +533,7 @@ void dcd_int_handler(uint8_t rhport) if ( int_status & USBD_INTEN_USBRESET_Msk ) { bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } // ISOIN: Data was moved to endpoint buffer, client will be notified in SOF diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 1a0007d8a..dc48e54cc 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -329,8 +329,7 @@ void dcd_int_handler(uint8_t rhport) USBD->ATTR |= USBD_ATTR_USB_EN_Msk | USBD_ATTR_PHY_EN_Msk; bus_reset(); - - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } if(state & USBD_STATE_SUSPEND) diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index af7fee8b0..c9ead6de0 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -340,7 +340,7 @@ void dcd_int_handler(uint8_t rhport) bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } if(state & USBD_ATTR_SUSPEND_Msk) diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 8357bf2b8..519b8fb7b 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -224,7 +224,7 @@ static void process_bus_reset(uint8_t rhport) _dcd.addr = 0; prepare_next_setup_packet(rhport); KHCI->CTL &= ~USB_CTL_ODDRST_MASK; - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } static void process_bus_inactive(uint8_t rhport) diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 39c5e6638..7d867aaba 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -471,7 +471,7 @@ static void bus_event_isr(uint8_t rhport) if (dev_status & SIE_DEV_STATUS_RESET_MASK) { bus_reset(); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } if (dev_status & SIE_DEV_STATUS_CONNECT_CHANGE_MASK) diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 3d1420c65..e4d92458c 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -243,7 +243,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) (void) rhport; // TODO not support ISO yet - if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) return false; + TU_VERIFY(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// uint8_t ep_id = ep_addr2id(p_endpoint_desc->bEndpointAddress); @@ -357,7 +357,7 @@ void dcd_int_handler(uint8_t rhport) if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset { bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } if (cmd_stat & CMDSTAT_CONNECT_CHANGE_MASK) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dc125a758..18f0bc8e1 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -547,7 +547,7 @@ void dcd_int_handler(uint8_t rhport) { // USBRST is start of reset. clear_istr_bits(USB_ISTR_RESET); dcd_handle_bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? } diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 227c9ee61..4e385f691 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -565,15 +565,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) TU_ASSERT(epnum < EP_MAX); - if (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) - { - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 1024 : 1023)); - } - else - { - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 512 : 64)); - } - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; xfer->interval = desc_edpt->bInterval; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index ad71e1168..e08c3536a 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -232,9 +232,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - // Unsupported endpoint numbers/size or type (Iso not supported. Control + // Unsupported endpoint numbers or type (Iso not supported. Control // not supported on nonzero endpoints). - if((desc_edpt->wMaxPacketSize.size > 64) || (epnum > 7) || \ + if( (epnum > 7) || \ (desc_edpt->bmAttributes.xfer == 0) || \ (desc_edpt->bmAttributes.xfer == 1)) { return false; @@ -572,7 +572,7 @@ void dcd_int_handler(uint8_t rhport) { case USBVECINT_RSTR: bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); break; // Clear the (hardware-enforced) NAK on EP 0 after a SETUP packet diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index d670dd38e..b68f04faa 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -332,7 +332,7 @@ static void dcd_reset(void) usb_out_ev_enable_write(1); usb_setup_ev_enable_write(3); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } // Initializes the USB peripheral for device mode and enables it. diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index a01ef153a..00bb86ccf 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -202,7 +202,7 @@ void setUp(void) tusb_init(); } - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, false); + dcd_event_bus_reset(rhport, TUSB_SPEED_HIGH, false); tud_task(); } diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 8cd99eaae..d80e144da 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -86,8 +86,8 @@ //------------- CDC -------------// // FIFO size of CDC TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 +#define CFG_TUD_CDC_RX_BUFSIZE 512 +#define CFG_TUD_CDC_TX_BUFSIZE 512 //------------- MSC -------------// @@ -97,7 +97,7 @@ //------------- HID -------------// // Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_EP_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 64 #ifdef __cplusplus } -- cgit v1.3.1 From 84c383061f4af9e0fa66326a09c6c332920df6a7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:08:59 +0100 Subject: Add tusb_fifo.h header file to dcd.h --- src/device/dcd.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index b7e5a8da0..1b2d2b941 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -32,6 +32,7 @@ #define _TUSB_DCD_H_ #include "common/tusb_common.h" +#include "common/tusb_fifo.h" #ifdef __cplusplus extern "C" { @@ -133,6 +134,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 2284db1fb5d99c91b31ef7176ea04a8a01b3206a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:14:17 +0100 Subject: Add usbd_edpt_ISO_xfer() --- src/device/usbd.c | 6 +++--- src/device/usbd_pvt.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 05acb7019..e0546ac39 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,12 +1206,12 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, tu_fifo_count(ff)); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); @@ -1220,7 +1220,7 @@ bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff, total_bytes) ) + if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff) ) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index de2f37281..4ae55aecc 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -72,8 +72,8 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Submit a usb ISO transfer by use of a FIFO (ring buffer) -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +// Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. -- cgit v1.3.1 From 56edc2b2618e542b73c284a3116cf88fd70303e2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 19 Jan 2021 10:50:19 +0100 Subject: Change names from edpt_ISO_xfer to edpt_iso_xfer --- src/class/audio/audio_device.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 4 ++-- src/device/usbd_pvt.h | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8dd1a8fef..616760223 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -537,7 +537,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); - TU_VERIFY(usbd_edpt_ISO_xfer(rhport, audio->ep_in, &audio->epin_ff)); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->epin_ff)); diff --git a/src/device/dcd.h b/src/device/dcd.h index 1b2d2b941..30224e16e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -135,7 +135,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index e0546ac39..c2b5b65d1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,7 +1206,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1220,7 +1220,7 @@ bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff) ) + if ( dcd_edpt_iso_xfer(rhport, ep_addr, ff) ) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 4ae55aecc..1d24957a9 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5f9dc267b..90fcd51e7 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -670,7 +670,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); -- cgit v1.3.1 From 93ec6f3735b30193f368458cf10d1af6c833c230 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 19 Jan 2021 17:10:08 +0100 Subject: Adjust #include "dcd.h" to "device/dcd.h", the same for usbd.h in usbd.c --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index c2b5b65d1..4e18df757 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -29,9 +29,9 @@ #if TUSB_OPT_DEVICE_ENABLED #include "tusb.h" -#include "usbd.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" -#include "dcd.h" +#include "device/dcd.h" #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 -- cgit v1.3.1 From 84406f1654ca757ecd7294f4b98b56146583be49 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 31 Jan 2021 19:08:23 +0100 Subject: Rework audio driver --- src/class/audio/audio_device.c | 410 ++++++++++++++++---------------- src/class/audio/audio_device.h | 317 +++++++++++++++--------- src/device/dcd.h | 12 +- src/device/usbd.c | 10 +- src/device/usbd_pvt.h | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 8 +- 6 files changed, 419 insertions(+), 340 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 616760223..07bfe6158 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -32,8 +32,6 @@ * * */ -// TODO: Rename CFG_TUD_AUDIO_EPSIZE_IN to CFG_TUD_AUDIO_EP_IN_BUFFER_SIZE - #include "tusb_option.h" #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) @@ -49,30 +47,17 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT -#define CFG_TUD_AUDIO_TX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_TX -#endif -#endif - -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#ifndef CFG_TUD_AUDIO_RX_FIFO_COUNT -#define CFG_TUD_AUDIO_RX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_RX -#endif -#endif - typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EPSIZE_IN - uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint16_t epin_buf_cnt; // Count filling status of EP in buffer - this is a shared state currently and is intended to be removed once EP buffers can be implemented as FIFOs! +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + uint8_t ep_in; // TX audio data EP. uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE uint8_t ep_out; // Incoming (into uC) audio data EP. uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) @@ -89,49 +74,60 @@ typedef struct #if CFG_TUD_AUDIO_N_AS_INT uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif + /*------------- From this point, data is not cleared by bus reset -------------*/ // Buffer for control requests CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; - // FIFO -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_TX_FIFO_COUNT]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_TX_FIFO_COUNT][CFG_TUD_AUDIO_TX_FIFO_SIZE]; + // EP Transfer buffers and FIFOs +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; + tu_fifo_t ep_out_ff; + #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_TX_FIFO_COUNT]; + osal_mutex_def_t ep_out_ff_mutex; #endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#endif + #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_RX_FIFO_COUNT]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_RX_FIFO_COUNT][CFG_TUD_AUDIO_RX_FIFO_SIZE]; +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; + tu_fifo_t ep_in_ff; + #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_RX_FIFO_COUNT]; + osal_mutex_def_t ep_in_ff_mutex; #endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - tu_fifo_t int_ctr_ff; - CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; + // Support FIFOs +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t int_ctr_ff_mutex; + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif - // Endpoint Transfer buffers -#if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif - #endif -#if CFG_TUD_AUDIO_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) - tu_fifo_t epin_ff; +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t int_ctr_ff_mutex; +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -149,11 +145,11 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio); #endif @@ -167,34 +163,23 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); bool tud_audio_n_mounted(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_AUDIO); audiod_interface_t* audio = &_audiod_itf[itf]; -#if CFG_TUD_AUDIO_EPSIZE_OUT - if (audio->ep_out == 0) - { - return false; - } +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + if (audio->ep_out == 0) return false; #endif -#if CFG_TUD_AUDIO_EPSIZE_IN - if (audio->ep_in == 0) - { - return false; - } +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + if (audio->ep_in == 0) return false; #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) - { - return false; - } + if (audio->ep_int_ctr == 0) return false; #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) - { - return false; - } + if (audio->ep_fb == 0) return false; #endif return true; @@ -204,43 +189,58 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +uint16_t tud_audio_n_available(uint8_t itf) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_count(&_audiod_itf[itf].ep_out_ff); } -uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_read_n(&_audiod_itf[itf].ep_out_ff, buffer, bufsize); } -void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) +void tud_audio_n_clear_ep_out_ff(uint8_t itf) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); - tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); } -#else -uint16_t tud_audio_n_available(uint8_t itf) + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +// Delete all content in the support RX FIFOs +void tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - return tu_fifo_count(&_audiod_itf[itf].rx_ff[0]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } -uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[0], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); } -void tud_audio_n_read_flush (uint8_t itf) +uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - tu_fifo_clear(&_audiod_itf[itf].rx_ff[0]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); } #endif + #endif + + + + + + + + + #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN uint16_t tud_audio_int_ctr_n_available(uint8_t itf) @@ -261,9 +261,9 @@ void tud_audio_int_ctr_n_read_flush (uint8_t itf) #endif // This function is called once something is received by USB and is responsible for decoding received stream into audio channels. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { @@ -281,7 +281,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! @@ -309,11 +309,11 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* return true; } -#endif //CFG_TUD_AUDIO_EPSIZE_OUT +#endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 +// The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_N_CHANNELS_RX > 1 static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { (void) rhport; @@ -365,13 +365,53 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize); return true; } -#endif // CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE +#endif // CFG_TUD_AUDIO_N_CHANNELS_RX > 1 +#endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_write_n(&_audiod_itf[itf].ep_in_ff, data, len); +} + +void tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); +} + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into EP SW FIFO +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + audiod_interface_t* audio = &_audiod_itf[itf]; + uint16_t n_bytes_copied; + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); + return n_bytes_copied; +} + +uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); + +uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX, ); + return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); +} +#endif + +#endif + + + + + + /** * \brief Write data to EP in buffer * @@ -383,50 +423,28 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ -#if CFG_TUD_AUDIO_EPSIZE_IN -#if !CFG_TUD_AUDIO_TX_FIFO_SIZE -/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } - - // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if audiod_tx_done_cb() is executed in between! - - // FOR SINGLE THREADED OPERATION: - // AS LONG AS THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + if (audio->p_desc == NULL) return 0; - // Determine free space - uint16_t free = CFG_TUD_AUDIO_EPSIZE_IN - audio->epin_buf_cnt; - - // Clip length if needed - if (len > free) len = free; - - // Write data - memcpy((void *) &audio->epin_buf[audio->epin_buf_cnt], data, len); - - audio->epin_buf_cnt += len; - - // Return number of bytes written - return len; + return tu_fifo_write_n(&audio->ep_in_ff, data, len); } -*/ #else -#if CFG_TUD_AUDIO_TX_FIFO_COUNT == 1 +#if CFG_TUD_AUDIO_N_CHANNELS_TX == 1 uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len) { + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) - { - return 0; - } - return tu_fifo_write_n(&audio->tx_ff[0], data, len); + return 0; } + return tu_fifo_write_n(&audio->tx_ff[0], data, len); } #else uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) @@ -471,11 +489,11 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_EPSIZE_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16_t * n_bytes_copied) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; @@ -488,10 +506,10 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP in buffer by use of tud_audio_n_write_ep_in_buffer(). + // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -526,30 +544,11 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } #endif - // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if tud_audio_n_write_ep_in_buffer() is executed in between! - - // THIS IS NOT SOLVED SO FAR! - - // FOR SINGLE THREADED OPERATION: - // THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT SO IT DOES NOT INTERRUPT tud_audio_n_write_ep_in_buffer()! AS LONG AS tud_audio_n_write_ep_in_buffer() IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + // Inform how many bytes will be copied + *n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); // Schedule transmit - // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); - - - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->epin_ff)); - - - - - - // Inform how many bytes were copied - *n_bytes_copied = audio->epin_buf_cnt; - - // Declare EP in buffer empty - audio->epin_buf_cnt = 0; - - // TO HERE + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, *n_bytes_copied)); // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, *n_bytes_copied, idxDriver, audio->ep_in, audio->altSetting[idxItf])); @@ -557,19 +556,18 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ return true; } -#endif //CFG_TUD_AUDIO_EPSIZE_IN +#endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { - // We encode directly into IN EP's buffer - abort if previous transfer not complete + // We encode directly into IN EP's FIFO - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE; - uint16_t nBytesToSend; uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) @@ -582,58 +580,47 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* } // Check if there is enough - if (nSamplesPerChannelToSend == 0) - { - audio->epin_buf_cnt = 0; - return true; - } + if (nSamplesPerChannelToSend == 0) return true; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); - nBytesToSend = nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Encode uint16_t cntSample; - uint8_t * pBuff = audio->epin_buf; -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 - uint8_t sample; -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 - uint16_t sample; -#else - uint32_t sample; -#endif - // TODO: Big endianess handling for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) { for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - // Get sample from buffer - tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); + // If 8, 16, or 32 bit values are to be copied +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE + tu_fifo_read_n_into_other_fifo(&audio->tx_ff[cntChannel], &audio->ep_in_ff, 0, CFG_TUD_AUDIO_TX_ITEMSIZE); +#else + // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO + uint32_t sample = 0; - // Put it into EP's buffer - Let alignment problems be handled by memcpy - memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + // Get sample from buffer + tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); - // Advance pointer - pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + tu_fifo_write_n(&audio->ep_in_ff, &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); +#endif } } - - audio->epin_buf_cnt = nBytesToSend; - return true; } #else static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { + // TODO GET RID OF SINGLE TX_FIFO! + // We encode directly into IN EP's buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]); - nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EPSIZE_IN); + nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE); // Check if there is enough if (nByteCount == 0) @@ -641,20 +628,17 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* return true; } - nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->epin_ff, 0, nByteCount); -// nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); - - audio->epin_buf_cnt = nByteCount; + nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->ep_in_ff, 0, nByteCount); return true; } -#endif // CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) +#endif // CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) -#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE +#endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) { uint8_t fb[4]; @@ -738,28 +722,34 @@ void audiod_init(void) { audiod_interface_t* audio = &_audiod_itf[i]; + // Initialize IN EP FIFO if required +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + // Initialize IN EP FIFO + tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#endif + // Initialize TX FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif } - - // Initialize IN EP FIFO - tu_fifo_config(&audio->epin_ff, &audio->epin_buf, CFG_TUD_AUDIO_EPSIZE_IN, 1, true); - #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif + + // Initialize OUT EP FIFO + tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); + } #endif @@ -781,19 +771,19 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EPSIZE_IN - tu_fifo_clear(&audio->epin_ff); +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { tu_fifo_clear(&audio->tx_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { tu_fifo_clear(&audio->rx_ff[cnt]); } @@ -891,7 +881,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; @@ -904,7 +894,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) { _audiod_itf[idxDriver].ep_out_as_intf_num = 0; @@ -945,7 +935,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address @@ -961,7 +951,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { @@ -973,7 +963,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -1242,7 +1232,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE // Data transmission of audio packet finished if (_audiod_itf[idxDriver].ep_in == ep_addr) @@ -1264,16 +1254,16 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) { // Save into buffer - do whatever has to be done - TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); // prepare for next transmission - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); return true; } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5061501ce..fdd4c15d4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -38,9 +38,11 @@ // Class Driver Configuration //--------------------------------------------------------------------+ +// All sizes are in bytes! + // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) #ifndef CFG_TUD_AUDIO_N_AS_INT -#define CFG_TUD_AUDIO_N_AS_INT 0 +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the descriptors! #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors @@ -48,20 +50,6 @@ #error You must define an audio class control request buffer size! #endif -// Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined). -// For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). -// For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. -// Further, it implements encoding and decoding of the individual channels (parameterized by the defines below). -// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and audio_tx_done_cb(). This, however, allows for optimizations. - -#ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel -#endif - -#ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel -#endif - // End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 #ifndef CFG_TUD_AUDIO_EPSIZE_IN #define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX @@ -71,29 +59,90 @@ #define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX #endif -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +// Software EP FIFO buffer sizes - must be >= EP SIZEs! +#if CFG_TUD_AUDIO_EPSIZE_IN +#ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX #endif - -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE -#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO_EPSIZE_OUT +#ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX #endif #endif +// General information of number of TX and/or RX channels - is used in case support FIFOs (see below) are used and can be used for descriptor definitions #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 +#endif + +// Use of TX/RX support FIFOs + +// Support FIFOs are not mandatory for the audio driver, rather they are intended to be of use in +// - TX case: CFG_TUD_AUDIO_N_CHANNELS_TX channels need to be encoded into one USB output stream (currently PCM type I is implemented) +// - RX case: CFG_TUD_AUDIO_N_CHANNELS_RX channels need to be decoded from a single USB input stream (currently PCM type I is implemented) +// +// This encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the +// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using +// - tud_audio_n_write() or +// - tud_audio_n_read(). +// To write/read to/from the support FIFOs use +// - tud_audio_n_write_support_ff() or +// - tud_audio_n_read_support_ff(). +// +// The encoding/decoding format type done is defined below. +// +// The encoding/decoding starts when the private callback functions +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// are invoked. If support FIFOs are used the corresponding encoding/decoding functions are called from there. +// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// if you want to get informed what happened. +// +// If you don't use the support FIFOs you may use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. +// +// If you need a different encoding which is not support so far implement it in the +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// functions. + +// Size of support FIFOs - if size > 0 there are as many FIFOs set up as TX/RX channels defined +#ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX +#endif + +#ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX +#endif + +// Enable/disable feedback EP (required for asynchronous RX applications) +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -// Audio data format types +// Audio interrupt control EP size - disabled if 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#endif +#endif + +// Audio data format types - look in audio.h for existing types +// Used in case support FIFOs are used #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif @@ -110,8 +159,8 @@ #define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif #ifndef CFG_TUD_AUDIO_TX_ITEMSIZE @@ -136,8 +185,8 @@ #define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 #endif #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 @@ -170,69 +219,84 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); -uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); -void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); -#else -uint16_t tud_audio_n_available (uint8_t itf); -uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_n_read_flush (uint8_t itf); -#endif -#endif +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +uint16_t tud_audio_n_available (uint8_t itf); +uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO -/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers -#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE -uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +void tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -*/ -#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT -#define CFG_TUD_AUDIO_TX_FIFO_COUNT 1 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); -#else -uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +void tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO +uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif -uint16_t tud_audio_n_write_flush(uint8_t itf); + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -uint16_t tud_audio_int_ctr_n_available (uint8_t itf); -uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_int_ctr_n_read_flush (uint8_t itf); -uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_clear (uint8_t itf); // Delete all content in the AUDIO_INT_CTR FIFO +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ -static inline bool tud_audio_mounted (void); +static inline bool tud_audio_mounted (void); + +// RX API + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -static inline uint16_t tud_audio_available (void); -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -static inline void tud_audio_read_flush (void); +static inline uint16_t tud_audio_available (void); +static inline void tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +static inline void tud_audio_clear_rx_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); -#else -static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t bufsize); #endif + +// TX API + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_write (const void * data, uint16_t len); +static inline uint16_t tud_audio_clear_ep_in_ff (void); + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +static inline uint16_t tud_audio_flush_tx_support_ff (void); +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); +#endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -static inline uint32_t tud_audio_int_ctr_available (void); -static inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); -static inline void tud_audio_int_ctr_read_flush (void); -static inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +// INT CTR API + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static inline uint16_t tud_audio_int_ctr_available (void); +static inline uint16_t tud_audio_int_ctr_read (void* buffer, uint16_t bufsize); +static inline void tud_audio_int_ctr_clear (void); +static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif // Buffer control EP data and schedule a transmit @@ -247,16 +311,17 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // User code should call this function with feedback value in 16.16 format for FS and HS. // Value will be corrected for FS to 10.14 format automatically. @@ -302,64 +367,82 @@ static inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN -#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used +// RX API + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_available (void) { - return tud_audio_n_write(0, channelId, buffer, n_bytes); + return tud_audio_n_available(0); } -#else -static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used + +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize) { - return tud_audio_n_write(0, buffer, n_bytes); + return tud_audio_n_read(0, buffer, bufsize); } -#endif -static inline uint16_t tud_audio_write_flush (void) // Short version if only one audio function is used +static inline uint16_t tud_audio_clear_ep_out_ff (void) { -#if CFG_TUD_AUDIO_TX_FIFO_SIZE - return tud_audio_n_write_flush(0); -#else - return 0; -#endif + return tud_audio_n_clear_ep_out_ff(0); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_available(uint8_t channelId) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + +static inline void tud_audio_clear_rx_support_ff (uint8_t channelId) { - return tud_audio_n_available(0, channelId); + tud_audio_n_clear_rx_support_ff(0, channelId); } -static inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_available_support_ff (uint8_t channelId) { - return tud_audio_n_read(0, channelId, buffer, bufsize); + return tud_audio_n_available_support_ff(0, channelId); } -static inline void tud_audio_read_flush(uint8_t channelId) +static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize) { - tud_audio_n_read_flush(0, channelId); + return tud_audio_n_read_support_ff(0, channelId, buffer, bufsize); } -#else -static inline uint16_t tud_audio_available(void) + +#endif + +#endif + +// TX API + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_write (const void * data, uint16_t len) { - return tud_audio_n_available(0); + return tud_audio_n_write(0, data, len); } -static inline uint16_t tud_audio_read(void *buffer, uint16_t bufsize) +static inline uint16_t tud_audio_clear_ep_in_ff (void) { - return tud_audio_n_read(0, buffer, bufsize); + return tud_audio_n_clear_ep_in_ff(0); } -static inline void tud_audio_read_flush(void) +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + +static inline uint16_t tud_audio_flush_tx_support_ff (void) { - tud_audio_n_read_flush(0); + return tud_audio_n_flush_tx_support_ff(0); } + +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId) +{ + return tud_audio_n_clear_tx_support_ff(0, channelId); +} + +static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len) +{ + return tud_audio_n_write_support_ff(0, channelId, data, len); +} + #endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN static inline uint16_t tud_audio_int_ctr_available(void) { return tud_audio_int_ctr_n_available(0); @@ -370,25 +453,25 @@ static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) return tud_audio_int_ctr_n_read(0, buffer, bufsize); } -static inline void tud_audio_int_ctr_read_flush(void) +static inline void tud_audio_int_ctr_clear(void) { - return tud_audio_int_ctr_n_read_flush(0); + return tud_audio_int_ctr_n_clear(0); } -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) { - return tud_audio_int_ctr_n_write(0, buffer, bufsize); + return tud_audio_int_ctr_n_write(0, buffer, len); } #endif //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/dcd.h b/src/device/dcd.h index 30224e16e..f0a552434 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -125,23 +125,23 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Stall endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); +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); +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ // Event API (implemented by stack) diff --git a/src/device/usbd.c b/src/device/usbd.c index 4e18df757..2e2f9cf65 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,12 +1206,16 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, tu_fifo_count(ff)); + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, count); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); @@ -1220,7 +1224,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_iso_xfer(rhport, ep_addr, ff) ) + if (dcd_edpt_iso_xfer(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 1d24957a9..412a97a5d 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 90fcd51e7..4cb6028cc 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -670,13 +670,15 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); - uint16_t total_bytes = tu_fifo_count(ff); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); -- cgit v1.3.1 From bb2f93d4270cfffc16b180a870f30ac789fdae30 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Feb 2021 20:41:41 +0700 Subject: prepare for release --- changelog.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/device/usbd.h | 1 + 2 files changed, 65 insertions(+) (limited to 'src/device') diff --git a/changelog.md b/changelog.md index 6b17e1666..393ca24ca 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,69 @@ # TinyUSB Changelog +## 0.8.0 - 2021.02.05 + +### Device Controller Driver + +- Added new device support for Raspberry Pi RP2040 +- Added new device support for NXP Kinetis KL25ZXX +- Use dcd_event_bus_reset() with link speed to replace bus_signal +- ESP32-S2: + - Add bus suspend and wakeup support +- SAMD21: + - Fix (walkaround) samd21 setup_packet overflow by USB DMA +- STM32 Synopsys: + - Rework USB FIFO allocation scheme and allow RX FIFO size reduction +- Sony CXD56 + - Update Update Spresense SDK to 2.0.2 + - Fix dcd issues with setup packets + - Correct EP number for cdc_msc example + +### USB Device + +**UBSD** + +- Rework usbd control transfer to have additional stage parameter for setup, data, status +- Fix tusb_init() return true instead of TUSB_ERROR_NONE +- Added new API tud_connected() that return true after device got out of bus reset and received the very first setup packet + +**Class Driver** + +- CDC + - Allow to transmit data, even if the host does not support control line states i.e set DTR +- HID + - change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64 +- MIDI + - Fix midi sysex sending bug +- MSC + - Invoke only scsi complete callback after status transaction is complete. + - Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error. +- USBTMC + - Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu + +**Example** + +- Support make from windows cmd.exe +- Add HID Consumer Control (media keys) to hid_composite & hid_composite_freertos examples + +### USB Host + +No noticeable changes to host stack + +### New Boards + +- NXP/Freescale Freedom FRDM-KL25Z +- Feather Double M33 express +- Raspberry Pi Pico +- Adafruit Feather RP2040 +- Adafruit Itsy Bitsy RP2040 +- Adafruit QT RP2040 +- Adfruit Feather ESP32-S2 +- Adafruit Magtag 29" Eink +- Adafruit Metro ESP32-S2 +- Adafruit PyBadge +- Adafruit PyPortal +- Great Scott Gadgets' LUNA D11 & D21 + ## 0.7.0 - 2020.11.08 ### Device Controller Driver diff --git a/src/device/usbd.h b/src/device/usbd.h index 360567743..b5f7dceba 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -57,6 +57,7 @@ extern void dcd_int_handler(uint8_t rhport); tusb_speed_t tud_speed_get(void); // Check if device is connected (may not mounted/configured yet) +// True if just got out of Bus Reset and received the very first data from host bool tud_connected(void); // Check if device is connected and configured -- cgit v1.3.1 From 49bc97b0caf65f4e850846f03c8693bb49198172 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 11:22:02 +0700 Subject: remove the requirement of std SET/CLEAR_FEATURE must not return zlp status --- src/device/usbd.c | 75 ++++++++++++++++++++++++++--------------------- src/device/usbd_control.c | 18 +++--------- 2 files changed, 46 insertions(+), 47 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f6b00563d..d871a53d4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -485,6 +485,12 @@ void tud_task (void) // But it is easier to set it every time instead of wasting time to check then set _usbd_dev.connected = 1; + // mark both in & out control as free + _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; + // Process control request if ( !process_control_request(event.rhport, &event.setup_received) ) { @@ -605,6 +611,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // forward to class driver: "non-STD request to Interface" return invoke_class_control(rhport, driver, p_request); } + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Non standard request is not supported @@ -712,14 +719,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - bool ret = false; + usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - // Handle STD request to endpoint - if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { - // force return true for standard request - ret = true; - + // Forward class request to its driver + TU_VERIFY(driver); + return invoke_class_control(rhport, driver, p_request); + } + else + { + // Handle STD request to endpoint switch ( p_request->bRequest ) { case TUSB_REQ_GET_STATUS: @@ -730,40 +740,39 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_CLEAR_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_clear_stall(rhport, ep_addr); - tud_control_status(rhport, p_request); - break; - case TUSB_REQ_SET_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_stall(rhport, ep_addr); - tud_control_status(rhport, p_request); + { + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) + { + if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) + { + usbd_edpt_clear_stall(rhport, ep_addr); + }else + { + usbd_edpt_stall(rhport, ep_addr); + } + } + + if (driver) + { + // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request + // We will also forward std request targeted endpoint to class drivers as well + + // STD request must always be ACKed regardless of driver returned value + // Also clear complete callback if driver set since it can also stall the request. + (void) invoke_class_control(rhport, driver, p_request); + usbd_control_set_complete_callback(NULL); + + // skip ZLP status if driver already did that + if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request); + } + } break; // Unknown/Unsupported request default: TU_BREAKPOINT(); return false; } } - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - - if (driver) - { - // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request - // We will forward all request targeted endpoint to class drivers after - // - For class-type requests: driver is fully responsible to reply to host - // - For std-type requests : driver init/re-init internal variable/buffer only, and - // must not call tud_control_status(), driver's return value will have no effect. - // EP state has already affected (stalled/cleared) - if ( invoke_class_control(rhport, driver, p_request) ) ret = true; - } - - if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) - { - // Set complete callback = NULL since it can also stall the request. - usbd_control_set_complete_callback(NULL); - } - - return ret; } break; diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 8ed0ad1c0..d15380199 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -67,12 +67,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con { // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - - TU_LOG2(" Queue EP %02X with zlp Status\r\n", ep_addr); - - // status direction is reversed to one in the setup packet - // Note: Status must always be DATA1 - return dcd_edpt_xfer(rhport, ep_addr, NULL, 0); + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } // Status phase @@ -101,9 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" Queue EP %02X with %u bytes\r\n", ep_addr, xact_len); - - return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); + return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } // Transmit data to/from the control endpoint. @@ -140,9 +133,6 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // USBD API //--------------------------------------------------------------------+ -//--------------------------------------------------------------------+ -// Prototypes -//--------------------------------------------------------------------+ void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); @@ -153,13 +143,13 @@ void usbd_control_reset(void) tu_varclr(&_ctrl_xfer); } -// TODO may find a better way +// Set complete callback void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) { _ctrl_xfer.complete_cb = fp; } -// useful for dcd_set_address where DCD is responsible for status response +// for dcd_set_address where DCD is responsible for status response void usbd_control_set_request(tusb_control_request_t const *request) { _ctrl_xfer.request = (*request); -- cgit v1.3.1 From 919bb9ce38e2c2c7afc3f9c763cc76c0c47f3a85 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 11:45:24 +0700 Subject: more epsize checking per type --- src/device/usbd.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f6b00563d..10fd4612d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1103,22 +1103,36 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); - if (TUSB_XFER_ISOCHRONOUS == desc_ep->bmAttributes.xfer) + switch (desc_ep->bmAttributes.xfer) { - TU_ASSERT(desc_ep->wMaxPacketSize.size <= (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023)); - } - else - { - uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 512 : 64); - - if (TUSB_XFER_BULK == desc_ep->bmAttributes.xfer) + case TUSB_XFER_ISOCHRONOUS: { - // Bulk must be EXACTLY 512/64 bytes - TU_ASSERT(desc_ep->wMaxPacketSize.size == max_epsize); - }else + uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + } + break; + + case TUSB_XFER_BULK: + + if (_usbd_dev.speed == TUSB_SPEED_HIGH) + { + // Bulk highspeed must be EXACTLY 512 + TU_ASSERT(desc_ep->wMaxPacketSize.size == 512); + }else + { + // TODO Bulk fullspeed can only be 8, 16, 32, 64 + TU_ASSERT(desc_ep->wMaxPacketSize.size <= 64); + } + break; + + case TUSB_XFER_INTERRUPT: { + uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); } + break; + + default: return false; } return dcd_edpt_open(rhport, desc_ep); -- cgit v1.3.1 From 9812cfc6c6ab98e600a1dd812d62e465ea3b99b4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 11:48:34 +0700 Subject: clean up --- src/device/usbd.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 10fd4612d..0c2d7b2ea 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1113,7 +1113,6 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) break; case TUSB_XFER_BULK: - if (_usbd_dev.speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 -- cgit v1.3.1 From e12c25ec2c6d1cb0dd3c02bdc1947ae351ccad54 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 12:05:22 +0700 Subject: rename dfu_rt to dfu_runtime for easy reading also rename tud_dfu_rt_reboot_to_dfu to tud_dfu_runtime_reboot_to_dfu_cb --- examples/device/dfu_rt/src/main.c | 2 +- examples/device/dfu_rt/src/tusb_config.h | 2 +- src/class/dfu/dfu_rt_device.c | 4 ++-- src/class/dfu/dfu_rt_device.h | 2 +- src/device/usbd.c | 4 ++-- src/tusb.h | 2 +- src/tusb_option.h | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu_rt/src/main.c b/examples/device/dfu_rt/src/main.c index 029ff7312..823c71ae5 100644 --- a/examples/device/dfu_rt/src/main.c +++ b/examples/device/dfu_rt/src/main.c @@ -112,7 +112,7 @@ void tud_resume_cb(void) } // Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_rt_reboot_to_dfu(void) +void tud_dfu_runtime_reboot_to_dfu_cb(void) { blink_interval_ms = BLINK_DFU_MODE; } diff --git a/examples/device/dfu_rt/src/tusb_config.h b/examples/device/dfu_rt/src/tusb_config.h index abdbe7526..bdae1d2e9 100644 --- a/examples/device/dfu_rt/src/tusb_config.h +++ b/examples/device/dfu_rt/src/tusb_config.h @@ -78,7 +78,7 @@ //------------- CLASS -------------// -#define CFG_TUD_DFU_RT 1 +#define CFG_TUD_DFU_RUNTIME 1 #ifdef __cplusplus } diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 38644615a..5700615be 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RT) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" @@ -110,7 +110,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request { case DFU_REQUEST_DETACH: tud_control_status(rhport, request); - tud_dfu_rt_reboot_to_dfu(); + tud_dfu_runtime_reboot_to_dfu_cb(); break; case DFU_REQUEST_GETSTATUS: diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 643e25d8f..cff43d035 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -58,7 +58,7 @@ typedef enum //--------------------------------------------------------------------+ // Invoked when received new data -TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention +TU_ATTR_WEAK void tud_dfu_runtime_reboot_to_dfu_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.c b/src/device/usbd.c index d871a53d4..f4e4e08f3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -175,9 +175,9 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_DFU_RT + #if CFG_TUD_DFU_RUNTIME { - DRIVER_NAME("DFU-RT") + DRIVER_NAME("DFU-RUNTIME") .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, diff --git a/src/tusb.h b/src/tusb.h index 8b0dd103c..cc82c440d 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -92,7 +92,7 @@ #include "class/usbtmc/usbtmc_device.h" #endif - #if CFG_TUD_DFU_RT + #if CFG_TUD_DFU_RUNTIME #include "class/dfu/dfu_rt_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 73daf8592..6cbdefbf1 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -233,8 +233,8 @@ #define CFG_TUD_USBTMC 0 #endif -#ifndef CFG_TUD_DFU_RT - #define CFG_TUD_DFU_RT 0 +#ifndef CFG_TUD_DFU_RUNTIME + #define CFG_TUD_DFU_RUNTIME 0 #endif #ifndef CFG_TUD_NET -- cgit v1.3.1 From 72c1066ed152916cb99dee5e5749b78916d4ba76 Mon Sep 17 00:00:00 2001 From: Duddie Date: Sun, 28 Feb 2021 22:18:35 +0800 Subject: Fix Endpoint descriptor for MIDI Device Endpoint descriptor should be 9 bytes in length (not 7) and have two extra bytes at the end: bRefresh and bSynchAddress According to MIDI USB specification 1.0 (6.2.1 Standard MS Bulk Data Endpoint Descriptor) --- src/device/usbd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index b5f7dceba..8aeb6aff8 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -289,10 +289,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* MS Out Jack (External), connected to In Jack Embedded */\ 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 -#define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) +#define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ /* MS Endpoint (connected to embedded jack) */\ (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables -- cgit v1.3.1 From 9d5e3691706f3f17edd701310b967c729240a507 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Mar 2021 23:24:36 +0700 Subject: rp2040 add disconnection detection - also use dcd_event_bus_reset() - Add TODO for suspend, resume later on (need to test with/without vbus detection). --- src/device/usbd.c | 21 ++++++++------ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 43 ++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 11 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 4fc221888..911977eb0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -992,11 +992,15 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) switch (event->event_id) { case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); + // UNPLUGGED event can be bouncing, only processing if we are currently connected + if ( _usbd_dev.connected ) + { + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + osal_queue_send(_usbd_q, event, in_isr); + } break; case DCD_EVENT_SOF: @@ -1004,9 +1008,10 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) break; case DCD_EVENT_SUSPEND: - // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the - // SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well. - // We will skip handling SUSPEND/RESUME event if not currently connected + // NOTE: When plugging/unplugging device, the D+/D- state are unstable and + // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). + // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish + // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected if ( _usbd_dev.connected ) { _usbd_dev.suspended = 1; diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index d32870439..84dce0248 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -317,13 +317,45 @@ static void dcd_rp2040_irq(void) pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); usb_hw->dev_addr_ctrl = 0; handled |= USB_INTS_BUS_RESET_BITS; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX rp2040_usb_device_enumeration_fix(); #endif } + if (status & USB_INTS_DEV_CONN_DIS_BITS) + { + handled |= USB_INTS_DEV_CONN_DIS_BITS; + + if ( usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS ) + { + // Connected: nothing to do + }else + { + // Disconnected + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS; + } + +#if 0 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection + if (status & USB_INTS_DEV_SUSPEND_BITS) + { + handled |= USB_INTS_DEV_SUSPEND_BITS; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS; + } + + if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) + { + handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS; + } +#endif + if (status ^ handled) { panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); @@ -364,8 +396,10 @@ void dcd_init (uint8_t rhport) // Enable individual controller IRQS here. Processor interrupt enable will be used // for the global interrupt enable... + // TODO Enable SUSPEND & RESUME interrupt usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; - usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS; + usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS | + USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */ ; dcd_connect(rhport); } @@ -393,8 +427,9 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { - pico_info("dcd_remote_wakeup %d is not supported yet\n", rhport); + pico_info("dcd_remote_wakeup %d\n", rhport); assert(rhport == 0); + usb_hw_set->sie_ctrl = USB_SIE_CTRL_RESUME_BITS; } // disconnect by disabling internal pull-up resistor on D+/D- @@ -402,6 +437,7 @@ void dcd_disconnect(uint8_t rhport) { pico_info("dcd_disconnect %d\n", rhport); assert(rhport == 0); + //TU_LOG2("dcd_disconnect\n"); usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } @@ -410,6 +446,7 @@ void dcd_connect(uint8_t rhport) { pico_info("dcd_connect %d\n", rhport); assert(rhport == 0); + //TU_LOG2("dcd_connect\n"); usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } -- cgit v1.3.1 From 7b8a08d2e1519afba6045e2a77898afecb1943e1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 20:00:39 +0100 Subject: Rename dcd_edpt_iso_xfer() to dcd_edpt_xfer_fifo() --- src/class/audio/audio_device.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 2 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 4 ++-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- src/portable/template/dcd_template.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 32745002c..37d6a36a7 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -34,7 +34,7 @@ * * 1. Input data -> SW-FIFO -> MCU USB * - * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_iso_xfer() is available) + * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) * * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB * diff --git a/src/device/dcd.h b/src/device/dcd.h index f0a552434..89f8760d0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -135,7 +135,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index c087e2b38..1879729e8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1246,7 +1246,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (dcd_edpt_iso_xfer(rhport, ep_addr, ff, total_bytes)) + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 25e54418f..ade79f107 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -357,7 +357,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void)rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 1edbba629..5866e1ce8 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -297,7 +297,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 9ff34e760..0e7157d4c 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -77,7 +77,7 @@ static bool active_ep0_xfer; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -297,7 +297,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 8aa97ad10..65a41463c 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -303,7 +303,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 0a690d84d..0d82a28c0 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -95,7 +95,7 @@ static uint32_t bufseg_addr; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -412,7 +412,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index e2fd48d74..dbd514f86 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -867,7 +867,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 1d0bb5107..6dad05ba1 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -675,7 +675,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 7a9a0ae22..ba656385b 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -106,7 +106,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; (void) ep_addr; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 61cbe1cf7..a8da1ae49 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -347,7 +347,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; -- cgit v1.3.1 From a655a4169e4a7be4b547f012643a86d198d46b1f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 01:18:49 +0700 Subject: add note for MIDI (audio v1.0) endpoint decriptor use 9 bytes instead of 7 --- src/device/usbd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index 8aeb6aff8..56615b081 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -254,6 +254,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// +// MIDI v1.0 is based on Audio v1.0 #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ @@ -291,7 +292,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ + /* Endpoint: Note Audio v1.0's endpoint has 9 bytes instead of 7 */\ 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ /* MS Endpoint (connected to embedded jack) */\ (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables -- cgit v1.3.1 From eeea19c0ab1c6e66c56eabac49e2c0f190e9a080 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 11:33:03 +0700 Subject: usbd ack SET_INTERFACE if it is not implemented by class driver. --- src/device/usbd.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 911977eb0..ca5a482fc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -699,13 +699,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE if ( !invoke_class_control(rhport, driver, p_request) ) { - // For GET_INTERFACE, it is mandatory to respond even if the class - // driver doesn't use alternate settings. - TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && - TUSB_REQ_GET_INTERFACE == p_request->bRequest); + // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class + // driver doesn't use alternate settings or implement this + TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + }else if (TUSB_REQ_SET_INTERFACE == p_request->bRequest) + { + tud_control_status(rhport, p_request); + } else + { + return false; + } } } break; -- cgit v1.3.1 From a397353916db36d925f5aec654fc66d5ca09f427 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 17:58:39 +0700 Subject: fix ci build with rp2040 --- src/common/tusb_fifo.h | 2 +- src/device/dcd.h | 5 +++-- src/osal/osal_pico.h | 4 ++-- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 0276c8044..62ee942d2 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -109,7 +109,7 @@ static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mute bool tu_fifo_write (tu_fifo_t* f, void const * p_data); uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); -uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); +uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); diff --git a/src/device/dcd.h b/src/device/dcd.h index 89f8760d0..1e5b3ff1e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -134,8 +134,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +// Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack +// This API is optional, may be useful for register-based for transferring data. +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index c277af271..bae1217eb 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -143,7 +143,7 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context - assert(!qhdl->ff.mutex); + //assert(!qhdl->ff.mutex); _osal_q_lock(qhdl); bool success = tu_fifo_read(&qhdl->ff, data); @@ -157,7 +157,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context - assert(!qhdl->ff.mutex); + //assert(!qhdl->ff.mutex); _osal_q_lock(qhdl); bool success = tu_fifo_write(&qhdl->ff, data); diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index f844a0c65..7731078b5 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -35,7 +35,8 @@ #include "pico/fix/rp2040_usb_device_enumeration.h" #endif - +#include "osal/osal.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ -- cgit v1.3.1 From 1138f8cc704e09af3335e253e5f244fde90d982f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Fri, 26 Mar 2021 15:30:43 -0400 Subject: Add DFU Class per Version 1.1 Spec --- src/class/dfu/dfu.h | 107 +++++++ src/class/dfu/dfu_rt_device.c | 667 ++++++++++++++++++++++++++++++++++++++++-- src/class/dfu/dfu_rt_device.h | 111 +++++-- src/common/tusb_types.h | 19 ++ src/device/usbd.c | 8 +- src/device/usbd.h | 15 +- src/device/usbd_control.c | 2 +- src/tusb_option.h | 4 + 8 files changed, 875 insertions(+), 58 deletions(-) create mode 100644 src/class/dfu/dfu.h (limited to 'src/device') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h new file mode 100644 index 000000000..39ce567da --- /dev/null +++ b/src/class/dfu/dfu.h @@ -0,0 +1,107 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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_H_ +#define _TUSB_DFU_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Common Definitions +//--------------------------------------------------------------------+ +// DFU Protocol +typedef enum +{ + DFU_PROTOCOL_RT = 0x01, + DFU_PROTOCOL_DFU = 0x02, +} dfu_protocol_type_t; + +// DFU Descriptor Type +typedef enum +{ + DFU_DESC_FUNCTIONAL = 0x21, +} dfu_descriptor_type_t; + +// DFU Requests +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; + +// DFU States +typedef enum { + APP_IDLE = 0, + APP_DETACH = 1, + DFU_IDLE = 2, + DFU_DNLOAD_SYNC = 3, + DFU_DNBUSY = 4, + DFU_DNLOAD_IDLE = 5, + DFU_MANIFEST_SYNC = 6, + DFU_MANIFEST = 7, + DFU_MANIFEST_WAIT_RESET = 8, + DFU_UPLOAD_IDLE = 9, + DFU_ERROR = 10, +} dfu_mode_state_t; + +// DFU Status +typedef enum { + DFU_STATUS_OK = 0x00, + DFU_STATUS_ERRTARGET = 0x01, + DFU_STATUS_ERRFILE = 0x02, + DFU_STATUS_ERRWRITE = 0x03, + DFU_STATUS_ERRERASE = 0x04, + DFU_STATUS_ERRCHECK_ERASED = 0x05, + DFU_STATUS_ERRPROG = 0x06, + DFU_STATUS_ERRVERIFY = 0x07, + DFU_STATUS_ERRADDRESS = 0x08, + DFU_STATUS_ERRNOTDONE = 0x09, + DFU_STATUS_ERRFIRMWARE = 0x0A, + DFU_STATUS_ERRVENDOR = 0x0B, + DFU_STATUS_ERRUSBR = 0x0C, + DFU_STATUS_ERRPOR = 0x0D, + DFU_STATUS_ERRUNKNOWN = 0x0E, + DFU_STATUS_ERRSTALLEDPKT = 0x0F, +} dfu_mode_device_status_t; + +#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0) +#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1) +#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) +#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 5700615be..965d1661e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -34,34 +34,176 @@ //--------------------------------------------------------------------+ // 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; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_state_ctx_t; typedef struct TU_ATTR_PACKED { - uint8_t status; - uint8_t poll_timeout[3]; - uint8_t state; - uint8_t istring; -} dfu_status_t; + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} dfu_status_req_payload_t; + +TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_mode_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), + .items = _dfu_mode_state_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_mode_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), + .items = _dfu_mode_status_lookup +}; + +#endif + +#define dfu_rtd_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ +} //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { + if ( tud_dfu_runtime_init_cb ) { + _dfu_state_ctx.state = (tud_dfu_runtime_init_cb() == DFU_PROTOCOL_DFU) ? APP_DETACH : APP_IDLE; + } else { + _dfu_state_ctx.state = APP_IDLE; + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + + dfu_rtd_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - (void) rhport; + if ( tud_dfu_runtime_usb_reset_cb ) + { + tud_dfu_runtime_usb_reset_cb(rhport, _dfu_state_ctx.state); + } + + switch (_dfu_state_ctx.state) + { + case APP_DETACH: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_runtime_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + dfu_rtd_debug_print_context(); } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -69,9 +211,10 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui (void) rhport; (void) max_len; - // Ensure this is DFU Runtime + // Ensure this is DFU Runtime or Mode TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && - itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); + ( (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT) + | (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) ), 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); uint16_t drv_len = sizeof(tusb_desc_interface_t); @@ -90,9 +233,16 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // return false to stall control endpoint (e.g unsupported request) bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - // nothing to do with DATA and ACK stage + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_mode_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage if ( stage != CONTROL_STAGE_SETUP ) return true; + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request @@ -106,34 +256,487 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - switch ( request->bRequest ) + switch (request->bRequest) { case DFU_REQUEST_DETACH: - tud_control_status(rhport, request); - tud_dfu_runtime_reboot_to_dfu_cb(); - break; - + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: { - // status = OK, poll timeout = 0, state = app idle, istring = 0 - uint8_t status_response[6] = { 0, 0, 0, 0, 0, 0 }; - tud_control_xfer(rhport, request, status_response, sizeof(status_response)); + return dfu_state_machine(rhport, request); } break; - default: return false; // stall unsupported request + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; + } + break; } return true; } +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) +{ + _dfu_state_ctx.status = status; +} -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { - (void) rhport; - (void) ep_addr; - (void) result; - (void) xferred_bytes; + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.epin_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.epin_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.epout_buf, request->wLength); +} + +static void dfu_runtime_start_status_poll_timeout() +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); +} + +void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_runtime_start_status_poll_timeout(); + tud_dfu_runtime_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.epout_buf, request->wLength); + _dfu_state_ctx.blk_transfer_in_proc = false; +} + +void tud_dfu_runtime_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case APP_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + { + _dfu_state_ctx.state = APP_DETACH; + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) + { + tud_dfu_runtime_reboot_to_dfu_cb(); + } else { + tud_dfu_runtime_detach_start_timer_cb(request->wValue); + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case APP_DETACH: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = APP_IDLE; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_runtime_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_runtime_abort_cb ) + { + tud_dfu_runtime_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_runtime_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_runtime_abort_cb) + { + tud_dfu_runtime_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + return true; } + #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index cff43d035..0d8f67a9b 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -29,36 +29,106 @@ #include "common/tusb_common.h" #include "device/usbd.h" +#include "dfu.h" #ifdef __cplusplus extern "C" { #endif - //--------------------------------------------------------------------+ -// Common Definitions +// Application Callback API (weak is optional) //--------------------------------------------------------------------+ +// Allow the application to update the status as required. +// Is set to DFU_STATUS_OK during internal initialization and USB reset +// Value is not checked to allow for custom statuses to be used +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); -// DFU Protocol -typedef enum -{ - DFU_PROTOCOL_RT = 1, - DFU_PROTOCOL_DFU = 2, -} dfu_protocol_type_t; +// Invoked when a DFU_DETACH request is received and bitWillDetatch is set +void tud_dfu_runtime_reboot_to_dfu_cb(); -// DFU Descriptor Type -typedef enum -{ - DFU_DESC_FUNCTIONAL = 0x21, -} dfu_descriptor_type_t; +// Invoked when a DFU_DETACH request is received and bitWillDetatch is not set +// This should start a timer for wTimeout ms +// The application should then look for a USB reset signal to occur before +// the timeout has elapsed. The reset signal will invoke tud_dfu_runtime_usb_reset_cb. +// If this reset signal is received before the timeout, then the application must +// switch to DFU mode. +// If the timer expires, the app does not need to do anything. +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this can will hold up the USB stack +TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_runtime_firmware_valid_check_cb(); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_runtime_init_attrs_cb(); + +// Invoked during initialization of the dfu driver to start as RT or DFU +// This will determine if the internal state machine will begin in +// APP_IDLE or DFU_IDLE +TU_ATTR_WEAK dfu_protocol_type_t tud_dfu_runtime_init_cb(); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); -// Invoked when received new data -TU_ATTR_WEAK void tud_dfu_runtime_reboot_to_dfu_cb(void); +// Invoked during a USB reset +// Lets the app know that a USB reset has occurred so it can act accordingly, +// See tud_dfu_runtime_detach_start_timer_cb for how to handle the APP_DETACH state +// Other states will be application specific +TU_ATTR_WEAK void tud_dfu_runtime_usb_reset_cb(uint8_t rhport, dfu_mode_state_t state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_runtime_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_runtime_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_runtime_poll_timeout_done(); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_runtime_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_runtime_device_data_done_check_cb(); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_runtime_abort_cb(); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_runtime_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API @@ -67,8 +137,11 @@ void dfu_rtd_init(void); void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, 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); +//--------------------------------------------------------------------+ +void dfu_mode_init(void); +void dfu_mode_reset(uint8_t rhport); +void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); #ifdef __cplusplus } #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ba3fe2c41..a462b498f 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -421,6 +421,25 @@ typedef struct TU_ATTR_PACKED char url[]; } tusb_desc_webusb_url_t; +// DFU Functional Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType; + + struct TU_ATTR_PACKED { + uint8_t bitCanDnload : 1; + uint8_t bitCanUpload : 1; + uint8_t bitManifestationTolerant : 1; + uint8_t bitWillDetach : 1; + uint8_t reserved : 4; + } bmAttributes; + + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +} tusb_desc_dfu_functional_t; + /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ diff --git a/src/device/usbd.c b/src/device/usbd.c index 4fc221888..28c9acdd2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -182,7 +182,7 @@ static usbd_class_driver_t const _usbd_driver[] = .reset = dfu_rtd_reset, .open = dfu_rtd_open, .control_xfer_cb = dfu_rtd_control_xfer_cb, - .xfer_cb = dfu_rtd_xfer_cb, + .xfer_cb = NULL, .sof = NULL }, #endif @@ -1270,9 +1270,9 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) /** * usbd_edpt_close will disable an endpoint. - * + * * In progress transfers on this EP may be delivered after this call. - * + * */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { diff --git a/src/device/usbd.h b/src/device/usbd.h index b5f7dceba..f9700811f 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -529,7 +529,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb //------------- DFU Runtime -------------// #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -#define TUD_DFU_APP_SUBCLASS 0x01u +#define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) // Length of template descriptr: 18 bytes #define TUD_DFU_RT_DESC_LEN (9 + 9) @@ -542,6 +542,17 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +// Length of template descriptr: 18 bytes +#define TUD_DFU_MODE_DESC_LEN (9 + 9) + +// DFU runtime descriptor +// Interface number, string index, alternate setting, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _alt_setting, _attr, _timeout, _xfer_size) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt_setting, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + //------------- CDC-ECM -------------// diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index d15380199..724c652e6 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -107,7 +107,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo _ctrl_xfer.buffer = (uint8_t*) buffer; _ctrl_xfer.total_xferred = 0U; _ctrl_xfer.data_len = tu_min16(len, request->wLength); - + if (request->wLength > 0U) { if(_ctrl_xfer.data_len > 0U) diff --git a/src/tusb_option.h b/src/tusb_option.h index 6cbdefbf1..1af3ee672 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -237,6 +237,10 @@ #define CFG_TUD_DFU_RUNTIME 0 #endif +#ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE + #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 +#endif + #ifndef CFG_TUD_NET #define CFG_TUD_NET 0 #endif -- cgit v1.3.1 From 9b2ddd9cc6401b80350179d26e842557f9b60aaf Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 09:49:27 +0200 Subject: Generalize audio driver for 3 audio functions plus a lot more. - Audio format and parameters are parsed from descriptors thus user no longer needs to give them explicitely - Tested for 4 channel software type I PCM encoding with 16 bit with 1 channel per FIFO and 2 channels per FIFO (this is I2S specific) --- examples/device/audio_test/src/main.c | 8 +- examples/device/audio_test/src/tusb_config.h | 22 +- examples/device/audio_test/src/usb_descriptors.c | 11 +- examples/device/uac2_headset/src/tusb_config.h | 34 +- examples/device/uac2_headset/src/usb_descriptors.c | 2 +- src/class/audio/audio.h | 76 +- src/class/audio/audio_device.c | 1088 ++++++++++++++++---- src/class/audio/audio_device.h | 313 ++++-- src/common/tusb_fifo.c | 4 +- src/device/usbd.h | 59 +- 10 files changed, 1214 insertions(+), 403 deletions(-) (limited to 'src/device') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index a631f37b6..7cbf57946 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -53,17 +53,17 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[CFG_TUD_AUDIO_EPSIZE_IN/2]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_EP_SZ_IN/2]; uint16_t startVal = 0; void led_blinking_task(void); diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 557a8b15e..d3b617319 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -91,6 +91,21 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- +// Have a look into audio_device.h for all configurations + +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! +#define CFG_TUD_AUDIO_EP_SZ_IN 48 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channel +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + 1 + + + // Audio format type #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I @@ -100,14 +115,11 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_EPSIZE_IN 48 * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 -// Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 #ifdef __cplusplus } diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index d4869a940..67dd34d2a 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -79,7 +79,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -89,20 +89,13 @@ enum #define EPNUM_AUDIO 0x01 #endif -// These variables are required by the audio driver in audio_device.c - -// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO - unfortunately this is not possible to determine otherwise -const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_MIC_DESC_LEN}; - -// TAKE CARE - THE NUMBER OF AUDIO STREAMING INTERFACES PER AUDIO FUNCTION MUST NOT EXCEED CFG_TUD_AUDIO_N_AS_INT - IF IT DOES INCREASE CFG_TUD_AUDIO_N_AS_INT IN tusb_config.h! - uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ 16, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EPSIZE_IN) + TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 7795d8405..511e4e558 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -91,35 +91,31 @@ extern "C" { //-------------------------------------------------------------------- // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) - -// Audio format type -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_I +#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) +#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) // Audio format type I specifications -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 -#define CFG_TUD_AUDIO_N_CHANNELS_RX 2 -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 2 -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX 2 +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EPSIZE_IN // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_OUT (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT*3 +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 +#define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 #ifdef __cplusplus } diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 940f0fe2b..b69e5a5e0 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -98,7 +98,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EPSIZE_OUT, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EPSIZE_IN) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_OUT_SZ, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index af0e86e21..2c6cd260a 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -469,44 +469,44 @@ typedef enum /// Additional Audio Device Class Codes - Source: Audio Data Formats /// A.1 - Audio Class-Format Type Codes UAC2 -//typedef enum -//{ -// AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, -// AUDIO_FORMAT_TYPE_I = 0x01, -// AUDIO_FORMAT_TYPE_II = 0x02, -// AUDIO_FORMAT_TYPE_III = 0x03, -// AUDIO_FORMAT_TYPE_IV = 0x04, -// AUDIO_EXT_FORMAT_TYPE_I = 0x81, -// AUDIO_EXT_FORMAT_TYPE_II = 0x82, -// AUDIO_EXT_FORMAT_TYPE_III = 0x83, -//} audio_format_type_t; - -#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 -#define AUDIO_FORMAT_TYPE_I 0x01 -#define AUDIO_FORMAT_TYPE_II 0x02 -#define AUDIO_FORMAT_TYPE_III 0x03 -#define AUDIO_FORMAT_TYPE_IV 0x04 -#define AUDIO_EXT_FORMAT_TYPE_I 0x81 -#define AUDIO_EXT_FORMAT_TYPE_II 0x82 -#define AUDIO_EXT_FORMAT_TYPE_III 0x83 - -/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -//typedef enum -//{ -// AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), -// AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), -// AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), -// AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), -// AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), -// AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, -//} audio_data_format_type_I_t; - -#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) -#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) -#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) -#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) -#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) -#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +//#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 +//#define AUDIO_FORMAT_TYPE_I 0x01 +//#define AUDIO_FORMAT_TYPE_II 0x02 +//#define AUDIO_FORMAT_TYPE_III 0x03 +//#define AUDIO_FORMAT_TYPE_IV 0x04 +//#define AUDIO_EXT_FORMAT_TYPE_I 0x81 +//#define AUDIO_EXT_FORMAT_TYPE_II 0x82 +//#define AUDIO_EXT_FORMAT_TYPE_III 0x83 + +// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, +} audio_data_format_type_I_t; + +//#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) +//#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) +//#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) +//#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) +//#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) +//#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 73f265a8f..5df32c30f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -63,7 +63,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ - // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically #if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ @@ -92,18 +92,170 @@ #define USE_LINEAR_BUFFER 0 #endif +// Declaration of buffers + +// Check for maximum supported numbers +#if CFG_TUD_AUDIO > 3 +#error Maximum number of audio functions restricted to three! +#endif + +// EP IN software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + +// Linear buffer TX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// EP OUT software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + +// Linear buffer RX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// Control buffers +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +#if CFG_TUD_AUDIO > 1 +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +#endif +#if CFG_TUD_AUDIO > 2 +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +#endif + +// Active alternate setting of interfaces +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +#endif + +// Software encoding/decoding support FIFOs +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#endif + typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN uint8_t ep_in; // TX audio data EP. + uint16_t ep_in_sz; // Current size of TX EP uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT uint8_t ep_out; // Incoming (into uC) audio data EP. + uint16_t ep_out_sz; // Current size of RX EP uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -116,74 +268,83 @@ typedef struct uint8_t ep_int_ctr; // Audio control interrupt EP. #endif -#if CFG_TUD_AUDIO_N_AS_INT - uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + uint8_t * alt_setting_ptr; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif /*------------- From this point, data is not cleared by bus reset -------------*/ + // + uint16_t desc_length; // Length of audio function descriptor + // Buffer for control requests - CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; + uint8_t * ctrl_buf; + uint8_t ctrl_buf_sz; // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - -#if !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t ep_out_ff; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd; // No need for write mutex as only USB driver writes into FIFO -#endif - #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). #endif - #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t ep_in_ff; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr; // No need for read mutex as only USB driver reads from FIFO #endif -#endif - - // Audio control interrupt buffer - no FIFO + // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif - // Support FIFOs -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + // Decoding parameters - parameters are set when alternate AS interface is set by host + // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + audio_format_type_t format_type_rx; + uint8_t n_channels_rx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio_data_format_type_I_t format_type_I_rx; + uint8_t n_bytes_per_sampe_rx; #endif #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + // Encoding parameters - parameters are set when alternate AS interface is set by host +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + audio_format_type_t format_type_tx; + uint8_t n_channels_tx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + audio_data_format_type_I_t format_type_I_tx; + uint8_t n_bytes_per_sampe_tx; + uint8_t n_channels_per_ff_tx; +#endif #endif + + // Support FIFOs for software encoding and decoding +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_t * rx_supp_ff; + uint8_t n_rx_supp_ff; + uint8_t n_channels_per_ff_rx; +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_t * tx_supp_ff; + uint8_t n_tx_supp_ff; #endif // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_EPSIZE_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE) - CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + uint8_t * lin_buf_out; #define USE_LINEAR_BUFFER_RX 1 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE) - CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) + uint8_t * lin_buf_in; #define USE_LINEAR_BUFFER_TX 1 #endif @@ -204,30 +365,19 @@ typedef struct //--------------------------------------------------------------------+ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; -extern const uint16_t tud_audio_desc_lengths[]; - -// bSubslotSize for PCM encoding/decoding using support FIFOs -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -extern const tud_audio_n_bytes_per_sample_tx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -extern const tud_audio_n_bytes_per_sample_rx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif @@ -238,17 +388,23 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); +static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); + +static inline uint8_t tu_desc_subtype(void const* desc) +{ + return ((uint8_t const*) desc)[2]; +} bool tud_audio_n_mounted(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_AUDIO); audiod_interface_t* audio = &_audiod_itf[itf]; -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (audio->ep_in == 0) return false; #endif @@ -267,7 +423,7 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING uint16_t tud_audio_n_available(uint8_t itf) { @@ -289,50 +445,46 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif // This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + switch (audio->format_type_rx) { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! @@ -342,7 +494,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + switch (audio->format_type_I_tx) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); @@ -364,7 +516,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else @@ -373,34 +525,108 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); return true; } -#endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT -// The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Decoding according to 2.3.1.5 Audio Streams + +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +{ + + // This function is an optimized version of +// while((uint8_t *)dst < dst_end) +// { +// memcpy(dst, src, nBytesToCopy); +// dst = (uint8_t *)dst + nBytesToCopy; +// src += nBytesToCopy * n_ff_used; +// } + + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while((uint8_t *)dst < dst_end) + { + *(uint8_t *)dst++ = *src; + src += n_ff_used; + } + break; + + case 2: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + dst += 2; + src += 2 * n_ff_used; + } + break; + + case 3: + while((uint8_t *)dst < dst_end) + { +// memcpy(dst, src, 3); +// dst = (uint8_t *)dst + 3; +// src += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + + src += 3 * (n_ff_used - 1); + } + break; + + case 4: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + dst += 4; + src += 4 * n_ff_used; + } + break; + } + + return src; +} + static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { (void) rhport; // Determine amount of samples - uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; - uint16_t const nSamplesPerFFToRead = n_bytes_received / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + uint8_t const n_ff_used = audio->n_channels_rx / audio->n_channels_per_ff_rx; + + TU_ASSERT( n_ff_used <= audio->n_rx_supp_ff ); + + uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; + uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; // Decode @@ -409,36 +635,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint8_t * dst_end; uint16_t len; - for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - src = &audio->lin_buf_out[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead); tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + dst_end = dst + len; - while((uint8_t *)dst < dst_end) - { - memcpy(dst, src, nBytesToCopy); - dst = (uint8_t *)dst + nBytesToCopy; - src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - } + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len < nSamplesPerFFToRead) + if (len < nBytesPerFFToRead) { - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead - len); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead - len); tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + dst_end = dst + len; - while((uint8_t *)dst < dst_end) - { - memcpy(dst, src, nBytesToCopy); - dst = (uint8_t *)dst + nBytesToCopy; - src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - } + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); } } @@ -447,13 +663,13 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, return true; } -#endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_DECODING //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING /** * \brief Write data to EP in buffer @@ -480,7 +696,7 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); @@ -498,13 +714,13 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); } #endif @@ -534,42 +750,44 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I + // Required in any case regardless if call backs are used - find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); +#else + // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface + if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); +#endif // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; // If support FIFOs are used, encode and schedule transmit -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN - switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + switch (audio->format_type_tx) { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + switch (audio->format_type_I_tx) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: @@ -580,6 +798,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // YOUR ENCODING IS REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; } break; @@ -588,6 +807,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; } @@ -596,27 +816,27 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #else // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); + n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - #if USE_LINEAR_BUFFER_TX - tu_fifo_write_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - #else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); - #endif +#if USE_LINEAR_BUFFER_TX + tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); +#else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); +#endif #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); return true; } -#endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN // Take samples from the support buffer and encode them into the IN EP software FIFO // Returns number of bytes written into linear buffer @@ -626,7 +846,7 @@ data streams. The audio data is not compressed and uses a signed two’s-complem is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the range [-1, +1) -*/ + */ /* * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples @@ -634,35 +854,99 @@ range [-1, +1) * does not change the number of bytes per sample. * */ +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +{ + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while((uint8_t *)src < src_end) + { + *dst = *(uint8_t *)src++; + dst += n_ff_used; + } + break; + + case 2: + while((uint8_t *)src < src_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + src += 2; + dst += 2 * n_ff_used; + } + break; + + case 3: + while((uint8_t *)src < src_end) + { +// memcpy(dst, src, 3); +// src = (uint8_t *)src + 3; +// dst += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *dst++ = *(uint8_t *)src++; + *dst++ = *(uint8_t *)src++; + *dst++ = *(uint8_t *)src++; + + dst += 3 * (n_ff_used - 1); + } + break; + + case 4: + while((uint8_t *)src < src_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + src += 4; + dst += 4 * n_ff_used; + } + break; + } + + return dst; +} + static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's linear buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t const capSamplesPerFF = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - uint16_t nSamplesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); + uint8_t const n_ff_used = audio->n_channels_tx / audio->n_channels_per_ff_tx; + + TU_ASSERT( n_ff_used <= audio->n_tx_supp_ff ); + + uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; + uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes + uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); uint8_t cnt_ff; - for (cnt_ff = 1; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) { uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nSamplesPerFFToSend) + if (count < nBytesPerFFToSend) { - nSamplesPerFFToSend = count; + nBytesPerFFToSend = count; } } // Check if there is enough - if (nSamplesPerFFToSend == 0) return 0; + if (nBytesPerFFToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nSamplesPerFFToSend = tu_min16(nSamplesPerFFToSend, capSamplesPerFF); + nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); // Round to full number of samples (flooring) - nSamplesPerFFToSend = (nSamplesPerFFToSend / nChannelsPerFF) * nChannelsPerFF; + nBytesPerFFToSend = (nBytesPerFFToSend / audio->n_channels_per_ff_tx) * audio->n_channels_per_ff_tx; // Encode void * src; @@ -670,46 +954,36 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud uint8_t * src_end; uint16_t len; - for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - dst = &audio->lin_buf_in[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; + dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend); tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + src_end = src + len; - while((uint8_t *)src < src_end) - { - memcpy(dst, src, nBytesToCopy); - src = (uint8_t *)src + nBytesToCopy; - dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - } + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len < nSamplesPerFFToSend) + if (len < nBytesPerFFToSend) { - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend - len); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend - len); tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + src_end = src + len; - while((uint8_t *)src < src_end) - { - memcpy(dst, src, nBytesToCopy); - src = (uint8_t *)src + nBytesToCopy; - dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - } + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); } } - return nSamplesPerFFToSend * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + return nBytesPerFFToSend * n_ff_used; } -#endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_ENCODING // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) { return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); @@ -727,43 +1001,304 @@ void audiod_init(void) { audiod_interface_t* audio = &_audiod_itf[i]; + // Initialize control buffers + switch (i) + { + case 0: + audio->ctrl_buf = ctrl_buf_1; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; + break; +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 + case 1: + audio->ctrl_buf = ctrl_buf_2; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 + case 2: + audio->ctrl_buf = ctrl_buf_3; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; + break; +#endif + } + + // Initialize active alternate interface buffers +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 + case 0: + audio->alt_setting_ptr = alt_setting_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 + case 1: + audio->alt_setting_ptr = alt_setting_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + case 2: + audio->alt_setting_ptr = alt_setting_3; + break; +#endif + } +#endif + // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_1), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_2), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex_wr), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_3), NULL); #endif + break; #endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_TX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 + case 0: + audio->lin_buf_in = lin_buf_in_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 + case 1: + audio->lin_buf_in = lin_buf_in_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 + case 2: + audio->lin_buf_in = lin_buf_in_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&audio->ep_out_ff_mutex_rd)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_1)); #endif + break; #endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_2)); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_3)); +#endif + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_RX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 + case 0: + audio->lin_buf_out = lin_buf_out_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 + case 1: + audio->lin_buf_out = lin_buf_out_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 + case 2: + audio->lin_buf_out = lin_buf_out_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) { - tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, true); +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->tx_supp_ff = tx_supp_ff_1; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->tx_supp_ff = tx_supp_ff_2; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->tx_supp_ff = tx_supp_ff_3; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex_wr[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); #endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; + break; #endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) { - tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX, true); +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->rx_supp_ff = rx_supp_ff_1; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->rx_supp_ff = rx_supp_ff_2; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->rx_supp_ff = rx_supp_ff_3; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], NULL, osal_mutex_create(&audio->rx_supp_ff_mutex_rd[cnt])); + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); #endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; + break; #endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING } } @@ -776,23 +1311,23 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_clear(&audio->ep_out_ff); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { tu_fifo_clear(&audio->rx_supp_ff[cnt]); } @@ -827,6 +1362,25 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one _audiod_itf[i].rhport = rhport; + + // Setup descriptor lengths + switch (i) + { + case 0: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; + break; +#if CFG_TUD_AUDIO > 1 + case 1: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; + break; +#endif +#if CFG_TUD_AUDIO > 2 + case 2: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; + break; +#endif + } + break; } } @@ -835,14 +1389,14 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { -#if CFG_TUD_AUDIO_N_AS_INT > 0 +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface @@ -850,9 +1404,9 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *dummy; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting_ptr[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting_ptr[idxItf]); return true; @@ -888,41 +1442,60 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *p_desc; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + audiod_interface_t* audio = &_audiod_itf[idxDriver]; + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (audio->ep_in_as_intf_num == itf) { - _audiod_itf[idxDriver].ep_in_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + audio->ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_in); // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - _audiod_itf[idxDriver].ep_in = 0; // Necessary? + audio->ep_in = 0; // Necessary? + + // Clear support FIFOs if used +#if CFG_TUD_AUDIO_ENABLE_ENCODING + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->tx_supp_ff[cnt]); + } +#endif + } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + if (audio->ep_out_as_intf_num == itf) { - _audiod_itf[idxDriver].ep_out_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); - _audiod_itf[idxDriver].ep_out = 0; // Necessary? + audio->ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_out); + audio->ep_out = 0; // Necessary? + + // Clear support FIFOs if used +#if CFG_TUD_AUDIO_ENABLE_DECODING + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->rx_supp_ff[cnt]); + } +#endif // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); - _audiod_itf[idxDriver].ep_fb = 0; // Necessary? + usbd_edpt_close(rhport, audio->ep_fb); + audio->ep_fb = 0; // Necessary? #endif } #endif // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; + audio->alt_setting_ptr[idxItf] = alt; // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; // p_desc starts at required interface with alternate setting zero while (p_desc < p_desc_end) @@ -930,6 +1503,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find correct interface if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) { +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING + uint8_t const * p_desc_parse_for_params = p_desc; +#endif // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; while (foundEPs < nEps && p_desc < p_desc_end) @@ -943,52 +1519,61 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address - _audiod_itf[idxDriver].ep_in = ep_addr; - _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + audio->ep_in = ep_addr; + audio->ep_in_as_intf_num = itf; + audio->ep_in_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; + // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters +#if CFG_TUD_AUDIO_ENABLE_ENCODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); +#endif // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an TX FIFO empty interrupt which can only trigger if something was in there + // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); } -#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { // Save address - _audiod_itf[idxDriver].ep_out = ep_addr; - _audiod_itf[idxDriver].ep_out_as_intf_num = itf; + audio->ep_out = ep_addr; + audio->ep_out_as_intf_num = itf; + audio->ep_out_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; +#if CFG_TUD_AUDIO_ENABLE_DECODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); +#endif // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data #if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback { - _audiod_itf[idxDriver].ep_fb = ep_addr; + audio->ep_fb = ep_addr; // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } #endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT -#endif foundEPs += 1; } p_desc = tu_desc_next(p_desc); @@ -1188,7 +1773,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, _audiod_itf[idxDriver].ctrl_buf_sz)); return true; } @@ -1238,7 +1823,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished if (_audiod_itf[idxDriver].ep_in == ep_addr) @@ -1259,7 +1844,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) @@ -1327,7 +1912,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; + if (len > _audiod_itf[idxDriver].ctrl_buf_sz) len = _audiod_itf[idxDriver].ctrl_buf_sz; // Copy into buffer memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); @@ -1348,7 +1933,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // Advance past AC descriptors uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1413,7 +1998,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { // Get pointer at beginning and end uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; while (p_desc < p_desc_end) { @@ -1437,7 +2022,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length; // Advance past AC descriptors - EP we look for are streaming EPs uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1457,6 +2042,69 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) return false; } +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +// p_desc points to the AS interface of alternate setting zero +// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter +// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! +static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) +{ + p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor + + while (p_desc < p_desc_end) + { + // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; + + // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) + { + if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + + if (itf == audio->ep_in_as_intf_num) + { + audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; +#endif + } + + if (itf == audio->ep_out_as_intf_num) + { + audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; +#endif + } + } + + // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) + { + if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + + if (itf == audio->ep_in_as_intf_num) + { + audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } + + if (itf == audio->ep_out_as_intf_num) + { + audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } + } +#endif + + // Other format types are not supported yet + + p_desc = tu_desc_next(p_desc); + } +} +#endif + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 730d42c38..e68c437ad 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -40,49 +40,151 @@ // All sizes are in bytes! -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) -#ifndef CFG_TUD_AUDIO_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the descriptors! +#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces +#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE +#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ #error You must define an audio class control request buffer size! #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + // End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 -#ifndef CFG_TUD_AUDIO_EPSIZE_IN -#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX +#endif + +// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation +#if CFG_TUD_AUDIO_ENABLE_EP_IN +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT + +// Software EP FIFO buffer sizes - must be >= max EP SIZEs! +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 +#endif + +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 +#endif + +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#ifndef CFG_TUD_AUDIO_EPSIZE_OUT -#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -// Software EP FIFO buffer sizes - must be >= EP SIZEs! -#if CFG_TUD_AUDIO_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX +#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#else -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE 0 + +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT -#ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX +#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#else -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE 0 + +#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -// General information of number of TX and/or RX channels - is used in combination with support FIFOs (see below) and can be used for descriptor definitions -#ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +// Enable/disable feedback EP (required for asynchronous RX applications) +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -#ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +// Audio interrupt control EP size - disabled if 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif // Use of TX/RX support FIFOs @@ -120,83 +222,100 @@ // - audio_rx_done_cb() // functions. -// The number of support FIFOs and number of channels is decoupled. The PCM encoding/decoding works depending on the ratio CFG_TUD_AUDIO_N_CHANNELS_XX / CFG_TUD_AUDIO_N_XX_SUPPORT_SW_FIFO, where currently 1:1 and 2:1 is implemented. The version 2:1 is useful in case of I2S for which usually 2 are channels already interleaved available. +// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size +// The actual parameters of active encoding is parsed from the descriptors -// Size of support FIFOs IN SAMPLES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO and CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO -#ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: // ceil(f_s/1000) * CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO +// For PCM encoding/decoding + +#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING +#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 #endif -#ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO +#ifndef CFG_TUD_AUDIO_ENABLE_DECODING +#define CFG_TUD_AUDIO_ENABLE_DECODING 0 #endif -#ifndef CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_TX // default size is equal to number of channels -#else -#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO 0 +// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 #endif + +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 #endif -#ifndef CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_RX // default size is equal to number of channels -#else -#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO 0 +// Type I Coding parameters not given within UAC2 descriptors +// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif - -// Enable/disable feedback EP (required for asynchronous RX applications) -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif - -// Audio interrupt control EP size - disabled if 0 -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif - -// Audio data format types - look in audio.h for existing types -// Used in case support FIFOs are used -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif - -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif #endif -// Audio data format type I specifications -#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I +// Remaining types not support so far -// Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface +#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 #endif - -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 #endif - +#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 #endif -#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I - -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO +#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 #endif +#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 #endif //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); @@ -219,33 +338,29 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING uint16_t tud_audio_n_available (uint8_t itf); uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO - #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO +#endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif -#endif - #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif @@ -258,15 +373,13 @@ static inline bool tud_audio_mounted (void); // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); - #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); @@ -274,14 +387,12 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); - #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); @@ -290,7 +401,7 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, // INT CTR API #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); +static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif // Buffer control EP data and schedule a transmit @@ -305,17 +416,17 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // User code should call this function with feedback value in 16.16 format for FS and HS. // Value will be corrected for FS to 10.14 format automatically. @@ -364,7 +475,7 @@ static inline bool tud_audio_mounted(void) // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING static inline uint16_t tud_audio_available (void) { @@ -383,7 +494,7 @@ static inline bool tud_audio_clear_ep_out_ff (void) #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) { @@ -404,7 +515,7 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len) { @@ -418,7 +529,7 @@ static inline bool tud_audio_clear_ep_in_ff (void) #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void) { @@ -444,7 +555,7 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool tud_audio_fb_set(uint32_t feedback) { return tud_audio_n_fb_set(0, feedback); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index d05549e3e..1b7f64447 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -138,9 +138,7 @@ static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const voi } } -// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address -// Code adapted from dcd_synopsis.c -// TODO generalize with configurable 1 byte or 4 byte each write +// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address in full word copies static void _tu_fifo_write_to_const_dst_ptr_in_full_words(void * dst, const void * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; diff --git a/src/device/usbd.h b/src/device/usbd.h index 56615b081..7c50a6db0 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -353,6 +353,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) #define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx +// 4 - Channels +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN (6+(4+1)*4) +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _ctrlch3, _ctrlch4, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), U32_TO_U8S_LE(_ctrlch3), U32_TO_U8S_LE(_ctrlch4), _stridx // For more channels, add definitions here @@ -389,7 +393,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -#define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ +#define TUD_AUDIO_MIC_ONE_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + TUD_AUDIO_DESC_STD_AC_LEN\ + TUD_AUDIO_DESC_CS_AC_LEN\ + TUD_AUDIO_DESC_CLK_SRC_LEN\ @@ -403,9 +407,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces +#define TUD_AUDIO_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces -#define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ @@ -435,6 +439,55 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) +// AUDIO simple descriptor (UAC2) for 4 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces + +#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + // AUDIO simple descriptor (UAC2) for mono speaker // - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source -- cgit v1.3.1 From c5b8ef15299e9d5787602b39805efbb0ca385110 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 16:32:58 -0400 Subject: Separate DFU RT and Mode. Untested --- src/class/dfu/dfu.h | 91 ++++++ src/class/dfu/dfu_mode_device.c | 598 +++++++++++++++++++++++++++++++++++ src/class/dfu/dfu_mode_device.h | 132 ++++++++ src/class/dfu/dfu_rt_device.c | 670 +++------------------------------------- src/class/dfu/dfu_rt_device.h | 70 +---- src/common/tusb_common.h | 2 +- src/device/usbd.c | 12 + src/tusb.h | 6 +- src/tusb_option.h | 6 +- 9 files changed, 903 insertions(+), 684 deletions(-) create mode 100644 src/class/dfu/dfu_mode_device.c create mode 100644 src/class/dfu/dfu_mode_device.h (limited to 'src/device') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 39ce567da..2040e415c 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -100,6 +100,97 @@ typedef enum { #define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) #define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) +// DFU Status Request Payload +typedef struct TU_ATTR_PACKED +{ + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} dfu_status_req_payload_t; + +TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_mode_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), + .items = _dfu_mode_state_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_mode_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), + .items = _dfu_mode_status_lookup +}; + +#endif + +#define dfu_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ +} + + #ifdef __cplusplus } #endif diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c new file mode 100644 index 000000000..e66fb823c --- /dev/null +++ b/src/class/dfu/dfu_mode_device.c @@ -0,0 +1,598 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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_MODE) + +#include "dfu_mode_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + uint16_t last_block_num; + uint16_t last_transfer_len; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_mode_state_ctx_t; + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_mode_state_ctx_t _dfu_state_ctx; + + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request); + + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_mode_init(void) +{ + _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + + dfu_debug_print_context(); +} + +void dfu_mode_reset(uint8_t rhport) +{ + if ( tud_dfu_mode_usb_reset_cb ) + { + tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); + } else { + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + } + + if(_dfu_state_ctx.state == APP_IDLE) + { + tud_dfu_mode_reboot_to_rt_cb(); + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + dfu_debug_print_context(); +} + +uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) rhport; + (void) max_len; + + // Ensure this is DFU Mode + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + uint16_t drv_len = sizeof(tusb_desc_interface_t); + + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_mode_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; + + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: + case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: + { + return dfu_mode_state_machine(rhport, request); + } + break; + + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_mode_req_nonstandard_cb ) ? tud_dfu_mode_req_nonstandard_cb(rhport, stage, request) : false; + } + break; + } + + return true; +} + +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) +{ + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_mode_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_mode_get_poll_timeout_cb ) + { + tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_mode_get_status_desc_table_index_cb ) ? tud_dfu_mode_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + _dfu_state_ctx.last_block_num = request->wValue; + _dfu_state_ctx.last_transfer_len = request->wLength; + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); +} + +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_mode_get_poll_timeout_cb ) + { + tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_mode_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); + + // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. + tud_dfu_mode_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); + _dfu_state_ctx.blk_transfer_in_proc = false; + + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; +} + +void tud_dfu_mode_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_mode_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_mode_abort_cb ) + { + tud_dfu_mode_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_mode_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_mode_abort_cb) + { + tud_dfu_mode_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + + return true; +} + + +bool dfu_mode_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_mode_device.h b/src/class/dfu/dfu_mode_device.h new file mode 100644 index 000000000..32bf58bbd --- /dev/null +++ b/src/class/dfu/dfu_mode_device.h @@ -0,0 +1,132 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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_MODE_DEVICE_H_ +#define _TUSB_DFU_MODE_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_mode_firmware_valid_check_cb(); + +// Invoked when the device must reboot to dfu runtime mode +void tud_dfu_mode_reboot_to_rt_cb(); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_mode_init_attrs_cb(); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); + +// Invoked during a USB reset +// Lets the app perform custom behavior on a USB reset. +// If not defined, the default behavior remains the DFU specification of +// Checking the firmware valid and changing to the error state or rebooting to runtime +// Note: If used, the application must perform the reset logic for all states. +// Changing the state to APP_IDLE will result in tud_dfu_mode_reboot_to_rt_cb being called +TU_ATTR_WEAK void tud_dfu_mode_usb_reset_cb(uint8_t rhport, dfu_mode_state_t *state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_mode_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_mode_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_mode_poll_timeout_done(); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_mode_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_mode_device_data_done_check_cb(); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_mode_abort_cb(); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_mode_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); + +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_mode_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_mode_init(void); +void dfu_mode_reset(uint8_t rhport); +uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 7d40d2057..806bfba2e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -40,176 +40,39 @@ //--------------------------------------------------------------------+ typedef struct TU_ATTR_PACKED { - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; - bool blk_transfer_in_proc; - - uint8_t itf_num; - uint16_t last_block_num; - uint16_t last_transfer_len; - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; -} dfu_state_ctx_t; - -typedef struct TU_ATTR_PACKED -{ - uint8_t bStatus; - uint8_t bwPollTimeout[3]; - uint8_t bState; - uint8_t iString; -} dfu_status_req_payload_t; - -TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; +} dfu_rt_state_ctx_t; // Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -static tu_lookup_entry_t const _dfu_mode_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "DFU_IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "DFU_ERROR" }, -}; - -static tu_lookup_table_t const _dfu_mode_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), - .items = _dfu_mode_state_lookup -}; - -static tu_lookup_entry_t const _dfu_mode_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, - { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -static tu_lookup_table_t const _dfu_mode_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), - .items = _dfu_mode_status_lookup -}; - -#endif +CFG_TUSB_MEM_SECTION static dfu_rt_state_ctx_t _dfu_state_ctx; -#define dfu_rtd_debug_print_context() \ -{ \ - TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ - tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ - tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ -} +static void dfu_rt_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { - if ( tud_dfu_runtime_init_cb ) { - _dfu_state_ctx.state = (tud_dfu_runtime_init_cb() == DFU_PROTOCOL_DFU) ? APP_DETACH : APP_IDLE; - } else { - _dfu_state_ctx.state = APP_IDLE; - } - + _dfu_state_ctx.state = APP_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - - dfu_rtd_debug_print_context(); + dfu_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - if ( tud_dfu_runtime_usb_reset_cb ) + if (((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 0) + && (_dfu_state_ctx.state == DFU_REQUEST_DETACH)) { - tud_dfu_runtime_usb_reset_cb(rhport, _dfu_state_ctx.state); - } - - switch (_dfu_state_ctx.state) - { - case APP_DETACH: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_runtime_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; - - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; + tud_dfu_runtime_reboot_to_dfu_cb(); } + _dfu_state_ctx.state = APP_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - dfu_rtd_debug_print_context(); + dfu_debug_print_context(); } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -217,10 +80,9 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui (void) rhport; (void) max_len; - // Ensure this is DFU Runtime or Mode - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && - ( (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT) - | (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) ), 0); + // Ensure this is DFU Runtime + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); uint16_t drv_len = sizeof(tusb_desc_interface_t); @@ -239,16 +101,9 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // return false to stall control endpoint (e.g unsupported request) bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) - { - dfu_mode_req_dnload_reply(rhport, request); - return true; - } - - // nothing to do with any other DATA or ACK stage + // nothing to do with DATA or ACK stage if ( stage != CONTROL_STAGE_SETUP ) return true; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request @@ -262,490 +117,67 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: - case DFU_REQUEST_DNLOAD: - case DFU_REQUEST_UPLOAD: - case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: - { - return dfu_state_machine(rhport, request); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; - } - break; - } - - return true; -} - -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) -{ - _dfu_state_ctx.status = status; -} - -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) -{ - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); - return retval; -} - -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - dfu_status_req_payload_t resp; - - resp.bStatus = _dfu_state_ctx.status; - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); - } else { - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); - } - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); -} - -static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); -} - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) -{ - _dfu_state_ctx.last_block_num = request->wValue; - _dfu_state_ctx.last_transfer_len = request->wLength; - // TODO: add "zero" copy mode so the buffer we read into can be provided by the user - // if they wish, there still will be the internal control buffer copy to this buffer - // but this mode would provide zero copy from the class driver to the application - - // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); -} - -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - uint8_t bwPollTimeout[3] = {0,0,0}; - - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } - - tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - - // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. - tud_dfu_runtime_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); - _dfu_state_ctx.blk_transfer_in_proc = false; - - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; -} - -void tud_dfu_runtime_poll_timeout_done() -{ - if (_dfu_state_ctx.state == DFU_DNBUSY) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_state_ctx.state == DFU_MANIFEST) - { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } -} - -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) -{ - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); - - switch (_dfu_state_ctx.state) - { - case APP_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - { - _dfu_state_ctx.state = APP_DETACH; - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } else { - tud_dfu_runtime_detach_start_timer_cb(request->wValue); - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case APP_DETACH: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = APP_IDLE; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_UPLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) - { - _dfu_state_ctx.state = DFU_UPLOAD_IDLE; - dfu_req_upload(rhport, request, request->wValue, request->wLength); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - ; // do nothing, but don't stall so continue on - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNLOAD_SYNC: { - switch (request->bRequest) + if (_dfu_state_ctx.state == APP_IDLE) { - case DFU_REQUEST_GETSTATUS: + _dfu_state_ctx.state = APP_DETACH; + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) { - if ( _dfu_state_ctx.blk_transfer_in_proc ) - { - _dfu_state_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); - } else { - _dfu_state_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); - } + tud_dfu_runtime_reboot_to_dfu_cb(); + } else { + tud_dfu_runtime_detach_start_timer_cb(request->wValue); } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNBUSY: - { - switch (request->bRequest) - { - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; + } else { + TU_LOG2(" DFU Unexpected request during state %s: %u\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), request->bRequest); + return false; } } break; - case DFU_DNLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - - dfu_req_dnload_setup(rhport, request); - } else { - if ( tud_dfu_runtime_device_data_done_check_cb() ) - { - _dfu_state_ctx.state = DFU_MANIFEST_SYNC; - tud_control_status(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall - } - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if ( tud_dfu_runtime_abort_cb ) - { - tud_dfu_runtime_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - { - _dfu_state_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); - } else { - if ( tud_dfu_runtime_firmware_valid_check_cb() ) - { - _dfu_state_ctx.state = DFU_IDLE; - } - dfu_req_getstatus_reply(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST: + case DFU_REQUEST_GETSTATUS: { - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } - } - break; + dfu_status_req_payload_t resp; + resp.bStatus = _dfu_state_ctx.status; + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); // Value is ignored + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - case DFU_MANIFEST_WAIT_RESET: - { - // technically we should never even get here, but we will handle it just in case - TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } break; - case DFU_UPLOAD_IDLE: + case DFU_REQUEST_GETSTATE: { - switch (request->bRequest) - { - case DFU_REQUEST_UPLOAD: - { - if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) - { - _dfu_state_ctx.state = DFU_IDLE; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if (tud_dfu_runtime_abort_cb) - { - tud_dfu_runtime_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); } break; - case DFU_ERROR: + default: { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_CLRSTATUS: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } + TU_LOG2(" DFU Nonstandard Runtime Request: %u\r\n", request->bRequest); + return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; } break; - - default: - _dfu_state_ctx.state = DFU_ERROR; - TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); - return false; // Unexpected state, stall and change to error } return true; } +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) +{ + _dfu_state_ctx.status = status; +} + +void tud_dfu_runtime_detach_timer_elapsed() +{ + if (_dfu_state_ctx.state == DFU_REQUEST_DETACH) + { + _dfu_state_ctx.state = APP_IDLE; + } +} #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 9e7ae029e..23703862d 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -43,28 +43,26 @@ // Value is not checked to allow for custom statuses to be used void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); -// Invoked when a DFU_DETACH request is received and bitWillDetatch is set +// Invoked when a DFU_DETACH request is received and bitWillDetach is set void tud_dfu_runtime_reboot_to_dfu_cb(); -// Invoked when a DFU_DETACH request is received and bitWillDetatch is not set +// Invoked when a DFU_DETACH request is received and bitWillDetach is not set // This should start a timer for wTimeout ms -// The application should then look for a USB reset signal to occur before -// the timeout has elapsed. The reset signal will invoke tud_dfu_runtime_usb_reset_cb. -// If this reset signal is received before the timeout, then the application must -// switch to DFU mode. -// If the timer expires, the app does not need to do anything. +// When the timer has elapsed, the app must call tud_dfu_runtime_detach_timer_elapsed +// If a USB reset is called while the timer is running, the class will call +// tud_dfu_runtime_reboot_to_dfu_cb. // NOTE: This callback should return immediately, and not implement the delay // internally, as this can will hold up the USB stack TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); +// Invoke when the dfu runtime detach timer has elapsed +void tud_dfu_runtime_detach_timer_elapsed(); + // Invoked when a nonstandard request is received // Use may be vendor specific. // Return false to stall TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -// Invoked when a reset is received to check if firmware is valid -bool tud_dfu_runtime_firmware_valid_check_cb(); - // Invoked during initialization of the dfu driver to set attributes // Return byte set with bitmasks: // DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK @@ -74,62 +72,10 @@ bool tud_dfu_runtime_firmware_valid_check_cb(); // Note: This should match the USB descriptor uint8_t tud_dfu_runtime_init_attrs_cb(); -// Invoked during initialization of the dfu driver to start as RT or DFU -// This will determine if the internal state machine will begin in -// APP_IDLE or DFU_IDLE -TU_ATTR_WEAK dfu_protocol_type_t tud_dfu_runtime_init_cb(); - // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); -// Invoked during a USB reset -// Lets the app know that a USB reset has occurred so it can act accordingly, -// See tud_dfu_runtime_detach_start_timer_cb for how to handle the APP_DETACH state -// Other states will be application specific -TU_ATTR_WEAK void tud_dfu_runtime_usb_reset_cb(uint8_t rhport, dfu_mode_state_t state); - -// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use -// before the subsequent DFU_GETSTATUS requests. -// The purpose of this value is to allow the device to tell the host -// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks -// to allow the device to have time to erase, write memory, etc. -// ms_timeout is a pointer to array of length 3. -// Refer to the USB DFU class specification for more details -TU_ATTR_WEAK void tud_dfu_runtime_get_poll_timeout_cb(uint8_t *ms_timeout); - -// Invoked when a DFU_DNLOAD request is received -// This should start a timer for ms_timeout ms -// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this will hold up the class stack from receiving any packets -// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states -void tud_dfu_runtime_start_poll_timeout_cb(uint8_t *ms_timeout); - -// Must be called when the poll_timeout has elapsed -void tud_dfu_runtime_poll_timeout_done(); - -// Invoked when a DFU_DNLOAD request is received -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_runtime_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_runtime_device_data_done_check_cb(); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_runtime_abort_cb(); - -// Invoked when a DFU_UPLOAD request is received -// This callback must populate data with up to length bytes -// Return the number of bytes to write -uint16_t tud_dfu_runtime_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f10be88ab..859d9d47d 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/device/usbd.c b/src/device/usbd.c index 28c9acdd2..91838b39c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -187,6 +187,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_DFU_MODE + { + DRIVER_NAME("DFU-MODE") + .init = dfu_mode_init, + .reset = dfu_mode_reset, + .open = dfu_mode_open, + .control_xfer_cb = dfu_mode_control_xfer_cb, + .xfer_cb = dfu_mode_xfer_cb, + .sof = NULL + }, + #endif + #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index cc82c440d..c9558515c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -96,6 +96,10 @@ #include "class/dfu/dfu_rt_device.h" #endif + #if CFG_TUD_DFU_MODE + #include "class/dfu/dfu_mode_device.h" + #endif + #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 1af3ee672..3cd3df9f2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -234,7 +234,11 @@ #endif #ifndef CFG_TUD_DFU_RUNTIME - #define CFG_TUD_DFU_RUNTIME 0 + #define CFG_TUD_DFU_RUNTIME 0 +#endif + +#ifndef CFG_TUD_DFU_MODE + #define CFG_TUD_DFU_MODE 0 #endif #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE -- cgit v1.3.1 From bc2cb99780a0bc0359195a4be8e556f71da5a70b Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 17:06:27 -0400 Subject: Remove unreachable callback --- src/class/dfu/dfu_mode_device.c | 10 ---------- src/class/dfu/dfu_mode_device.h | 1 - src/device/usbd.c | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) (limited to 'src/device') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 68f55510b..59cea7673 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -590,14 +590,4 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const } -bool dfu_mode_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_mode_device.h b/src/class/dfu/dfu_mode_device.h index 32bf58bbd..11b748c3b 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -122,7 +122,6 @@ void dfu_mode_init(void); void dfu_mode_reset(uint8_t rhport); uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 91838b39c..de0e7b0b7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -194,7 +194,7 @@ static usbd_class_driver_t const _usbd_driver[] = .reset = dfu_mode_reset, .open = dfu_mode_open, .control_xfer_cb = dfu_mode_control_xfer_cb, - .xfer_cb = dfu_mode_xfer_cb, + .xfer_cb = NULL, .sof = NULL }, #endif -- cgit v1.3.1 From c39b7b8177acbab23e82fee295d5f3205aa9752c Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 17:52:33 -0400 Subject: Add DFU runtime and mode "class" With the runtime and mode portions in separate classes, a single application should only be building with one or the other enabled. In some applications both might be desired at build time. The CFG_TUD_DFU_RUNTIME_AND_MODE option creates a DFU class, which asks the application which mode to initialize to. This allows a runtime change between RT and DFU mode, by just reinitializing tusb. --- src/class/dfu/dfu_mode_device.c | 4 +- src/class/dfu/dfu_rt_and_mode_device.c | 114 +++++++++++++++++++++++++++++++++ src/class/dfu/dfu_rt_and_mode_device.h | 57 +++++++++++++++++ src/class/dfu/dfu_rt_device.c | 2 +- src/device/usbd.c | 12 ++++ src/tusb.h | 6 ++ src/tusb_option.h | 10 +++ 7 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 src/class/dfu/dfu_rt_and_mode_device.c create mode 100644 src/class/dfu/dfu_rt_and_mode_device.h (limited to 'src/device') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 59cea7673..0b80b103d 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) #include "dfu_mode_device.h" #include "device/usbd_pvt.h" @@ -590,4 +590,4 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const } - #endif +#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c new file mode 100644 index 000000000..d555a1d58 --- /dev/null +++ b/src/class/dfu/dfu_rt_and_mode_device.c @@ -0,0 +1,114 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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_RUNTIME_AND_MODE) + +#include "dfu_rt_and_mode_device.h" + +#include "dfu_mode_device.h" +#include "dfu_rt_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct +{ + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +} dfu_local_driver_t; + +static dfu_local_driver_t ctx = +{ + .init = NULL, + .reset = NULL, + .open = NULL, + .control_xfer_cb = NULL +}; + +static dfu_protocol_type_t mode = 0x00; + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_init(void) +{ + mode = dfu_init_in_mode_cb(); + + switch (mode) + { + case DFU_PROTOCOL_RT: + { + ctx.init = dfu_rtd_init; + ctx.reset = dfu_rtd_reset; + ctx.open = dfu_rtd_open; + ctx.control_xfer_cb = dfu_rtd_control_xfer_cb; + } + break; + + case DFU_PROTOCOL_DFU: + { + ctx.init = dfu_mode_init; + ctx.reset = dfu_mode_reset; + ctx.open = dfu_mode_open; + ctx.control_xfer_cb = dfu_mode_control_xfer_cb; + } + break; + + default: + { + TU_LOG2(" DFU Unexpected mode: %u\r\n", mode); + } + break; + } + + ctx.init(); +} + +void dfu_reset(uint8_t rhport) +{ + ctx.reset(rhport); +} + +uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + return ctx.open(rhport, itf_desc, max_len); +} + +bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + return ctx.control_xfer_cb(rhport, stage, request); +} + +#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h new file mode 100644 index 000000000..9734a031c --- /dev/null +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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_AND_MODE_DEVICE_H_ +#define _TUSB_DFU_RT_AND_MODE_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when the driver needs to determine the callbacks to use +dfu_protocol_type_t dfu_init_in_mode_cb(); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_init(void); +void dfu_reset(uint8_t rhport); +uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_RT_AND_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 806bfba2e..d1d028d69 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index de0e7b0b7..6f2262feb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,6 +199,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_DFU_RUNTIME_AND_MODE + { + DRIVER_NAME("DFU-RT-MODE") + .init = dfu_init, + .reset = dfu_reset, + .open = dfu_open, + .control_xfer_cb = dfu_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index c9558515c..6eab4bee2 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -100,6 +100,12 @@ #include "class/dfu/dfu_mode_device.h" #endif + #if CFG_TUD_DFU_RUNTIME_AND_MODE + #include "class/dfu/dfu_rt_and_mode_device.h" + #include "class/dfu/dfu_rt_device.h" + #include "class/dfu/dfu_mode_device.h" + #endif + #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 3cd3df9f2..4c2204964 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -241,6 +241,10 @@ #define CFG_TUD_DFU_MODE 0 #endif +#ifndef CFG_TUD_DFU_RUNTIME_AND_MODE + #define CFG_TUD_DFU_RUNTIME_AND_MODE 0 +#endif + #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 #endif @@ -285,6 +289,12 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif +#if (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_RUNTIME) \ + || (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_MODE) \ + || (CFG_TUD_DFU_RUNTIME && CFG_TUD_DFU_MODE) + #error Only one of CFG_TUD_DFU_RUNTIME_AND_MODE, CFG_TUD_DFU_RUNTIME, and CFG_TUD_DFU_MODE can be enabled in a single build +#endif + #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 2e2dc7bdc5928dfa027291ca8c6d6792698e5b9a Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 7 Apr 2021 17:05:04 -0400 Subject: Revise per initial comments Returns the RT driver to the function state of previous iteration, which did not support the will_detach. Behavior should be fine without this feature. This removes much of the added bloat to track state, and handle requests in the APP_DETACH state which is no longer required. Removes the optional bloat added to the RT driver, such as responding to GETSTATE requests. Fixes the DFU Mode to extract the attr bits from the functional descriptor when opened. Fixes some incorrect bitwise if checks. Also, updates some naming of functions to be consistent with the rest of the library. --- src/class/dfu/dfu_mode_device.c | 19 +++++---- src/class/dfu/dfu_mode_device.h | 8 ++-- src/class/dfu/dfu_rt_and_mode_device.c | 18 ++++---- src/class/dfu/dfu_rt_and_mode_device.h | 10 ++--- src/class/dfu/dfu_rt_device.c | 76 ++++------------------------------ src/class/dfu/dfu_rt_device.h | 35 ---------------- src/class/vendor/vendor_device.c | 2 +- src/common/tusb_types.h | 18 ++++---- src/device/usbd.c | 16 +++---- 9 files changed, 55 insertions(+), 147 deletions(-) (limited to 'src/device') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 0b80b103d..7ad0f5168 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -65,11 +65,11 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ -void dfu_mode_init(void) +void dfu_moded_init(void) { _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.last_block_num = 0; _dfu_state_ctx.last_transfer_len = 0; @@ -77,7 +77,7 @@ void dfu_mode_init(void) dfu_debug_print_context(); } -void dfu_mode_reset(uint8_t rhport) +void dfu_moded_reset(uint8_t rhport) { if (_dfu_state_ctx.state == APP_DETACH) { @@ -118,14 +118,13 @@ void dfu_mode_reset(uint8_t rhport) } _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.last_block_num = 0; _dfu_state_ctx.last_transfer_len = 0; dfu_debug_print_context(); } -uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; (void) max_len; @@ -139,6 +138,9 @@ uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, u if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { + tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -149,7 +151,7 @@ uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, u // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) { @@ -266,7 +268,7 @@ void tud_dfu_mode_poll_timeout_done() _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -394,7 +396,6 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); } else { if ( tud_dfu_mode_device_data_done_check_cb() ) @@ -447,7 +448,7 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h index 11b748c3b..aacb1911c 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -118,10 +118,10 @@ TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_mode_init(void); -void dfu_mode_reset(uint8_t rhport); -uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +void dfu_moded_init(void); +void dfu_moded_reset(uint8_t rhport); +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c index d555a1d58..8b6a8a766 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.c +++ b/src/class/dfu/dfu_rt_and_mode_device.c @@ -62,9 +62,9 @@ static dfu_protocol_type_t mode = 0x00; //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ -void dfu_init(void) +void dfu_d_init(void) { - mode = dfu_init_in_mode_cb(); + mode = tud_dfu_init_in_mode_cb(); switch (mode) { @@ -79,10 +79,10 @@ void dfu_init(void) case DFU_PROTOCOL_DFU: { - ctx.init = dfu_mode_init; - ctx.reset = dfu_mode_reset; - ctx.open = dfu_mode_open; - ctx.control_xfer_cb = dfu_mode_control_xfer_cb; + ctx.init = dfu_moded_init; + ctx.reset = dfu_moded_reset; + ctx.open = dfu_moded_open; + ctx.control_xfer_cb = dfu_moded_control_xfer_cb; } break; @@ -96,17 +96,17 @@ void dfu_init(void) ctx.init(); } -void dfu_reset(uint8_t rhport) +void dfu_d_reset(uint8_t rhport) { ctx.reset(rhport); } -uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { return ctx.open(rhport, itf_desc, max_len); } -bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { return ctx.control_xfer_cb(rhport, stage, request); } diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h index 9734a031c..b6eafbba4 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -39,15 +39,15 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t dfu_init_in_mode_cb(); +dfu_protocol_type_t tud_dfu_init_in_mode_cb(); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_init(void); -void dfu_reset(uint8_t rhport); -uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +void dfu_d_init(void); +void dfu_d_reset(uint8_t rhport); +uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index d1d028d69..729b8e3e0 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -38,41 +38,17 @@ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; -} dfu_rt_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_rt_state_ctx_t _dfu_state_ctx; - -static void dfu_rt_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { - _dfu_state_ctx.state = APP_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - dfu_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - if (((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 0) - && (_dfu_state_ctx.state == DFU_REQUEST_DETACH)) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } - - _dfu_state_ctx.state = APP_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - dfu_debug_print_context(); + (void) rhport; } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -117,67 +93,29 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU RT Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: { - if (_dfu_state_ctx.state == APP_IDLE) - { - _dfu_state_ctx.state = APP_DETACH; - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } else { - tud_dfu_runtime_detach_start_timer_cb(request->wValue); - } - } else { - TU_LOG2(" DFU Unexpected request during state %s: %u\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), request->bRequest); - return false; - } + tud_control_status(rhport, request); + tud_dfu_runtime_reboot_to_dfu_cb(); } break; case DFU_REQUEST_GETSTATUS: { dfu_status_req_payload_t resp; - resp.bStatus = _dfu_state_ctx.status; - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); // Value is ignored - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - + // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 + memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } break; - case DFU_REQUEST_GETSTATE: - { - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Runtime Request: %u\r\n", request->bRequest); - return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; - } - break; + default: return false; // stall unsupported request } return true; } -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) -{ - _dfu_state_ctx.status = status; -} - -void tud_dfu_runtime_detach_timer_elapsed() -{ - if (_dfu_state_ctx.state == DFU_REQUEST_DETACH) - { - _dfu_state_ctx.state = APP_IDLE; - } -} - #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 23703862d..465bf9d99 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -38,44 +38,9 @@ //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Allow the application to update the status as required. -// Is set to DFU_STATUS_OK during internal initialization and USB reset -// Value is not checked to allow for custom statuses to be used -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); - // Invoked when a DFU_DETACH request is received and bitWillDetach is set void tud_dfu_runtime_reboot_to_dfu_cb(); -// Invoked when a DFU_DETACH request is received and bitWillDetach is not set -// This should start a timer for wTimeout ms -// When the timer has elapsed, the app must call tud_dfu_runtime_detach_timer_elapsed -// If a USB reset is called while the timer is running, the class will call -// tud_dfu_runtime_reboot_to_dfu_cb. -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this can will hold up the USB stack -TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); - -// Invoke when the dfu runtime detach timer has elapsed -void tud_dfu_runtime_detach_timer_elapsed(); - -// Invoked when a nonstandard request is received -// Use may be vendor specific. -// Return false to stall -TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -// Invoked during initialization of the dfu driver to set attributes -// Return byte set with bitmasks: -// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK -// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK -// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK -// DFU_FUNC_ATTR_WILL_DETACH_BITMASK -// Note: This should match the USB descriptor -uint8_t tud_dfu_runtime_init_attrs_cb(); - -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 3fcea89c4..d39830a6a 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a462b498f..7703ebb7b 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -427,13 +427,17 @@ typedef struct TU_ATTR_PACKED uint8_t bLength; uint8_t bDescriptorType; - struct TU_ATTR_PACKED { - uint8_t bitCanDnload : 1; - uint8_t bitCanUpload : 1; - uint8_t bitManifestationTolerant : 1; - uint8_t bitWillDetach : 1; - uint8_t reserved : 4; - } bmAttributes; + union { + struct TU_ATTR_PACKED { + uint8_t bitCanDnload : 1; + uint8_t bitCanUpload : 1; + uint8_t bitManifestationTolerant : 1; + uint8_t bitWillDetach : 1; + uint8_t reserved : 4; + } bmAttributes; + + uint8_t bAttributes; + }; uint16_t wDetachTimeOut; uint16_t wTransferSize; diff --git a/src/device/usbd.c b/src/device/usbd.c index 6f2262feb..92e521ec9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,10 +190,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_MODE { DRIVER_NAME("DFU-MODE") - .init = dfu_mode_init, - .reset = dfu_mode_reset, - .open = dfu_mode_open, - .control_xfer_cb = dfu_mode_control_xfer_cb, + .init = dfu_moded_init, + .reset = dfu_moded_reset, + .open = dfu_moded_open, + .control_xfer_cb = dfu_moded_control_xfer_cb, .xfer_cb = NULL, .sof = NULL }, @@ -202,10 +202,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_RUNTIME_AND_MODE { DRIVER_NAME("DFU-RT-MODE") - .init = dfu_init, - .reset = dfu_reset, - .open = dfu_open, - .control_xfer_cb = dfu_control_xfer_cb, + .init = dfu_d_init, + .reset = dfu_d_reset, + .open = dfu_d_open, + .control_xfer_cb = dfu_d_control_xfer_cb, .xfer_cb = NULL, .sof = NULL }, -- cgit v1.3.1 From 7b45b38fe4b7d2ebd197463cf12f091a6f68ac91 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 12 Apr 2021 11:17:01 -0400 Subject: Remove DFU mode and rt --- src/class/dfu/dfu_mode_device.c | 2 +- src/class/dfu/dfu_rt_and_mode_device.c | 114 --------------------------------- src/class/dfu/dfu_rt_and_mode_device.h | 57 ----------------- src/class/dfu/dfu_rt_device.c | 2 +- src/device/usbd.c | 12 ---- src/tusb.h | 6 -- src/tusb_option.h | 10 --- 7 files changed, 2 insertions(+), 201 deletions(-) delete mode 100644 src/class/dfu/dfu_rt_and_mode_device.c delete mode 100644 src/class/dfu/dfu_rt_and_mode_device.h (limited to 'src/device') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 7ad0f5168..5f8c714c0 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) #include "dfu_mode_device.h" #include "device/usbd_pvt.h" diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c deleted file mode 100644 index 8b6a8a766..000000000 --- a/src/class/dfu/dfu_rt_and_mode_device.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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_RUNTIME_AND_MODE) - -#include "dfu_rt_and_mode_device.h" - -#include "dfu_mode_device.h" -#include "dfu_rt_device.h" -#include "device/usbd_pvt.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct -{ - void (* init ) (void); - void (* reset ) (uint8_t rhport); - uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -} dfu_local_driver_t; - -static dfu_local_driver_t ctx = -{ - .init = NULL, - .reset = NULL, - .open = NULL, - .control_xfer_cb = NULL -}; - -static dfu_protocol_type_t mode = 0x00; - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_d_init(void) -{ - mode = tud_dfu_init_in_mode_cb(); - - switch (mode) - { - case DFU_PROTOCOL_RT: - { - ctx.init = dfu_rtd_init; - ctx.reset = dfu_rtd_reset; - ctx.open = dfu_rtd_open; - ctx.control_xfer_cb = dfu_rtd_control_xfer_cb; - } - break; - - case DFU_PROTOCOL_DFU: - { - ctx.init = dfu_moded_init; - ctx.reset = dfu_moded_reset; - ctx.open = dfu_moded_open; - ctx.control_xfer_cb = dfu_moded_control_xfer_cb; - } - break; - - default: - { - TU_LOG2(" DFU Unexpected mode: %u\r\n", mode); - } - break; - } - - ctx.init(); -} - -void dfu_d_reset(uint8_t rhport) -{ - ctx.reset(rhport); -} - -uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - return ctx.open(rhport, itf_desc, max_len); -} - -bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - return ctx.control_xfer_cb(rhport, stage, request); -} - -#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h deleted file mode 100644 index b311bb7a5..000000000 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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_AND_MODE_DEVICE_H_ -#define _TUSB_DFU_RT_AND_MODE_DEVICE_H_ - -#include "common/tusb_common.h" -#include "device/usbd.h" -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t tud_dfu_init_in_mode_cb(void); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_d_init(void); -void dfu_d_reset(uint8_t rhport); -uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_RT_AND_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 729b8e3e0..9da2e1e4f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 92e521ec9..af34e53ac 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,18 +199,6 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_DFU_RUNTIME_AND_MODE - { - DRIVER_NAME("DFU-RT-MODE") - .init = dfu_d_init, - .reset = dfu_d_reset, - .open = dfu_d_open, - .control_xfer_cb = dfu_d_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index 6eab4bee2..c9558515c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -100,12 +100,6 @@ #include "class/dfu/dfu_mode_device.h" #endif - #if CFG_TUD_DFU_RUNTIME_AND_MODE - #include "class/dfu/dfu_rt_and_mode_device.h" - #include "class/dfu/dfu_rt_device.h" - #include "class/dfu/dfu_mode_device.h" - #endif - #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 4c2204964..3cd3df9f2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -241,10 +241,6 @@ #define CFG_TUD_DFU_MODE 0 #endif -#ifndef CFG_TUD_DFU_RUNTIME_AND_MODE - #define CFG_TUD_DFU_RUNTIME_AND_MODE 0 -#endif - #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 #endif @@ -289,12 +285,6 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif -#if (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_RUNTIME) \ - || (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_MODE) \ - || (CFG_TUD_DFU_RUNTIME && CFG_TUD_DFU_MODE) - #error Only one of CFG_TUD_DFU_RUNTIME_AND_MODE, CFG_TUD_DFU_RUNTIME, and CFG_TUD_DFU_MODE can be enabled in a single build -#endif - #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 9ecb91e1bd0ac54c759ac1e91a0714c5a8c49172 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Apr 2021 23:47:28 +0700 Subject: fix build with LOG=2 --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 8b126a9f6..8a3d8ec2f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1250,7 +1250,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, count); + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); -- cgit v1.3.1 From 45e401e69df87353f528d0e3ce313d5af5a4f90c Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:42:54 -0400 Subject: Remove unused alt_setting --- src/device/usbd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index f9700811f..3d71b5e35 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -546,10 +546,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_DFU_MODE_DESC_LEN (9 + 9) // DFU runtime descriptor -// Interface number, string index, alternate setting, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _alt_setting, _attr, _timeout, _xfer_size) \ +// Interface number, string index, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt_setting, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -- cgit v1.3.1 From b15d126d594630e8ad75780f54a9218ccb5ad7b9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 24 Apr 2021 13:36:05 +0700 Subject: lpc55 improve multiple controller support port1 highspeed requires USB_RAM --- hw/bsp/lpc55/family.mk | 6 ++++-- src/device/usbd.c | 4 +++- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 17 +++++++---------- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk index c8874f571..46923cc4f 100644 --- a/hw/bsp/lpc55/family.mk +++ b/hw/bsp/lpc55/family.mk @@ -14,13 +14,15 @@ CFLAGS += \ -mfloat-abi=hard \ -mfpu=fpv5-sp-d16 \ -DCFG_TUSB_MCU=OPT_MCU_LPC55XX \ - -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data")))' \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) - CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED $(info "PORT1 High Speed") + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + + # LPC55 Highspeed Port1 can only write to USB_SRAM region + CFLAGS += -DCFG_TUSB_MEM_SECTION='__attribute__((section("m_usb_global")))' else $(info "PORT0 Full Speed") endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 8a3d8ec2f..2853b619b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -302,6 +302,8 @@ static char const* const _tusb_std_request_str[] = "Synch Frame" }; +static char const* const _tusb_speed_str[] = { "Full", "Low", "High" }; + // for usbd_control to print the name of control complete driver void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { @@ -464,7 +466,7 @@ void tud_task (void) switch ( event.event_id ) { case DCD_EVENT_BUS_RESET: - TU_LOG2("\r\n"); + TU_LOG2(": %s Speed\r\n", _tusb_speed_str[event.bus_reset.speed]); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; break; diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 090d9e602..d7efd8066 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -56,11 +56,6 @@ #include "device/dcd.h" -// only SRAM1 & USB RAM can be used for transfer. -// Used to set DATABUFSTART which is 22-bit aligned -// 2000 0000 to 203F FFFF -#define SRAM_REGION 0x20000000 - //--------------------------------------------------------------------+ // IP3511 Registers //--------------------------------------------------------------------+ @@ -161,6 +156,9 @@ typedef struct }dcd_data_t; // EP list must be 256-byte aligned +// Some MCU controller may require this variable to be placed in specific SRAM region. +// For example: LPC55s69 port1 Highspeed must be USB_RAM (0x40100000) +// Use CFG_TUSB_MEM_SECTION to place it accordingly. CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd; //--------------------------------------------------------------------+ @@ -179,7 +177,7 @@ typedef struct static const dcd_controller_t _dcd_controller[] = { { .regs = (dcd_registers_t*) USB0_BASE , .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM }, - #if FSL_FEATURE_SOC_USBHSD_COUNT + #if defined(FSL_FEATURE_SOC_USBHSD_COUNT) && FSL_FEATURE_SOC_USBHSD_COUNT { .regs = (dcd_registers_t*) USBHSD_BASE, .max_speed = TUSB_SPEED_HIGH, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM } #endif }; @@ -203,9 +201,9 @@ static inline uint16_t get_buf_offset(void const * buffer) return ( (addr >> 6) & 0xFFFFUL ) ; } -static inline uint8_t ep_addr2id(uint8_t endpoint_addr) +static inline uint8_t ep_addr2id(uint8_t ep_addr) { - return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_IN_MASK) ? 1 : 0); + return 2*(ep_addr & 0x0F) + ((ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0); } //--------------------------------------------------------------------+ @@ -216,8 +214,7 @@ void dcd_init(uint8_t rhport) dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep; - dcd_reg->DATABUFSTART = SRAM_REGION; // 22-bit alignment - + dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, 22); // 22-bit alignment dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt dcd_reg->INTEN = INT_DEVICE_STATUS_MASK; dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | -- cgit v1.3.1 From 2666e1efec20d78f8f74c23cdbb7977737b8d956 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 2 May 2021 01:46:22 +0700 Subject: add tuh_inited() and tud_inited() --- src/device/usbd.c | 19 ++++++++++++++++--- src/device/usbd.h | 3 +++ src/host/usbh.c | 14 ++++++++++++++ src/host/usbh.h | 3 +++ 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 2853b619b..fe18b21b3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -44,6 +44,10 @@ //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ + +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xFFu }; + typedef struct { struct TU_ATTR_PACKED @@ -76,9 +80,6 @@ typedef struct static usbd_device_t _usbd_dev; -// Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xFFu }; - //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ @@ -241,6 +242,8 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) // DCD Event //--------------------------------------------------------------------+ +static bool _initialized = false; + // Event queue // OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); @@ -368,8 +371,16 @@ bool tud_connect(void) //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ +bool tud_inited(void) +{ + return _initialized; +} + bool tud_init (void) { + // skip if already initialized + if (_initialized) return _initialized; + TU_LOG2("USBD init\r\n"); tu_varclr(&_usbd_dev); @@ -402,6 +413,8 @@ bool tud_init (void) dcd_init(TUD_OPT_RHPORT); dcd_int_enable(TUD_OPT_RHPORT); + _initialized = true; + return true; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 7c50a6db0..10fbe0bf1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -43,6 +43,9 @@ extern "C" { // Init device stack bool tud_init (void); +// Check if device stack is already initialized +bool tud_inited(void); + // Task function should be called in main/rtos loop void tud_task (void); diff --git a/src/host/usbh.c b/src/host/usbh.c index 86da97bb8..411945fdb 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -121,6 +121,8 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static bool _initialized = false; + // including zero-address CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; @@ -170,8 +172,19 @@ void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ + +bool tuh_inited(void) +{ + return _initialized; +} + bool tuh_init(void) { + // skip if already initialized + if (_initialized) return _initialized; + + TU_LOG2("USBH init\r\n"); + tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); //------------- Enumeration & Reporter Task init -------------// @@ -202,6 +215,7 @@ bool tuh_init(void) TU_ASSERT(hcd_init(TUH_OPT_RHPORT)); hcd_int_enable(TUH_OPT_RHPORT); + _initialized = true; return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index a05010b36..732a4b66e 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -78,6 +78,9 @@ typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request // Init host stack bool tuh_init(void); +// Check if host stack is already initialized +bool tuh_inited(void); + // Task function should be called in main/rtos loop void tuh_task(void); -- cgit v1.3.1 From 3a7f8b3ac3988eeb653ada6e3efdd7acb68fbe0f Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 17:32:52 +0700 Subject: separte tusb_init/inited() to tud/tuh init/inited add rhport to tud_init() --- src/device/usbd.c | 14 +++++++------- src/device/usbd.h | 2 +- src/host/usbh.c | 14 +++++++------- src/host/usbh.h | 2 +- src/tusb.c | 27 +++++++++++++++------------ 5 files changed, 31 insertions(+), 28 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index fe18b21b3..280235911 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -242,7 +242,7 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) // DCD Event //--------------------------------------------------------------------+ -static bool _initialized = false; +static bool _usbd_initialized = false; // Event queue // OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) @@ -373,13 +373,13 @@ bool tud_connect(void) //--------------------------------------------------------------------+ bool tud_inited(void) { - return _initialized; + return _usbd_initialized; } -bool tud_init (void) +bool tud_init (uint8_t rhport) { // skip if already initialized - if (_initialized) return _initialized; + if (_usbd_initialized) return _usbd_initialized; TU_LOG2("USBD init\r\n"); @@ -410,10 +410,10 @@ bool tud_init (void) } // Init device controller driver - dcd_init(TUD_OPT_RHPORT); - dcd_int_enable(TUD_OPT_RHPORT); + dcd_init(rhport); + dcd_int_enable(rhport); - _initialized = true; + _usbd_initialized = true; return true; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 10fbe0bf1..c0bec9566 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -41,7 +41,7 @@ extern "C" { //--------------------------------------------------------------------+ // Init device stack -bool tud_init (void); +bool tud_init (uint8_t rhport); // Check if device stack is already initialized bool tud_inited(void); diff --git a/src/host/usbh.c b/src/host/usbh.c index 411945fdb..5132d7e93 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -121,7 +121,7 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static bool _initialized = false; +static bool _usbh_initialized = false; // including zero-address CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; @@ -175,13 +175,13 @@ void osal_task_delay(uint32_t msec) bool tuh_inited(void) { - return _initialized; + return _usbh_initialized; } -bool tuh_init(void) +bool tuh_init(uint8_t rhport) { // skip if already initialized - if (_initialized) return _initialized; + if (_usbh_initialized) return _usbh_initialized; TU_LOG2("USBH init\r\n"); @@ -212,10 +212,10 @@ bool tuh_init(void) usbh_class_drivers[drv_id].init(); } - TU_ASSERT(hcd_init(TUH_OPT_RHPORT)); - hcd_int_enable(TUH_OPT_RHPORT); + TU_ASSERT(hcd_init(rhport)); + hcd_int_enable(rhport); - _initialized = true; + _usbh_initialized = true; return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 732a4b66e..809ffd40b 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -76,7 +76,7 @@ typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request //--------------------------------------------------------------------+ // Init host stack -bool tuh_init(void); +bool tuh_init(uint8_t rhport); // Check if host stack is already initialized bool tuh_inited(void); diff --git a/src/tusb.c b/src/tusb.c index 31452e897..0350fa1de 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -30,8 +30,6 @@ #include "tusb.h" -static bool _initialized = false; - // TODO clean up #if TUSB_OPT_DEVICE_ENABLED #include "device/usbd_pvt.h" @@ -39,25 +37,30 @@ static bool _initialized = false; bool tusb_init(void) { - // skip if already initialized - if (_initialized) return true; - -#if TUSB_OPT_HOST_ENABLED - TU_ASSERT( tuh_init() ); // init host stack -#endif - #if TUSB_OPT_DEVICE_ENABLED - TU_ASSERT ( tud_init() ); // init device stack + TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); // init device stack #endif - _initialized = true; +#if TUSB_OPT_HOST_ENABLED + TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); // init host stack +#endif return true; } bool tusb_inited(void) { - return _initialized; + bool ret = false; + +#if TUSB_OPT_DEVICE_ENABLED + ret = ret || tud_inited(); +#endif + +#if TUSB_OPT_HOST_ENABLED + ret = ret || tuh_inited(); +#endif + + return ret; } /*------------------------------------------------------------------*/ -- cgit v1.3.1 From 791efecfdfd650e7287388e3f3210b18f7262934 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 00:11:20 +0700 Subject: add tuh_device_ready() --- src/device/usbd.h | 1 + src/host/usbh.h | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index c0bec9566..c707cecfc 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -70,6 +70,7 @@ bool tud_mounted(void); bool tud_suspended(void); // Check if device is ready to transfer +TU_ATTR_ALWAYS_INLINE static inline bool tud_ready(void) { return tud_mounted() && !tud_suspended(); diff --git a/src/host/usbh.h b/src/host/usbh.h index e503ef8fb..590c8a359 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -90,7 +90,17 @@ extern void hcd_int_handler(uint8_t rhport); tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); +// Check if device is configured bool tuh_device_configured(uint8_t dev_addr); + +// Check if device is ready to communicate with +TU_ATTR_ALWAYS_INLINE +static inline bool tuh_device_ready(uint8_t dev_addr) +{ + return tuh_device_configured(dev_addr); +} + +// Carry out control transfer bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ -- cgit v1.3.1 From db8ea7ea1c48a04fff6446df294123690dcb7012 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 12:21:12 +0700 Subject: clean up --- src/device/usbd.c | 3 +- src/host/usbh.c | 201 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 107 insertions(+), 97 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 280235911..9fddbc299 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1090,7 +1090,7 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_ } //--------------------------------------------------------------------+ -// Helper +// USBD API For Class Driver //--------------------------------------------------------------------+ // Parse consecutive endpoint descriptors (IN & OUT) @@ -1184,7 +1184,6 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) #if CFG_TUSB_OS != OPT_OS_NONE // pre-check to help reducing mutex lock TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index f1c386a4d..ac0b654ef 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -135,20 +135,11 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); +static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - return _usbh_devices[dev_addr].rhport; -} - -uint8_t* usbh_get_enum_buf(void) -{ - return _usbh_ctrl_buf; -} - //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -223,6 +214,109 @@ bool tuh_init(uint8_t rhport) return true; } +/* USB Host Driver task + * This top level thread manages all host controller event and delegates events to class-specific drivers. + * This should be called periodically within the mainloop or rtos thread. + * + @code + int main(void) + { + application_init(); + tusb_init(); + + while(1) // the mainloop + { + application_code(); + tuh_task(); // tinyusb host task + } + } + @endcode + */ +void tuh_task(void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return; + + // Loop until there is no more events in the queue + while (1) + { + hcd_event_t event; + if ( !osal_queue_receive(_usbh_q, &event) ) return; + + switch (event.event_id) + { + case HCD_EVENT_DEVICE_ATTACH: + // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating + // one device before enumerating another one. + TU_LOG2("USBH DEVICE ATTACH\r\n"); + enum_new_device(&event); + break; + + case HCD_EVENT_DEVICE_REMOVE: + TU_LOG2("USBH DEVICE REMOVED\r\n"); + process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); + + #if CFG_TUH_HUB + // TODO remove + if ( event.connection.hub_addr != 0) + { + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( event.connection.hub_addr ); + } + #endif + break; + + case HCD_EVENT_XFER_COMPLETE: + { + usbh_device_t* dev = &_usbh_devices[event.dev_addr]; + 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); + + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + dev->ep_status[epnum][ep_dir].busy = false; + dev->ep_status[epnum][ep_dir].claimed = 0; + + if ( 0 == epnum ) + { + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } + } + break; + + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// USBH API For Class Driver +//--------------------------------------------------------------------+ + +uint8_t usbh_get_rhport(uint8_t dev_addr) +{ + return _usbh_devices[dev_addr].rhport; +} + +uint8_t* usbh_get_enum_buf(void) +{ + return _usbh_ctrl_buf; +} + +//------------- Endpoint API -------------// + bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -278,6 +372,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { usbh_device_t* dev = &_usbh_devices[dev_addr]; + TU_LOG2(" Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes); return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); } @@ -387,7 +482,7 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) // a device unplugged on hostid, hub_addr, hub_port // return true if found and unmounted device, false if cannot find -static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) +void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++) @@ -420,90 +515,6 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ } } -/* USB Host Driver task - * This top level thread manages all host controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - * - @code - int main(void) - { - application_init(); - tusb_init(); - - while(1) // the mainloop - { - application_code(); - tuh_task(); // tinyusb host task - } - } - @endcode - */ -void tuh_task(void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return; - - // Loop until there is no more events in the queue - while (1) - { - hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event) ) return; - - switch (event.event_id) - { - case HCD_EVENT_DEVICE_ATTACH: - // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating - // one device before enumerating another one. - TU_LOG2("USBH DEVICE ATTACH\r\n"); - enum_new_device(&event); - break; - - case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("USBH DEVICE REMOVED\r\n"); - usbh_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); - - #if CFG_TUH_HUB - // TODO remove - if ( event.connection.hub_addr != 0) - { - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( event.connection.hub_addr ); - } - #endif - break; - - case HCD_EVENT_XFER_COMPLETE: - { - usbh_device_t* dev = &_usbh_devices[event.dev_addr]; - 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); - - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - - if ( 0 == epnum ) - { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else - { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - } - } - break; - - case USBH_EVENT_FUNC_CALL: - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: break; - } - } -} - //--------------------------------------------------------------------+ // INTERNAL HELPER //--------------------------------------------------------------------+ -- cgit v1.3.1 From 4f033321189eb572c870d08281dd06e044c7597e Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 20:14:01 +0700 Subject: clean up --- src/device/dcd.h | 6 ------ src/host/hcd.h | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 22 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 1e5b3ff1e..71e88054c 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -24,10 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbd - * \defgroup group_dcd Device Controller Driver (DCD) - * @{ */ - #ifndef _TUSB_DCD_H_ #define _TUSB_DCD_H_ @@ -168,5 +164,3 @@ extern void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t x #endif #endif /* _TUSB_DCD_H_ */ - -/// @} diff --git a/src/host/hcd.h b/src/host/hcd.h index a470a45e8..ba6a9c5ca 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -24,14 +24,10 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbh - * \defgroup Group_HCD Host Controller Driver (HCD) - * @{ */ - #ifndef _TUSB_HCD_H_ #define _TUSB_HCD_H_ -#include +#include "common/tusb_common.h" #ifdef __cplusplus extern "C" { @@ -95,27 +91,46 @@ enum { #endif //--------------------------------------------------------------------+ -// Controller & Port API +// Controller API //--------------------------------------------------------------------+ + +// Initialize controller to host mode bool hcd_init(uint8_t rhport); + +// Interrupt Handler void hcd_int_handler(uint8_t rhport); + +// Enable USB interrupt void hcd_int_enable (uint8_t rhport); + +// Disable USB interrupt void hcd_int_disable(uint8_t rhport); // Get micro frame number (125 us) uint32_t hcd_uframe_number(uint8_t rhport); // Get frame number (1ms) -static inline uint32_t hcd_frame_number(uint8_t rhport) +TU_ATTR_ALWAYS_INLINE static inline +uint32_t hcd_frame_number(uint8_t rhport) { return hcd_uframe_number(rhport) >> 3; } -/// return the current connect status of roothub port -bool hcd_port_connect_status(uint8_t hostid); -void hcd_port_reset(uint8_t hostid); +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport); + +// Reset USB bus on the port +void hcd_port_reset(uint8_t rhport); + +// TODO implement later void hcd_port_reset_end(uint8_t rhport); -tusb_speed_t hcd_port_speed_get(uint8_t hostid); + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport); // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr); @@ -123,6 +138,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ // Endpoints API //--------------------------------------------------------------------+ + bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); @@ -134,14 +150,12 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); //--------------------------------------------------------------------+ -// PIPE API +// PIPE API - TODO remove later //--------------------------------------------------------------------+ // TODO control xfer should be used via usbh layer bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -// tusb_error_t hcd_pipe_cancel(); - //--------------------------------------------------------------------+ // Event API (implemented by stack) //--------------------------------------------------------------------+ @@ -163,5 +177,3 @@ extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t #endif #endif /* _TUSB_HCD_H_ */ - -/// @} -- cgit v1.3.1 From faa31152b4473166e099fc02500534018ce8c465 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 May 2021 20:25:44 +0700 Subject: rename usbd_edpt_iso_xfer to usbd_edpt_xfer_fifo --- src/class/audio/audio_device.c | 6 +++--- src/device/usbd.c | 2 +- src/device/usbd_pvt.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 72533013c..3afe6ce3f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -548,7 +548,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif #endif @@ -852,7 +852,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); #else // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); #endif #endif @@ -1611,7 +1611,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if USE_LINEAR_BUFFER_RX TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif } diff --git a/src/device/usbd.c b/src/device/usbd.c index 8454a2951..71c5d4e6c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1271,7 +1271,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 44310f022..c42bfd97b 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. -- cgit v1.3.1 From c7cecf28c8bd409c3032a11180333654c90020d4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 00:13:07 +0700 Subject: clean up --- README.md | 2 +- src/common/tusb_fifo.h | 13 ++++++------- src/device/usbd.h | 4 ++-- src/device/usbd_pvt.h | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src/device') diff --git a/README.md b/README.md index bef49eea4..f7b2cd811 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Supports multiple device configurations by dynamically changing usb descriptors. TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as CDC FIFO. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box. -- **No OS** : Disabling USB IRQ is used as way to provide mutex +- **No OS** - **FreeRTOS** - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example) diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 8d73911f0..1f9da94d1 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -53,9 +53,6 @@ extern "C" { #define tu_fifo_mutex_t osal_mutex_t #endif -/** \struct tu_fifo_t - * \brief Simple Circular FIFO - */ typedef struct { uint8_t* buffer ; ///< buffer pointer @@ -104,7 +101,8 @@ bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); #if CFG_FIFO_MUTEX -static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) +TU_ATTR_ALWAYS_INLINE static inline +void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) { f->mutex_wr = write_mutex_hdl; f->mutex_rd = read_mutex_hdl; @@ -129,15 +127,16 @@ uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); -static inline uint16_t tu_fifo_depth(tu_fifo_t* f) +static inline +uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; } // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! -void tu_fifo_advance_write_pointer (tu_fifo_t *f, uint16_t n); -void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); +void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies // to handle a possible wrapping part. These functions deliver a pointer to start diff --git a/src/device/usbd.h b/src/device/usbd.h index 53519c4de..3857295d7 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -70,8 +70,8 @@ bool tud_mounted(void); bool tud_suspended(void); // Check if device is ready to transfer -TU_ATTR_ALWAYS_INLINE -static inline bool tud_ready(void) +TU_ATTR_ALWAYS_INLINE static inline +bool tud_ready(void) { return tud_mounted() && !tud_suspended(); } diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index c42bfd97b..65fdadf51 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -94,7 +94,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); // Check if endpoint is stalled bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); -static inline +TU_ATTR_ALWAYS_INLINE static inline bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); -- cgit v1.3.1 From 9736e54734a85c03d9055c24414e23f112a67968 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 17:40:39 +0700 Subject: include clean up --- src/class/audio/audio_device.c | 3 +- src/class/audio/audio_device.h | 4 --- src/class/bth/bth_device.c | 1 - src/class/cdc/cdc_device.c | 4 ++- src/class/cdc/cdc_device.h | 1 - src/class/dfu/dfu_device.c | 4 ++- src/class/dfu/dfu_device.h | 2 -- src/class/dfu/dfu_rt_device.c | 4 ++- src/class/dfu/dfu_rt_device.h | 2 -- src/class/hid/hid_device.c | 5 +-- src/class/hid/hid_device.h | 2 -- src/class/midi/midi_device.c | 5 +-- src/class/midi/midi_device.h | 3 -- src/class/msc/msc_device.c | 5 +-- src/class/msc/msc_device.h | 72 +++++++++++++++++----------------------- src/class/net/net_device.c | 4 ++- src/class/net/net_device.h | 1 - src/class/usbtmc/usbtmc_device.c | 8 ++--- src/class/vendor/vendor_device.c | 4 ++- src/class/vendor/vendor_device.h | 1 - src/common/tusb_common.h | 5 +-- src/device/dcd.h | 1 + 22 files changed, 62 insertions(+), 79 deletions(-) (limited to 'src/device') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 3afe6ce3f..8e4420ed0 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -55,9 +55,10 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ +#include "device/usbd.h" #include "device/usbd_pvt.h" + #include "audio_device.h" -//#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index b8e6ef9c0..5a469523c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -28,10 +28,6 @@ #ifndef _TUSB_AUDIO_DEVICE_H_ #define _TUSB_AUDIO_DEVICE_H_ -#include "assert.h" -#include "common/tusb_common.h" -#include "device/usbd.h" - #include "audio.h" //--------------------------------------------------------------------+ diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 481dc134e..1d27ae7c5 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -32,7 +32,6 @@ // INCLUDE //--------------------------------------------------------------------+ #include "bth_device.h" -#include #include //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f5853fddb..cac811c45 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC) -#include "cdc_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "cdc_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 986585c5b..7ff757add 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -28,7 +28,6 @@ #define _TUSB_CDC_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #include "cdc.h" //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8496cb02b..81045ff7b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) -#include "dfu_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "dfu_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index c45c436c5..9a09a46b1 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_DFU_DEVICE_H_ #define _TUSB_DFU_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "dfu.h" #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index faeae9b68..07e6f30f3 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) -#include "dfu_rt_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "dfu_rt_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 0e5fd005a..babaa8214 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_DFU_RT_DEVICE_H_ #define _TUSB_DFU_RT_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "dfu.h" #ifdef __cplusplus diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 0d9cdb22b..c7f5d04ec 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -31,10 +31,11 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "hid_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "hid_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 61274be4d..beb755888 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_HID_DEVICE_H_ #define _TUSB_HID_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "hid.h" #ifdef __cplusplus diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 2c50bc4f3..953ca26e6 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -31,10 +31,11 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "midi_device.h" -#include "class/audio/audio.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "midi_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 67f03930c..211edc8d1 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -27,9 +27,6 @@ #ifndef _TUSB_MIDI_DEVICE_H_ #define _TUSB_MIDI_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" - #include "class/audio/audio.h" #include "midi.h" diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 539941935..9b06b7a33 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -28,11 +28,12 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC) -#include "common/tusb_common.h" -#include "msc_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" #include "device/dcd.h" // for faking dcd_event_xfer_complete +#include "msc_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 469f2f2f7..8f90ef4ad 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -28,7 +28,6 @@ #define _TUSB_MSC_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #include "msc.h" #ifdef __cplusplus @@ -51,53 +50,45 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); -/** \addtogroup ClassDriver_MSC - * @{ - * \defgroup MSC_Device Device - * @{ */ +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ +// Set SCSI sense response bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); //--------------------------------------------------------------------+ // Application Callbacks (WEAK is optional) //--------------------------------------------------------------------+ -/** - * Invoked when received \ref SCSI_CMD_READ_10 command - * \param[in] lun Logical unit number - * \param[in] lba Logical Block Address to be read - * \param[in] offset Byte offset from LBA - * \param[out] buffer Buffer which application need to update with the response data. - * \param[in] bufsize Requested bytes - * - * \return Number of byte read, if it is less than requested bytes by \a \b bufsize. Tinyusb will transfer - * this amount first and invoked this again for remaining data. - * - * \retval zero Indicate application is not ready yet to response e.g disk I/O is not complete. - * tinyusb will invoke this callback with the same parameters again some time later. - * - * \retval negative Indicate error e.g reading disk I/O. tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ +// Invoked when received SCSI READ10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If +// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. +// +// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); -/** - * Invoked when received \ref SCSI_CMD_WRITE_10 command - * \param[in] lun Logical unit number - * \param[in] lba Logical Block Address to be write - * \param[in] offset Byte offset from LBA - * \param[out] buffer Buffer which holds written data. - * \param[in] bufsize Requested bytes - * - * \return Number of byte written, if it is less than requested bytes by \a \b bufsize. Tinyusb will proceed with - * other work and invoked this again with adjusted parameters. - * - * \retval zero Indicate application is not ready yet e.g disk I/O is not complete. - * Tinyusb will invoke this callback with the same parameters again some time later. - * - * \retval negative Indicate error writing disk I/O. Tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ +// Invoked when received SCSI WRITE10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If +// - write < bufsize : callback invoked again with remaining data later on. +// +// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. +// +// TODO change buffer to const uint8_t* int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); // Invoked when received SCSI_CMD_INQUIRY @@ -152,9 +143,6 @@ TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[1 // Hook to make a mass storage device read-only. TODO remove TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); -/** @} */ -/** @} */ - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index ce1131223..9d9719ce4 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -29,8 +29,10 @@ #if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET ) -#include "net_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" + +#include "net_device.h" #include "rndis_protocol.h" void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 38c47d647..f5f0cd8f1 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -28,7 +28,6 @@ #ifndef _TUSB_NET_DEVICE_H_ #define _TUSB_NET_DEVICE_H_ -#include "common/tusb_common.h" #include "device/usbd.h" #include "class/cdc/cdc.h" diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d5f8fe41d..c1ee49f45 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -77,15 +77,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) -#include -#include "usbtmc.h" -#include "usbtmc_device.h" #include "device/usbd.h" -#include "osal/osal.h" - -// FIXME: I shouldn't need to include _pvt headers, but it is necessary for usbd_edpt_xfer, _stall, and _busy #include "device/usbd_pvt.h" +#include "usbtmc_device.h" + #ifdef xDEBUG #include "uart_util.h" static char logMsg[150]; diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 5fc7dd569..081aac9f6 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR) -#include "vendor_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "vendor_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 2c3d79a3d..6d9c784c0 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -28,7 +28,6 @@ #define _TUSB_VENDOR_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #ifndef CFG_TUD_VENDOR_EPSIZE #define CFG_TUD_VENDOR_EPSIZE 64 diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 88e85c9e0..1ebd8dd61 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -72,10 +72,11 @@ #include "tusb_option.h" #include "tusb_compiler.h" #include "tusb_verify.h" -#include "tusb_error.h" // TODO remove -#include "tusb_timeout.h" #include "tusb_types.h" +#include "tusb_error.h" // TODO remove +#include "tusb_timeout.h" // TODO remove + //------------- Mem -------------// #define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) diff --git a/src/device/dcd.h b/src/device/dcd.h index 71e88054c..e17c62d4e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -28,6 +28,7 @@ #define _TUSB_DCD_H_ #include "common/tusb_common.h" +#include "osal/osal.h" #include "common/tusb_fifo.h" #ifdef __cplusplus -- cgit v1.3.1 From b4f092ec74d85d4e5567ebb45e1bd0dec20f0e02 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Sat, 29 May 2021 21:23:39 +0200 Subject: Adaptations for Renesas CCRX toolchain and Rx72N controller performed --- src/class/cdc/cdc.h | 48 ++++++++++++-- src/class/cdc/cdc_device.c | 23 +++++-- src/class/cdc/cdc_device.h | 57 ++++++++++++++++ src/common/tusb_compiler.h | 92 ++++++++++++++++++++++++-- src/common/tusb_types.h | 39 ++++++++++- src/device/dcd.h | 42 ++++++++++-- src/device/usbd.c | 67 ++++++++++++------- src/device/usbd.h | 74 +++++++++++++++++++-- src/device/usbd_control.c | 15 ++++- src/device/usbd_pvt.h | 11 ++++ src/osal/osal_freertos.h | 25 +++++++ src/portable/renesas/usba/dcd_usba.c | 122 ++++++++++++++++++++++++++++------- src/tusb_option.h | 1 + 13 files changed, 543 insertions(+), 73 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f59bf0f1a..e5af9fc0c 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -216,6 +216,7 @@ typedef enum //--------------------------------------------------------------------+ /// Header Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -223,8 +224,10 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal }cdc_desc_func_header_t; +TU_PACK_STRUCT_END /// Union Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -233,17 +236,21 @@ typedef struct TU_ATTR_PACKED uint8_t bControlInterface ; ///< Interface number of Communication Interface uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; +TU_PACK_STRUCT_END #define cdc_desc_func_union_n_t(no_slave)\ - struct TU_ATTR_PACKED { \ + TU_PACK_STRUCT_BEGIN \ + struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ uint8_t bDescriptorSubType ;\ uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ -} +} \ +TU_PACK_STRUCT_END /// Country Selection Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -252,15 +259,18 @@ typedef struct TU_ATTR_PACKED uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; +TU_PACK_STRUCT_END #define cdc_desc_func_country_selection_n_t(no_country) \ - struct TU_ATTR_PACKED {\ + TU_PACK_STRUCT_BEGIN \ + struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ uint8_t bDescriptorSubType ;\ uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ -} +} \ +TU_PACK_STRUCT_END //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS @@ -268,22 +278,28 @@ typedef struct TU_ATTR_PACKED /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. uint8_t TU_RESERVED : 6; } bmCapabilities; + TU_BIT_FIELD_ORDER_END uint8_t bDataInterface; }cdc_desc_func_call_management_t; +TU_PACK_STRUCT_END +TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. @@ -292,11 +308,14 @@ typedef struct TU_ATTR_PACKED uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; +TU_BIT_FIELD_ORDER_END +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -304,25 +323,31 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ cdc_acm_capability_t bmCapabilities ; }cdc_desc_func_acm_t; +TU_PACK_STRUCT_END /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. uint8_t TU_RESERVED : 5; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_direct_line_management_t; +TU_PACK_STRUCT_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, /// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -331,31 +356,38 @@ typedef struct TU_ATTR_PACKED uint8_t bRingerVolSteps ; uint8_t bNumRingerPatterns ; }cdc_desc_func_telephone_ringer_t; +TU_PACK_STRUCT_END /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; uint8_t TU_RESERVED : 5; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_operational_modes_t; +TU_PACK_STRUCT_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. @@ -365,7 +397,9 @@ typedef struct TU_ATTR_PACKED uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification uint32_t TU_RESERVED : 26; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_call_state_reporting_capabilities_t; +TU_PACK_STRUCT_END static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { @@ -375,6 +409,7 @@ static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint32_t bit_rate; @@ -382,15 +417,20 @@ typedef struct TU_ATTR_PACKED uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); +TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. uint16_t half_duplex_carrier_control : 1; uint16_t : 14; } cdc_line_control_state_t; +TU_BIT_FIELD_ORDER_END +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f5853fddb..cf2ec64c8 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -31,6 +31,15 @@ #include "cdc_device.h" #include "device/usbd_pvt.h" +#if defined(TU_HAS_NO_ATTR_WEAK) +static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_cb))(uint8_t) = TUD_CDC_RX_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb))(uint8_t, char) = TUD_CDC_RX_WANTED_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb))(uint8_t) = TUD_CDC_TX_COMPLETE_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_line_state_cb))(uint8_t, bool, bool) = TUD_CDC_LINE_STATE_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_line_coding_cb))(uint8_t, cdc_line_coding_t const*) = TUD_CDC_LINE_CODING_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_send_break_cb))(uint8_t, uint16_t) = TUD_CDC_SEND_BREAK_CB; +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -359,7 +368,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK) { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + if ( MAKE_WEAK_FUNC(tud_cdc_line_coding_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_coding_cb)(itf, &p_cdc->line_coding); } break; @@ -394,7 +403,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + if ( MAKE_WEAK_FUNC(tud_cdc_line_state_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_state_cb)(itf, dtr, rts); } break; case CDC_REQUEST_SEND_BREAK: @@ -405,7 +414,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t else if (stage == CONTROL_STAGE_ACK) { TU_LOG2(" Send Break\r\n"); - if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + if ( MAKE_WEAK_FUNC(tud_cdc_send_break_cb) ) MAKE_WEAK_FUNC(tud_cdc_send_break_cb)(itf, request->wValue); } break; @@ -436,19 +445,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) + if ( MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb) && (((signed char) p_cdc->wanted_char) != -1) ) { for ( uint32_t i = 0; i < xferred_bytes; i++ ) { if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb)(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); + if (MAKE_WEAK_FUNC(tud_cdc_rx_cb) && !tu_fifo_empty(&p_cdc->rx_ff) ) MAKE_WEAK_FUNC(tud_cdc_rx_cb)(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); @@ -460,7 +469,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( ep_addr == p_cdc->ep_in ) { // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); + if ( MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb) ) MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb)(itf); if ( 0 == tud_cdc_n_write_flush(itf) ) { diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 986585c5b..ed816b707 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -130,6 +130,7 @@ static inline bool tud_cdc_write_clear (void); // Application Callback API (weak is optional) //--------------------------------------------------------------------+ +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); @@ -148,6 +149,62 @@ TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p // Invoked when received send break TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); +#else + #if ADD_WEAK_FUNC_TUD_CDC_RX_CB + #define TUD_CDC_RX_CB tud_cdc_rx_cb + #endif + #ifndef TUD_CDC_RX_CB + #define TUD_CDC_RX_CB NULL + #else + extern void TUD_CDC_RX_CB(uint8_t itf); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB + #define TUD_CDC_RX_WANTED_CB tud_cdc_rx_wanted_cb + #endif + #ifndef TUD_CDC_RX_WANTED_CB + #define TUD_CDC_RX_WANTED_CB NULL + #else + extern void TUD_CDC_RX_WANTED_CB(uint8_t itf, char wanted_char); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB + #define TUD_CDC_TX_COMPLETE_CB tud_cdc_tx_complete_cb + #endif + #ifndef TUD_CDC_TX_COMPLETE_CB + #define TUD_CDC_TX_COMPLETE_CB NULL + #else + extern void TUD_CDC_TX_COMPLETE_CB(uint8_t itf); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB + #define TUD_CDC_LINE_STATE_CB tud_cdc_line_state_cb + #endif + #ifndef TUD_CDC_LINE_STATE_CB + #define TUD_CDC_LINE_STATE_CB NULL + #else + extern void TUD_CDC_LINE_STATE_CB(uint8_t itf, bool dtr, bool rts); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB + #define TUD_CDC_LINE_CODING_CB tud_cdc_line_coding_cb + #endif + #ifndef TUD_CDC_LINE_CODING_CB + #define TUD_CDC_LINE_CODING_CB NULL + #else + extern void TUD_CDC_LINE_CODING_CB(uint8_t itf, cdc_line_coding_t const* p_line_coding); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB + #define TUD_CDC_SEND_BREAK_CB tud_cdc_send_break_cb + #endif + #ifndef TUD_CDC_SEND_BREAK_CB + #define TUD_CDC_SEND_BREAK_CB NULL + #else + extern void TUD_CDC_SEND_BREAK_CB(uint8_t itf, uint16_t duration_ms); + #endif +#endif + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 679060b20..508bb126e 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -48,6 +48,8 @@ #define TU_VERIFY_STATIC _Static_assert #elif defined (__cplusplus) && __cplusplus >= 201103L #define TU_VERIFY_STATIC static_assert +#elif defined(__CCRX__) + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif @@ -62,6 +64,9 @@ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ +// define the standard definition of this macro to construct a "weak" function name +#define MAKE_WEAK_FUNC(func_name) func_name + // TODO refactor since __attribute__ is supported across many compiler #if defined(__GNUC__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -73,9 +78,17 @@ #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 + #define TU_PACK_STRUCT_BEGIN + #define TU_PACK_STRUCT_END + + #define TU_BIT_FIELD_ORDER_BEGIN + #define TU_BIT_FIELD_ORDER_END + // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN + #define TU_ENDIAN_LITTLE_END #else #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif @@ -123,6 +136,77 @@ #define TU_BSWAP16(u16) (__iar_builtin_REV16(u16)) #define TU_BSWAP32(u32) (__iar_builtin_REV(u32)) + +#elif defined(__CCRX__) + #define TU_ATTR_ALIGNED(Bytes) + #define TU_ATTR_SECTION(sec_name) + #define TU_ATTR_PACKED + #define TU_ATTR_WEAK + #define TU_ATTR_ALWAYS_INLINE + #define TU_ATTR_DEPRECATED(mess) + #define TU_ATTR_UNUSED + #define TU_ATTR_USED + + #define TU_PACK_STRUCT_BEGIN _Pragma("pack") + #define TU_PACK_STRUCT_END _Pragma("packoption") + + #define TU_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") + #define TU_BIT_FIELD_ORDER_END _Pragma("bit_order") + + // Endian conversion use well-known host to network (big endian) naming + #if defined(__LIT) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN + #define TU_ENDIAN_LITTLE_END + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN _Pragma("endian little") + #define TU_ENDIAN_LITTLE_END _Pragma("endian") + #endif + + #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) + #define TU_BSWAP32(u32) (_builtin_revl(u32)) + + /* activate the "aligned" emulation, because this toolchain does not know + the aligned attribute (or something similar yet) */ + #define TU_HAS_NO_ATTR_ALIGNED + + /* activate the "weak" function emulation, because this toolchain does not + know the weak attribute (or something similar yet) */ + #define TU_HAS_NO_ATTR_WEAK + + // make sure to define away the standard definition of this macro + #undef MAKE_WEAK_FUNC + // Helper macro to construct a "weak" function name + #define MAKE_WEAK_FUNC(func_name) weak_ ## func_name + + #if defined(TU_HAS_NO_ATTR_WEAK) + // "Weak function" emulation defined in cdc_device.h + #define ADD_WEAK_FUNC_TUD_CDC_RX_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB 0 + + // "Weak function" emulation defined in usbd_pvt.h + #define ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB 0 + + // "Weak function" emulation defined in usbd.h + #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB 0 + #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB 0 + #define ADD_WEAK_FUNC_TUD_MOUNT_CB 0 + #define ADD_WEAK_FUNC_TUD_UMOUNT_CB 0 + #define ADD_WEAK_FUNC_TUD_SUSPEND_CB 0 + #define ADD_WEAK_FUNC_TUD_RESUME_CB 0 + #define ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB 0 + + // "Weak function" emulation defined in dcd.h + #define ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE 0 + #define ADD_WEAK_FUNC_DCD_EDPT_CLOSE 0 + #define ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO 0 + #endif + #else #error "Compiler attribute porting is required" #endif @@ -149,11 +233,11 @@ #define tu_htonl(u32) (u32) #define tu_ntohl(u32) (u32) - #define tu_htole16(u16) (tu_bswap16(u16)) - #define tu_le16toh(u16) (tu_bswap16(u16)) + #define tu_htole16(u16) (TU_BSWAP16(u16)) + #define tu_le16toh(u16) (TU_BSWAP16(u16)) - #define tu_htole32(u32) (tu_bswap32(u32)) - #define tu_le32toh(u32) (tu_bswap32(u32)) + #define tu_htole32(u32) (TU_BSWAP32(u32)) + #define tu_le32toh(u32) (TU_BSWAP32(u32)) #else #error Byte order is undefined diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ec58a3181..b20ea2974 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -263,6 +263,7 @@ enum //--------------------------------------------------------------------+ /// USB Device Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -283,10 +284,12 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -294,8 +297,10 @@ typedef struct TU_ATTR_PACKED uint16_t wTotalLength ; ///< Total length of data returned for this descriptor uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; +TU_PACK_STRUCT_END /// USB Configuration Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -308,10 +313,10 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); +TU_PACK_STRUCT_END /// USB Interface Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -325,8 +330,10 @@ typedef struct TU_ATTR_PACKED uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; +TU_PACK_STRUCT_END /// USB Endpoint Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -334,23 +341,32 @@ typedef struct TU_ATTR_PACKED uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t xfer : 2; uint8_t sync : 2; uint8_t usage : 2; uint8_t : 2; } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. + TU_BIT_FIELD_ORDER_END struct TU_ATTR_PACKED { +#if defined(__CCRX__) + //FIXME the original defined bit field has a problem with the CCRX toolchain, so only a size field is defined + uint16_t size; +#else uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. uint16_t hs_period_mult : 2; uint16_t TU_RESERVED : 3; +#endif }wMaxPacketSize; uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; +TU_PACK_STRUCT_END /// USB Other Speed Configuration Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -363,8 +379,10 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Same as Configuration descriptor uint8_t bMaxPower ; ///< Same as Configuration descriptor } tusb_desc_other_speed_t; +TU_PACK_STRUCT_END /// USB Device Qualifier Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -378,8 +396,10 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; +TU_PACK_STRUCT_END /// USB Interface Association Descriptor (IAD ECN) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -394,16 +414,20 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; +TU_PACK_STRUCT_END // USB String Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; +TU_PACK_STRUCT_END // USB Binary Device Object Store (BOS) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -413,8 +437,10 @@ typedef struct TU_ATTR_PACKED uint8_t PlatformCapabilityUUID[16]; uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; +TU_PACK_STRUCT_END // USB WebuSB URL Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -422,14 +448,17 @@ typedef struct TU_ATTR_PACKED uint8_t bScheme; char url[]; } tusb_desc_webusb_url_t; +TU_PACK_STRUCT_END // DFU Functional Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; union { + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t bitCanDnload : 1; uint8_t bitCanUpload : 1; @@ -437,6 +466,7 @@ typedef struct TU_ATTR_PACKED uint8_t bitWillDetach : 1; uint8_t reserved : 4; } bmAttributes; + TU_BIT_FIELD_ORDER_END uint8_t bAttributes; }; @@ -445,17 +475,21 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; +TU_PACK_STRUCT_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED{ union { + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. uint8_t type : 2; ///< Request type tusb_request_type_t. uint8_t direction : 1; ///< Direction type. tusb_dir_t } bmRequestType_bit; + TU_BIT_FIELD_ORDER_END uint8_t bmRequestType; }; @@ -465,6 +499,7 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/device/dcd.h b/src/device/dcd.h index 71e88054c..fd87686bf 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -116,24 +116,54 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Endpoint API //--------------------------------------------------------------------+ +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); - // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; -// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - // Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; +#else + #if ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE + #define DCD_EDPT0_STATUS_COMPLETE dcd_edpt0_status_complete + #endif + #ifndef DCD_EDPT0_STATUS_COMPLETE + #define DCD_EDPT0_STATUS_COMPLETE NULL + #else + extern void DCD_EDPT0_STATUS_COMPLETE(uint8_t rhport, tusb_control_request_t const * request); + #endif + + #if ADD_WEAK_FUNC_DCD_EDPT_CLOSE + #define DCD_EDPT_CLOSE dcd_edpt_close + #endif + #ifndef DCD_EDPT_CLOSE + #define DCD_EDPT_CLOSE NULL + #else + extern void DCD_EDPT_CLOSE(uint8_t rhport, uint8_t ep_addr); + #endif + + #if ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO + #define DCD_EDPT_XFER_FIFO dcd_edpt_xfer_fifo + #endif + #ifndef DCD_EDPT_XFER_FIFO + #define DCD_EDPT_XFER_FIFO NULL + #else + extern void DCD_EDPT_XFER_FIFO(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); + #endif +#endif + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 8454a2951..fa86c28c7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,6 +33,19 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" +#if defined(TU_HAS_NO_ATTR_WEAK) +static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_bos_cb))(void) = TUD_DESCRIPTOR_BOS_CB; +static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb))(void) = TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB; +static void (*const MAKE_WEAK_FUNC(tud_mount_cb))(void) = TUD_MOUNT_CB; +static void (*const MAKE_WEAK_FUNC(tud_umount_cb))(void) = TUD_UMOUNT_CB; +static void (*const MAKE_WEAK_FUNC(tud_suspend_cb))(_Bool) = TUD_SUSPEND_CB; +static void (*const MAKE_WEAK_FUNC(tud_resume_cb))(void) = TUD_RESUME_CB; +static _Bool (*const MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb))(uint8_t, uint8_t, tusb_control_request_t const *) = TUD_RESUME_CB; +static usbd_class_driver_t const* (*const MAKE_WEAK_FUNC(usbd_app_driver_get_cb))(uint8_t*) = USBD_APP_DRIVER_GET_CB; +static bool (*const MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo))(uint8_t, uint8_t, tu_fifo_t *, uint16_t) = DCD_EDPT_XFER_FIFO; +static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT_CLOSE; +#endif + #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -50,6 +63,8 @@ enum { DRVID_INVALID = 0xFFu }; typedef struct { + TU_PACK_STRUCT_BEGIN + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -60,6 +75,8 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; + TU_BIT_FIELD_ORDER_END + TU_PACK_STRUCT_END volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; @@ -67,6 +84,8 @@ typedef struct uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + TU_PACK_STRUCT_BEGIN + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile bool busy : 1; @@ -75,6 +94,8 @@ typedef struct // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUD_EP_MAX][2]; + TU_BIT_FIELD_ORDER_END + TU_PACK_STRUCT_END }usbd_device_t; @@ -236,7 +257,7 @@ static uint8_t _app_driver_count = 0; static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { // Application drivers - if ( usbd_app_driver_get_cb ) + if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) { if ( drvid < _app_driver_count ) return &_app_driver[drvid]; drvid -= _app_driver_count; @@ -408,9 +429,9 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( usbd_app_driver_get_cb ) + if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) { - _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + _app_driver = MAKE_WEAK_FUNC(usbd_app_driver_get_cb)(&_app_driver_count); } // Init class drivers @@ -501,7 +522,7 @@ void tud_task (void) usbd_reset(event.rhport); // invoke callback - if (tud_umount_cb) tud_umount_cb(); + if (MAKE_WEAK_FUNC(tud_umount_cb)) MAKE_WEAK_FUNC(tud_umount_cb)(); break; case DCD_EVENT_SETUP_RECEIVED: @@ -557,12 +578,12 @@ void tud_task (void) case DCD_EVENT_SUSPEND: TU_LOG2("\r\n"); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + if (MAKE_WEAK_FUNC(tud_suspend_cb)) MAKE_WEAK_FUNC(tud_suspend_cb)(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: TU_LOG2("\r\n"); - if (tud_resume_cb) tud_resume_cb(); + if (MAKE_WEAK_FUNC(tud_resume_cb)) MAKE_WEAK_FUNC(tud_resume_cb)(); break; case DCD_EVENT_SOF: @@ -609,10 +630,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(tud_vendor_control_xfer_cb); + TU_VERIFY(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); - usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); - return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); + usbd_control_set_complete_callback(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); + return MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 @@ -831,7 +852,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Parse interface descriptor uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; + uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); while( p_desc < desc_end ) { @@ -892,7 +913,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // invoke callback - if (tud_mount_cb) tud_mount_cb(); + if (MAKE_WEAK_FUNC(tud_mount_cb)) MAKE_WEAK_FUNC(tud_mount_cb)(); return true; } @@ -949,15 +970,15 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!tud_descriptor_bos_cb) return false; + if (!MAKE_WEAK_FUNC(tud_descriptor_bos_cb)) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)MAKE_WEAK_FUNC(tud_descriptor_bos_cb)(); uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); - return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); + return tud_control_xfer(rhport, p_request, (void*) desc_bos, tu_le16toh(total_len)); } break; @@ -972,7 +993,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); + return tud_control_xfer(rhport, p_request, (void*) desc_config, tu_le16toh(total_len)); } break; @@ -995,9 +1016,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Host sends this request to ask why our device with USB BCD from 2.0 // but is running at Full/Low Speed. If not highspeed capable stall this request, // otherwise return the descriptor that could work in highspeed mode - if ( tud_descriptor_device_qualifier_cb ) + if (MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)) { - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + uint8_t const* desc_qualifier = MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)(); TU_ASSERT(desc_qualifier); // first byte of descriptor is its size @@ -1165,18 +1186,18 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) if (_usbd_dev.speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(desc_ep->wMaxPacketSize.size == 512); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) == 512); }else { // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(desc_ep->wMaxPacketSize.size <= 64); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= 64); } break; case TUSB_XFER_INTERRUPT: { uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); } break; @@ -1285,7 +1306,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) + if (MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo)(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; @@ -1348,10 +1369,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - TU_ASSERT(dcd_edpt_close, /**/); + TU_ASSERT(MAKE_WEAK_FUNC(dcd_edpt_close), /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - dcd_edpt_close(rhport, ep_addr); + MAKE_WEAK_FUNC(dcd_edpt_close(rhport, ep_addr)); return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 53519c4de..04597a215 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -103,10 +103,6 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request); // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void); -// Invoked when received GET BOS DESCRIPTOR request -// Application return pointer to descriptor -TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); - // Invoked when received GET CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index); @@ -115,6 +111,11 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); +#if !defined(TU_HAS_NO_ATTR_WEAK) +// Invoked when received GET BOS DESCRIPTOR request +// Application return pointer to descriptor +TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); + // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); @@ -135,6 +136,71 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +#else + #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB + #define TUD_DESCRIPTOR_BOS_CB tud_descriptor_bos_cb + #endif + #ifndef TUD_DESCRIPTOR_BOS_CB + #define TUD_DESCRIPTOR_BOS_CB NULL + #else + extern uint8_t const* TUD_DESCRIPTOR_BOS_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB + #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB tud_descriptor_device_qualifier_cb + #endif + #ifndef TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB + #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB NULL + #else + extern uint8_t const* TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_MOUNT_CB + #define TUD_MOUNT_CB tud_mount_cb + #endif + #ifndef TUD_MOUNT_CB + #define TUD_MOUNT_CB NULL + #else + extern void TUD_MOUNT_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_UMOUNT_CB + #define TUD_UMOUNT_CB tud_umount_cb + #endif + #ifndef TUD_UMOUNT_CB + #define TUD_UMOUNT_CB NULL + #else + extern void TUD_UMOUNT_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_SUSPEND_CB + #define TUD_SUSPEND_CB tud_suspend_cb + #endif + #ifndef TUD_SUSPEND_CB + #define TUD_SUSPEND_CB NULL + #else + extern void TUD_SUSPEND_CB(bool remote_wakeup_en); + #endif + + #if ADD_WEAK_FUNC_TUD_RESUME_CB + #define TUD_RESUME_CB tud_resume_cb + #endif + #ifndef TUD_RESUME_CB + #define TUD_RESUME_CB NULL + #else + extern void TUD_RESUME_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB + #define TUD_VENDOR_CONTROL_XFER_CB tud_vendor_control_xfer_cb + #endif + #ifndef TUD_VENDOR_CONTROL_XFER_CB + #define TUD_VENDOR_CONTROL_XFER_CB NULL + #else + extern bool TUD_VENDOR_CONTROL_XFER_CB(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + #endif +#endif + //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 724c652e6..76f999f86 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -36,6 +36,10 @@ extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif +#if defined(TU_HAS_NO_ATTR_WEAK) +static void (*const MAKE_WEAK_FUNC(dcd_edpt0_status_complete))(uint8_t, tusb_control_request_t const *) = DCD_EDPT0_STATUS_COMPLETE; +#endif + enum { EDPT_CTRL_OUT = 0x00, @@ -55,8 +59,17 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; +#if defined(TU_HAS_NO_ATTR_ALIGNED) +// Helper union to overcome the lack of the alignment attribute/pragma +static union { + uint16_t : (sizeof(uint16_t) * 8); // Alignment of at least the size of the used type + uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +} Align_usbd_ctrl_buf_; +static uint8_t *_usbd_ctrl_buf = (uint8_t*)&Align_usbd_ctrl_buf_; +#else CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +#endif //--------------------------------------------------------------------+ // Application API @@ -171,7 +184,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + if (MAKE_WEAK_FUNC(dcd_edpt0_status_complete)) MAKE_WEAK_FUNC(dcd_edpt0_status_complete)(rhport, &_ctrl_xfer.request); if (_ctrl_xfer.complete_cb) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 44310f022..1d60e5ae2 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -51,10 +51,21 @@ typedef struct void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; +#else + #if ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB + #define USBD_APP_DRIVER_GET_CB usbd_app_driver_get_cb + #endif + #ifndef USBD_APP_DRIVER_GET_CB + #define USBD_APP_DRIVER_GET_CB NULL + #else + extern usbd_class_driver_t const* USBD_APP_DRIVER_GET_CB(uint8_t* driver_count); + #endif +#endif typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 66070c273..ec33b317d 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -51,6 +51,7 @@ static inline void osal_task_delay(uint32_t msec) typedef StaticSemaphore_t osal_semaphore_def_t; typedef SemaphoreHandle_t osal_semaphore_t; +#if (configSUPPORT_STATIC_ALLOCATION == 1) //FIXME Only static API supported static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { return xSemaphoreCreateBinaryStatic(semdef); @@ -76,6 +77,7 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) return res != 0; } } +#endif static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { @@ -96,7 +98,12 @@ typedef SemaphoreHandle_t osal_mutex_t; static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { +#if (configSUPPORT_STATIC_ALLOCATION == 0) //FIXME Only static API supported + (void)mdef; + return xSemaphoreCreateMutex(); +#else return xSemaphoreCreateMutexStatic(mdef); +#endif } static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) @@ -131,7 +138,11 @@ typedef QueueHandle_t osal_queue_t; static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { +#if defined(__Tx36V5_Maincard__) + return xQueueCreate(qdef->depth, qdef->item_sz); +#else return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); +#endif } static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) @@ -139,6 +150,19 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) return xQueueReceive(qhdl, data, portMAX_DELAY); } +#if defined(__Tx36V5_Maincard__) +extern BaseType_t UsbTaskWoken; +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + if (!in_isr) { + return(xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER)); + + } else { + BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &UsbTaskWoken); + return(res != 0); + } +} +#else static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if ( !in_isr ) @@ -159,6 +183,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return res != 0; } } +#endif static inline bool osal_queue_empty(osal_queue_t qhdl) { diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 06ea1a3f9..54410ff0b 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X ) +#if TUSB_OPT_DEVICE_ENABLED && (( CFG_TUSB_MCU == OPT_MCU_RX63X ) || ( CFG_TUSB_MCU == OPT_MCU_RX72N )) #include "device/dcd.h" #include "iodefine.h" @@ -38,6 +38,7 @@ #define SYSTEM_PRCR_PRKEY (0xA5u<<8) #define USB_FIFOSEL_TX ((uint16_t)(1u<<5)) +#define USB_FIFOSEL_BIGEND ((uint16_t)(1u<<8)) #define USB_FIFOSEL_MBW_8 ((uint16_t)(0u<<10)) #define USB_FIFOSEL_MBW_16 ((uint16_t)(1u<<10)) #define USB_IS0_CTSQ ((uint16_t)(7u)) @@ -91,39 +92,47 @@ typedef struct { union { + TU_BIT_FIELD_ORDER_BEGIN struct { uint16_t : 8; uint16_t TRCLR: 1; uint16_t TRENB: 1; uint16_t : 0; }; + TU_BIT_FIELD_ORDER_END uint16_t TRE; }; uint16_t TRN; } reg_pipetre_t; typedef union { + TU_BIT_FIELD_ORDER_BEGIN struct { volatile uint16_t u8: 8; volatile uint16_t : 0; }; + TU_BIT_FIELD_ORDER_END volatile uint16_t u16; } hw_fifo_t; +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ + TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t ep : 8; /* an assigned endpoint address */ uint32_t : 0; }; + TU_BIT_FIELD_ORDER_END } pipe_state_t; +TU_PACK_STRUCT_END typedef struct { - pipe_state_t pipe[9]; + pipe_state_t pipe[10]; uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */ } dcd_data_t; @@ -135,14 +144,23 @@ CFG_TUSB_MEM_SECTION static dcd_data_t _dcd; static uint32_t disable_interrupt(void) { uint32_t pswi; +#if defined(__CCRX__) + pswi = get_psw() & 0x010000; + clrpsw_i(); +#else pswi = __builtin_rx_mvfc(0) & 0x010000; __builtin_rx_clrpsw('I'); +#endif return pswi; } static void enable_interrupt(uint32_t pswi) { +#if defined(__CCRX__) + set_psw(get_psw() | pswi); +#else __builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi); +#endif } static unsigned find_pipe(unsigned xfer) @@ -226,7 +244,7 @@ static unsigned select_pipe(unsigned num, unsigned attr) { USB0.PIPESEL.WORD = num; USB0.D0FIFOSEL.WORD = num | attr; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; + while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; return wait_for_pipe_ready(); } @@ -270,11 +288,11 @@ static int fifo_read(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size if (rem < len) len = rem; pipe->remaining = rem - len; - hw_fifo_t *reg = (hw_fifo_t*)fifo; + uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */ uintptr_t addr = pipe->addr; unsigned loop = len; while (loop--) { - *(uint8_t *)addr = reg->u8; + *(uint8_t *)addr = *reg; ++addr; } pipe->addr = addr; @@ -292,6 +310,13 @@ static void process_setup_packet(uint8_t rhport) setup_packet[1] = USB0.USBVAL; setup_packet[2] = USB0.USBINDX; setup_packet[3] = USB0.USBLENG; +#if TU_BYTE_ORDER==TU_BIG_ENDIAN + #if defined(__CCRX__) + setup_packet[0] = tu_le16toh(setup_packet[0]); + #else + //FIXME needs to implemented for other tool chains + #endif +#endif USB0.INTSTS0.WORD = ~USB_IS0_VALID; dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); } @@ -317,7 +342,11 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe_state_t *pipe = &_dcd.pipe[0]; /* configure fifo direction and access unit settings */ if (ep_addr) { /* IN, 2 bytes */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; +#else USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16; +#endif while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ; } else { /* OUT, a byte */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; @@ -329,7 +358,7 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe->remaining = total_bytes; if (ep_addr) { /* IN */ TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); - if (fifo_write(&USB0.CFIFO.WORD, pipe, 64)) { + if (fifo_write((void*)&USB0.CFIFO.WORD, pipe, 64)) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; } } @@ -350,7 +379,7 @@ static void process_edpt0_bemp(uint8_t rhport) const unsigned rem = pipe->remaining; if (rem > 64) { pipe->remaining = rem - 64; - int r = fifo_write(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + int r = fifo_write((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } @@ -363,7 +392,7 @@ static void process_edpt0_bemp(uint8_t rhport) static void process_edpt0_brdy(uint8_t rhport) { size_t len = USB0.CFIFOCTR.BIT.DTLN; - int cplt = fifo_read(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); + int cplt = fifo_read((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); if (cplt || (len < 64)) { if (2 != cplt) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; @@ -392,11 +421,16 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, USB0.PIPESEL.WORD = num; const unsigned mps = USB0.PIPEMAXP.WORD; if (dir) { /* IN */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; +#else USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; - int r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); +#endif + while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; + int r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ } else { volatile reg_pipetre_t *pt = get_pipetre(num); if (pt) { @@ -416,19 +450,25 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) { pipe_state_t *pipe = &_dcd.pipe[num]; if (tu_edpt_dir(pipe->ep)) { /* IN */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + select_pipe(num, USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND); +#else select_pipe(num, USB_FIFOSEL_MBW_16); +#endif const unsigned mps = USB0.PIPEMAXP.WORD; unsigned rem = pipe->remaining; rem -= TU_MIN(rem, mps); pipe->remaining = rem; if (rem) { int r = 0; - r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); + r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ return; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ pipe->addr = 0; pipe->remaining = 0; dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, @@ -437,18 +477,20 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); const unsigned len = ctr & USB_FIFOCTR_DTLN; const unsigned mps = USB0.PIPEMAXP.WORD; - int cplt = fifo_read(&USB0.D0FIFO.WORD, pipe, mps, len); + int cplt = fifo_read((void*)&USB0.D0FIFO.WORD, pipe, mps, len); if (cplt || (len < mps)) { if (2 != cplt) { USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ dcd_event_xfer_complete(rhport, pipe->ep, pipe->length - pipe->remaining, XFER_RESULT_SUCCESS, true); return; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ } } @@ -458,7 +500,9 @@ static void process_bus_reset(uint8_t rhport) USB0.BRDYENB.WORD = 1; USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ USB0.D1FIFOSEL.WORD = 0; + while (USB0.D1FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1CTR.WORD)); volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1TRE.WORD)); for (int i = 1; i <= 5; ++i) { @@ -485,13 +529,22 @@ static void process_set_address(uint8_t rhport) { const uint32_t addr = USB0.USBADDR.BIT.USBADDR; if (!addr) return; +#if defined(__CCRX__) + tusb_control_request_t setup_packet; + setup_packet.bmRequestType = 0; + setup_packet.bRequest = 5; + setup_packet.wValue = addr; + setup_packet.wIndex = 0; + setup_packet.wLength = 0; +#else const tusb_control_request_t setup_packet = { - .bmRequestType = 0, - .bRequest = 5, - .wValue = addr, - .wIndex = 0, - .wLength = 0, - }; + .bmRequestType = 0, + .bRequest = 5, + .wValue = addr, + .wIndex = 0, + .wLength = 0, + }; +#endif dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true); } @@ -513,7 +566,13 @@ void dcd_init(uint8_t rhport) USB0.SYSCFG.BIT.DCFM = 0; USB0.SYSCFG.BIT.USBE = 1; + USB0.PHYSLEW.LONG = 0x5; + USB.DPUSR0R.BIT.FIXPHY0 = 0u; /* USB0 Transceiver Output fixed */ +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IR(PERIB, INTB185) = 0; +#else IR(USB0, USBI0) = 0; +#endif /* Setup default control pipe */ USB0.DCPMAXP.BIT.MXPS = 64; @@ -529,13 +588,21 @@ void dcd_init(uint8_t rhport) void dcd_int_enable(uint8_t rhport) { (void)rhport; +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IEN(PERIB, INTB185) = 1; +#else IEN(USB0, USBI0) = 1; +#endif } void dcd_int_disable(uint8_t rhport) { (void)rhport; +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IEN(PERIB, INTB185) = 0; +#else IEN(USB0, USBI0) = 0; +#endif } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) @@ -574,7 +641,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) const unsigned dir = tu_edpt_dir(ep_addr); const unsigned xfer = ep_desc->bmAttributes.xfer; - const unsigned mps = ep_desc->wMaxPacketSize.size; + const unsigned mps = tu_le16toh(ep_desc->wMaxPacketSize.size); if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) { /* USBa supports up to 256 bytes */ return false; @@ -680,8 +747,8 @@ void dcd_int_handler(uint8_t rhport) (void)rhport; unsigned is0 = USB0.INTSTS0.WORD; - /* clear bits except VALID */ - USB0.INTSTS0.WORD = USB_IS0_VALID; + /* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */ + USB0.INTSTS0.WORD = ~((USB_IS0_CTRT | USB_IS0_DVST | USB_IS0_SOFR | USB_IS0_RESM | USB_IS0_VBINT) & is0) | USB_IS0_VALID; if (is0 & USB_IS0_VBINT) { if (USB0.INTSTS0.BIT.VBSTS) { dcd_connect(rhport); @@ -720,13 +787,24 @@ void dcd_int_handler(uint8_t rhport) if (is0 & USB_IS0_BRDY) { const unsigned m = USB0.BRDYENB.WORD; unsigned s = USB0.BRDYSTS.WORD & m; - USB0.BRDYSTS.WORD = 0; + /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */ + USB0.BRDYSTS.WORD = ~s; if (s & 1) { process_edpt0_brdy(rhport); s &= ~1; } while (s) { +#if defined(__CCRX__) + static const int Mod37BitPosition[] = { + -1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, + 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, + 20, 8, 19, 18 + }; + + const unsigned num = Mod37BitPosition[(-s & s) % 37]; +#else const unsigned num = __builtin_ctz(s); +#endif process_pipe_brdy(rhport, num); s &= ~TU_BIT(num); } diff --git a/src/tusb_option.h b/src/tusb_option.h index b317f7630..d04542e61 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -112,6 +112,7 @@ // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 +#define OPT_MCU_RX72N 1401 ///< Renesas RX72N /** @} */ -- cgit v1.3.1 From 13cb0160421a6a66429e99ed103afba4f1c345ce Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 16:48:20 +0700 Subject: add usbh_classdriver.h --- src/class/cdc/cdc_host.c | 2 ++ src/class/hid/hid_host.c | 2 ++ src/class/msc/msc_host.c | 2 ++ src/device/usbd_pvt.h | 2 +- src/host/hub.c | 1 + src/host/usbh.c | 7 ++--- src/host/usbh.h | 43 ++----------------------- src/host/usbh_classdriver.h | 76 +++++++++++++++++++++++++++++++++++++++++++++ src/host/usbh_hcd.h | 6 ---- 9 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 src/host/usbh_classdriver.h (limited to 'src/device') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index facf86d56..dbe5341e9 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "cdc_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 83f3f3039..ec50f55f9 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "hid_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 205f0fd2d..176403e86 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -29,6 +29,8 @@ #if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "msc_host.h" //--------------------------------------------------------------------+ diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 65fdadf51..b8d34d7b6 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -34,7 +34,7 @@ #endif //--------------------------------------------------------------------+ -// Class Drivers +// Class Driver API //--------------------------------------------------------------------+ typedef struct diff --git a/src/host/hub.c b/src/host/hub.c index f921027c7..b2761184d 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -29,6 +29,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) #include "usbh.h" +#include "usbh_classdriver.h" #include "hub.h" //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index ca0653409..ff66d5afd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -24,7 +24,7 @@ * This file is part of the TinyUSB stack. */ -#include "common/tusb_common.h" +#include "tusb_option.h" #if TUSB_OPT_HOST_ENABLED @@ -32,10 +32,9 @@ #define CFG_TUH_TASK_QUEUE_SZ 16 #endif -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ #include "tusb.h" +#include "host/usbh.h" +#include "host/usbh_classdriver.h" #include "hub.h" #include "usbh_hcd.h" diff --git a/src/host/usbh.h b/src/host/usbh.h index a9790b484..edc9e0808 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -40,27 +40,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef enum tusb_interface_status_{ - TUSB_INTERFACE_STATUS_READY = 0, - TUSB_INTERFACE_STATUS_BUSY, - TUSB_INTERFACE_STATUS_COMPLETE, - TUSB_INTERFACE_STATUS_ERROR, - TUSB_INTERFACE_STATUS_INVALID_PARA -} tusb_interface_status_t; - -typedef struct { - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - uint8_t class_code; - - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -101,30 +80,12 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, //--------------------------------------------------------------------+ //TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); -/** Callback invoked when device is mounted (configured) */ +// Invoked when device is mounted (configured) TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); -/** Callback invoked when device is unmounted (bus reset/unplugged) */ +/// Invoked when device is unmounted (bus reset/unplugged) TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); -//--------------------------------------------------------------------+ -// CLASS-USBH & INTERNAL API -// TODO move to usbh_pvt.h -//--------------------------------------------------------------------+ - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); - #ifdef __cplusplus } #endif diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h new file mode 100644 index 000000000..2b1523855 --- /dev/null +++ b/src/host/usbh_classdriver.h @@ -0,0 +1,76 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * 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_USBH_CLASSDRIVER_H_ +#define _TUSB_USBH_CLASSDRIVER_H_ + +#include "osal/osal.h" +#include "common/tusb_fifo.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver API +//--------------------------------------------------------------------+ + +typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + + uint8_t class_code; + + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); +} usbh_class_driver_t; + +//--------------------------------------------------------------------+ +// USBH Endpoint API +//--------------------------------------------------------------------+ + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index abc7fd250..b3856d6b7 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -97,12 +97,6 @@ typedef struct { extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address -//--------------------------------------------------------------------+ -// callback from HCD ISR -//--------------------------------------------------------------------+ - - - #ifdef __cplusplus } #endif -- cgit v1.3.1 From c7f51cde40afbefe3f1d57b9dbdaaca0abed424e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 17:19:21 +0700 Subject: implement usbh_edpt_busy (WIP), remove hcd_edpt_busy --- src/class/cdc/cdc_host.c | 10 +++--- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 4 +-- src/host/hcd.h | 2 -- src/host/usbh.c | 46 ++++++++++++++++++++++++++-- src/host/usbh_classdriver.h | 19 ++++++++---- src/portable/ehci/ehci.c | 6 ---- src/portable/ohci/ohci.c | 6 ---- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 26 ++++++++-------- 11 files changed, 79 insertions(+), 46 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index dbe5341e9..33f1a8ad3 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -73,13 +73,13 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) switch (pipeid) { case CDC_PIPE_NOTIFICATION: - return hcd_edpt_busy(dev_addr, p_cdc->ep_notif ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_notif ); case CDC_PIPE_DATA_IN: - return hcd_edpt_busy(dev_addr, p_cdc->ep_in ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); case CDC_PIPE_DATA_OUT: - return hcd_edpt_busy(dev_addr, p_cdc->ep_out ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); default: return false; @@ -103,7 +103,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; - if ( hcd_edpt_busy(dev_addr, ep_out) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length); } @@ -115,7 +115,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; - if ( hcd_edpt_busy(dev_addr, ep_in) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ec50f55f9..cde5e23a5 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -201,7 +201,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); // // hidh_interface_t* hid_itf = get_instance(dev_addr, instance); -// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); +// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); //} //void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 176403e86..7f98ef9b1 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -111,7 +111,7 @@ bool tuh_msc_mounted(uint8_t dev_addr) bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in); + return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ diff --git a/src/device/dcd.h b/src/device/dcd.h index e17c62d4e..63e97df96 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -122,7 +122,7 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. diff --git a/src/device/usbd.c b/src/device/usbd.c index 71c5d4e6c..2935defd0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1248,8 +1248,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return - // and usbd task can preempt and clear the busy + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() + // could return and USBD task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) diff --git a/src/host/hcd.h b/src/host/hcd.h index 8cb5b3772..7a9aadc73 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -137,8 +137,6 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); - -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index ff66d5afd..59246a663 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -314,8 +314,11 @@ uint8_t* usbh_get_enum_buf(void) return _usbh_ctrl_buf; } -//------------- Endpoint API -------------// +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +// TODO has some duplication code with device, refactor later bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -343,6 +346,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -368,11 +372,36 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + usbh_device_t* dev = &_usbh_devices[dev_addr]; - TU_LOG2(" Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes); - return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } } bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) @@ -419,6 +448,17 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return ret; } +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + return dev->ep_status[epnum][dir].busy; +} + + //--------------------------------------------------------------------+ // HCD Event Handler //--------------------------------------------------------------------+ diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 2b1523855..07480fe8e 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -52,22 +52,29 @@ typedef struct { void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; +// Call by class driver to tell USBH that it has complete the enumeration +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + //--------------------------------------------------------------------+ // USBH Endpoint API //--------------------------------------------------------------------+ -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +// Open an endpoint +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); + +// Submit a usb transfer bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); +// Check if endpoint transferring is complete +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); #ifdef __cplusplus } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index be3030676..48788ba06 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -440,12 +440,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index cbb72c726..73489c764 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -489,12 +489,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index aeee93324..b575c6afc 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -515,19 +515,19 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - // EPX is shared, so multiple device addresses and endpoint addresses share that - // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own - // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint - // on that device - pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); - struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); - assert(ep); - bool busy = ep->active; - pico_trace("busy == %d\n", busy); - return busy; -} +//bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +//{ +// // EPX is shared, so multiple device addresses and endpoint addresses share that +// // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own +// // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint +// // on that device +// pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); +// struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); +// assert(ep); +// bool busy = ep->active; +// pico_trace("busy == %d\n", busy); +// return busy; +//} bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { -- cgit v1.3.1 From 1c23462b43f47685cf0051568f4bfea5de37d563 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Fri, 11 Jun 2021 22:25:36 +0200 Subject: weak atrribute work around removed from CCRX_Port --- src/class/cdc/cdc.h | 54 ++++++++++++----------------- src/class/cdc/cdc_device.c | 23 ++++--------- src/class/cdc/cdc_device.h | 57 ------------------------------- src/common/tusb_compiler.h | 39 --------------------- src/common/tusb_types.h | 42 ++++++----------------- src/device/dcd.h | 30 ---------------- src/device/usbd.c | 61 +++++++++++++-------------------- src/device/usbd.h | 66 ------------------------------------ src/device/usbd_control.c | 6 +--- src/device/usbd_pvt.h | 12 ------- src/portable/renesas/usba/dcd_usba.c | 33 ++++++------------ 11 files changed, 74 insertions(+), 349 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index e5af9fc0c..f59690835 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -215,8 +215,9 @@ typedef enum // Class Specific Functional Descriptor (Communication Interface) //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// Header Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -224,10 +225,8 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal }cdc_desc_func_header_t; -TU_PACK_STRUCT_END /// Union Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -236,7 +235,8 @@ typedef struct TU_ATTR_PACKED uint8_t bControlInterface ; ///< Interface number of Communication Interface uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_union_n_t(no_slave)\ TU_PACK_STRUCT_BEGIN \ @@ -249,8 +249,10 @@ TU_PACK_STRUCT_END } \ TU_PACK_STRUCT_END + +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// Country Selection Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -259,7 +261,8 @@ typedef struct TU_ATTR_PACKED uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_country_selection_n_t(no_country) \ TU_PACK_STRUCT_BEGIN \ @@ -276,29 +279,28 @@ TU_PACK_STRUCT_END // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. uint8_t TU_RESERVED : 6; } bmCapabilities; - TU_BIT_FIELD_ORDER_END uint8_t bDataInterface; }cdc_desc_func_call_management_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { @@ -309,13 +311,11 @@ typedef struct TU_ATTR_PACKED uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -323,31 +323,27 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ cdc_acm_capability_t bmCapabilities ; }cdc_desc_func_acm_t; -TU_PACK_STRUCT_END /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. uint8_t TU_RESERVED : 5; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_direct_line_management_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, /// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -356,38 +352,34 @@ typedef struct TU_ATTR_PACKED uint8_t bRingerVolSteps ; uint8_t bNumRingerPatterns ; }cdc_desc_func_telephone_ringer_t; -TU_PACK_STRUCT_END /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; uint8_t TU_RESERVED : 5; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_operational_modes_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. @@ -397,9 +389,8 @@ typedef struct TU_ATTR_PACKED uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification uint32_t TU_RESERVED : 26; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_call_state_reporting_capabilities_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { @@ -409,7 +400,6 @@ static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint32_t bit_rate; @@ -417,11 +407,9 @@ typedef struct TU_ATTR_PACKED uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; -TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); -TU_PACK_STRUCT_BEGIN TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { @@ -430,7 +418,9 @@ typedef struct TU_ATTR_PACKED uint16_t : 14; } cdc_line_control_state_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) + TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 57bb804a8..cac811c45 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -33,15 +33,6 @@ #include "cdc_device.h" -#if defined(TU_HAS_NO_ATTR_WEAK) -static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_cb))(uint8_t) = TUD_CDC_RX_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb))(uint8_t, char) = TUD_CDC_RX_WANTED_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb))(uint8_t) = TUD_CDC_TX_COMPLETE_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_line_state_cb))(uint8_t, bool, bool) = TUD_CDC_LINE_STATE_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_line_coding_cb))(uint8_t, cdc_line_coding_t const*) = TUD_CDC_LINE_CODING_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_send_break_cb))(uint8_t, uint16_t) = TUD_CDC_SEND_BREAK_CB; -#endif - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -370,7 +361,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK) { - if ( MAKE_WEAK_FUNC(tud_cdc_line_coding_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_coding_cb)(itf, &p_cdc->line_coding); + if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); } break; @@ -405,7 +396,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if ( MAKE_WEAK_FUNC(tud_cdc_line_state_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_state_cb)(itf, dtr, rts); + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; case CDC_REQUEST_SEND_BREAK: @@ -416,7 +407,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t else if (stage == CONTROL_STAGE_ACK) { TU_LOG2(" Send Break\r\n"); - if ( MAKE_WEAK_FUNC(tud_cdc_send_break_cb) ) MAKE_WEAK_FUNC(tud_cdc_send_break_cb)(itf, request->wValue); + if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); } break; @@ -447,19 +438,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if ( MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb) && (((signed char) p_cdc->wanted_char) != -1) ) + if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) { for ( uint32_t i = 0; i < xferred_bytes; i++ ) { if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) { - MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb)(itf, p_cdc->wanted_char); + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (MAKE_WEAK_FUNC(tud_cdc_rx_cb) && !tu_fifo_empty(&p_cdc->rx_ff) ) MAKE_WEAK_FUNC(tud_cdc_rx_cb)(itf); + if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); @@ -471,7 +462,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( ep_addr == p_cdc->ep_in ) { // invoke transmit callback to possibly refill tx fifo - if ( MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb) ) MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb)(itf); + if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); if ( 0 == tud_cdc_n_write_flush(itf) ) { diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 389516883..7ff757add 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -129,7 +129,6 @@ static inline bool tud_cdc_write_clear (void); // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); @@ -148,62 +147,6 @@ TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p // Invoked when received send break TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); -#else - #if ADD_WEAK_FUNC_TUD_CDC_RX_CB - #define TUD_CDC_RX_CB tud_cdc_rx_cb - #endif - #ifndef TUD_CDC_RX_CB - #define TUD_CDC_RX_CB NULL - #else - extern void TUD_CDC_RX_CB(uint8_t itf); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB - #define TUD_CDC_RX_WANTED_CB tud_cdc_rx_wanted_cb - #endif - #ifndef TUD_CDC_RX_WANTED_CB - #define TUD_CDC_RX_WANTED_CB NULL - #else - extern void TUD_CDC_RX_WANTED_CB(uint8_t itf, char wanted_char); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB - #define TUD_CDC_TX_COMPLETE_CB tud_cdc_tx_complete_cb - #endif - #ifndef TUD_CDC_TX_COMPLETE_CB - #define TUD_CDC_TX_COMPLETE_CB NULL - #else - extern void TUD_CDC_TX_COMPLETE_CB(uint8_t itf); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB - #define TUD_CDC_LINE_STATE_CB tud_cdc_line_state_cb - #endif - #ifndef TUD_CDC_LINE_STATE_CB - #define TUD_CDC_LINE_STATE_CB NULL - #else - extern void TUD_CDC_LINE_STATE_CB(uint8_t itf, bool dtr, bool rts); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB - #define TUD_CDC_LINE_CODING_CB tud_cdc_line_coding_cb - #endif - #ifndef TUD_CDC_LINE_CODING_CB - #define TUD_CDC_LINE_CODING_CB NULL - #else - extern void TUD_CDC_LINE_CODING_CB(uint8_t itf, cdc_line_coding_t const* p_line_coding); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB - #define TUD_CDC_SEND_BREAK_CB tud_cdc_send_break_cb - #endif - #ifndef TUD_CDC_SEND_BREAK_CB - #define TUD_CDC_SEND_BREAK_CB NULL - #else - extern void TUD_CDC_SEND_BREAK_CB(uint8_t itf, uint16_t duration_ms); - #endif -#endif - //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 508bb126e..f77cf94ee 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -64,9 +64,6 @@ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ -// define the standard definition of this macro to construct a "weak" function name -#define MAKE_WEAK_FUNC(func_name) func_name - // TODO refactor since __attribute__ is supported across many compiler #if defined(__GNUC__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -171,42 +168,6 @@ the aligned attribute (or something similar yet) */ #define TU_HAS_NO_ATTR_ALIGNED - /* activate the "weak" function emulation, because this toolchain does not - know the weak attribute (or something similar yet) */ - #define TU_HAS_NO_ATTR_WEAK - - // make sure to define away the standard definition of this macro - #undef MAKE_WEAK_FUNC - // Helper macro to construct a "weak" function name - #define MAKE_WEAK_FUNC(func_name) weak_ ## func_name - - #if defined(TU_HAS_NO_ATTR_WEAK) - // "Weak function" emulation defined in cdc_device.h - #define ADD_WEAK_FUNC_TUD_CDC_RX_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB 0 - - // "Weak function" emulation defined in usbd_pvt.h - #define ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB 0 - - // "Weak function" emulation defined in usbd.h - #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB 0 - #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB 0 - #define ADD_WEAK_FUNC_TUD_MOUNT_CB 0 - #define ADD_WEAK_FUNC_TUD_UMOUNT_CB 0 - #define ADD_WEAK_FUNC_TUD_SUSPEND_CB 0 - #define ADD_WEAK_FUNC_TUD_RESUME_CB 0 - #define ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB 0 - - // "Weak function" emulation defined in dcd.h - #define ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE 0 - #define ADD_WEAK_FUNC_DCD_EDPT_CLOSE 0 - #define ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO 0 - #endif - #else #error "Compiler attribute porting is required" #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index b20ea2974..a8a4d21e5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -262,8 +262,9 @@ enum // USB Descriptors //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// USB Device Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -284,12 +285,10 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; -TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -297,10 +296,8 @@ typedef struct TU_ATTR_PACKED uint16_t wTotalLength ; ///< Total length of data returned for this descriptor uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; -TU_PACK_STRUCT_END /// USB Configuration Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -313,10 +310,8 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; -TU_PACK_STRUCT_END /// USB Interface Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -330,10 +325,9 @@ typedef struct TU_ATTR_PACKED uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; -TU_PACK_STRUCT_END /// USB Endpoint Descriptor -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -341,14 +335,12 @@ typedef struct TU_ATTR_PACKED uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t xfer : 2; uint8_t sync : 2; uint8_t usage : 2; uint8_t : 2; } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. - TU_BIT_FIELD_ORDER_END struct TU_ATTR_PACKED { #if defined(__CCRX__) @@ -363,10 +355,9 @@ typedef struct TU_ATTR_PACKED uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// USB Other Speed Configuration Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -379,10 +370,8 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Same as Configuration descriptor uint8_t bMaxPower ; ///< Same as Configuration descriptor } tusb_desc_other_speed_t; -TU_PACK_STRUCT_END /// USB Device Qualifier Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -396,10 +385,8 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; -TU_PACK_STRUCT_END /// USB Interface Association Descriptor (IAD ECN) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -414,20 +401,16 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; -TU_PACK_STRUCT_END // USB String Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; -TU_PACK_STRUCT_END // USB Binary Device Object Store (BOS) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -437,10 +420,8 @@ typedef struct TU_ATTR_PACKED uint8_t PlatformCapabilityUUID[16]; uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; -TU_PACK_STRUCT_END // USB WebuSB URL Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -448,17 +429,15 @@ typedef struct TU_ATTR_PACKED uint8_t bScheme; char url[]; } tusb_desc_webusb_url_t; -TU_PACK_STRUCT_END // DFU Functional Descriptor -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; union { - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t bitCanDnload : 1; uint8_t bitCanUpload : 1; @@ -466,7 +445,6 @@ typedef struct TU_ATTR_PACKED uint8_t bitWillDetach : 1; uint8_t reserved : 4; } bmAttributes; - TU_BIT_FIELD_ORDER_END uint8_t bAttributes; }; @@ -475,21 +453,19 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED{ union { - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. uint8_t type : 2; ///< Request type tusb_request_type_t. uint8_t direction : 1; ///< Direction type. tusb_dir_t } bmRequestType_bit; - TU_BIT_FIELD_ORDER_END uint8_t bmRequestType; }; @@ -499,7 +475,9 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/device/dcd.h b/src/device/dcd.h index d68f9baa7..25cfafc4b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -117,7 +117,6 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Endpoint API //--------------------------------------------------------------------+ -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; @@ -130,35 +129,6 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; -#else - #if ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE - #define DCD_EDPT0_STATUS_COMPLETE dcd_edpt0_status_complete - #endif - #ifndef DCD_EDPT0_STATUS_COMPLETE - #define DCD_EDPT0_STATUS_COMPLETE NULL - #else - extern void DCD_EDPT0_STATUS_COMPLETE(uint8_t rhport, tusb_control_request_t const * request); - #endif - - #if ADD_WEAK_FUNC_DCD_EDPT_CLOSE - #define DCD_EDPT_CLOSE dcd_edpt_close - #endif - #ifndef DCD_EDPT_CLOSE - #define DCD_EDPT_CLOSE NULL - #else - extern void DCD_EDPT_CLOSE(uint8_t rhport, uint8_t ep_addr); - #endif - - #if ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO - #define DCD_EDPT_XFER_FIFO dcd_edpt_xfer_fifo - #endif - #ifndef DCD_EDPT_XFER_FIFO - #define DCD_EDPT_XFER_FIFO NULL - #else - extern void DCD_EDPT_XFER_FIFO(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); - #endif -#endif - // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); diff --git a/src/device/usbd.c b/src/device/usbd.c index 389ba4a4e..49c9279bf 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,19 +33,6 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" -#if defined(TU_HAS_NO_ATTR_WEAK) -static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_bos_cb))(void) = TUD_DESCRIPTOR_BOS_CB; -static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb))(void) = TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB; -static void (*const MAKE_WEAK_FUNC(tud_mount_cb))(void) = TUD_MOUNT_CB; -static void (*const MAKE_WEAK_FUNC(tud_umount_cb))(void) = TUD_UMOUNT_CB; -static void (*const MAKE_WEAK_FUNC(tud_suspend_cb))(_Bool) = TUD_SUSPEND_CB; -static void (*const MAKE_WEAK_FUNC(tud_resume_cb))(void) = TUD_RESUME_CB; -static _Bool (*const MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb))(uint8_t, uint8_t, tusb_control_request_t const *) = TUD_RESUME_CB; -static usbd_class_driver_t const* (*const MAKE_WEAK_FUNC(usbd_app_driver_get_cb))(uint8_t*) = USBD_APP_DRIVER_GET_CB; -static bool (*const MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo))(uint8_t, uint8_t, tu_fifo_t *, uint16_t) = DCD_EDPT_XFER_FIFO; -static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT_CLOSE; -#endif - #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -61,10 +48,11 @@ static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT // Invalid driver ID in itf2drv[] ep2drv[][] mapping enum { DRVID_INVALID = 0xFFu }; +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + +TU_BIT_FIELD_ORDER_BEGIN typedef struct { - TU_PACK_STRUCT_BEGIN - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -75,8 +63,6 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; - TU_BIT_FIELD_ORDER_END - TU_PACK_STRUCT_END volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; @@ -84,8 +70,6 @@ typedef struct uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - TU_PACK_STRUCT_BEGIN - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile bool busy : 1; @@ -94,10 +78,11 @@ typedef struct // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUD_EP_MAX][2]; - TU_BIT_FIELD_ORDER_END - TU_PACK_STRUCT_END }usbd_device_t; +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) static usbd_device_t _usbd_dev; @@ -257,7 +242,7 @@ static uint8_t _app_driver_count = 0; static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { // Application drivers - if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) + if ( usbd_app_driver_get_cb ) { if ( drvid < _app_driver_count ) return &_app_driver[drvid]; drvid -= _app_driver_count; @@ -429,9 +414,9 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) + if ( usbd_app_driver_get_cb ) { - _app_driver = MAKE_WEAK_FUNC(usbd_app_driver_get_cb)(&_app_driver_count); + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); } // Init class drivers @@ -522,7 +507,7 @@ void tud_task (void) usbd_reset(event.rhport); // invoke callback - if (MAKE_WEAK_FUNC(tud_umount_cb)) MAKE_WEAK_FUNC(tud_umount_cb)(); + if (tud_umount_cb) tud_umount_cb(); break; case DCD_EVENT_SETUP_RECEIVED: @@ -578,12 +563,12 @@ void tud_task (void) case DCD_EVENT_SUSPEND: TU_LOG2("\r\n"); - if (MAKE_WEAK_FUNC(tud_suspend_cb)) MAKE_WEAK_FUNC(tud_suspend_cb)(_usbd_dev.remote_wakeup_en); + if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: TU_LOG2("\r\n"); - if (MAKE_WEAK_FUNC(tud_resume_cb)) MAKE_WEAK_FUNC(tud_resume_cb)(); + if (tud_resume_cb) tud_resume_cb(); break; case DCD_EVENT_SOF: @@ -630,10 +615,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); + TU_VERIFY(tud_vendor_control_xfer_cb); - usbd_control_set_complete_callback(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); - return MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)(rhport, CONTROL_STAGE_SETUP, p_request); + usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); + return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 @@ -913,7 +898,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // invoke callback - if (MAKE_WEAK_FUNC(tud_mount_cb)) MAKE_WEAK_FUNC(tud_mount_cb)(); + if (tud_mount_cb) tud_mount_cb(); return true; } @@ -970,9 +955,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!MAKE_WEAK_FUNC(tud_descriptor_bos_cb)) return false; + if (!tud_descriptor_bos_cb) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)MAKE_WEAK_FUNC(tud_descriptor_bos_cb)(); + tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)tud_descriptor_bos_cb(); uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address @@ -1016,9 +1001,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Host sends this request to ask why our device with USB BCD from 2.0 // but is running at Full/Low Speed. If not highspeed capable stall this request, // otherwise return the descriptor that could work in highspeed mode - if (MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)) + if (tud_descriptor_device_qualifier_cb) { - uint8_t const* desc_qualifier = MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)(); + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); TU_ASSERT(desc_qualifier); // first byte of descriptor is its size @@ -1306,7 +1291,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo)(rhport, ep_addr, ff, total_bytes)) + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; @@ -1369,10 +1354,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - TU_ASSERT(MAKE_WEAK_FUNC(dcd_edpt_close), /**/); + TU_ASSERT(dcd_edpt_close, /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - MAKE_WEAK_FUNC(dcd_edpt_close(rhport, ep_addr)); + dcd_edpt_close(rhport, ep_addr); return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 67f1e2913..57c80fed1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -111,7 +111,6 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received GET BOS DESCRIPTOR request // Application return pointer to descriptor TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); @@ -136,71 +135,6 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -#else - #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB - #define TUD_DESCRIPTOR_BOS_CB tud_descriptor_bos_cb - #endif - #ifndef TUD_DESCRIPTOR_BOS_CB - #define TUD_DESCRIPTOR_BOS_CB NULL - #else - extern uint8_t const* TUD_DESCRIPTOR_BOS_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB - #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB tud_descriptor_device_qualifier_cb - #endif - #ifndef TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB - #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB NULL - #else - extern uint8_t const* TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_MOUNT_CB - #define TUD_MOUNT_CB tud_mount_cb - #endif - #ifndef TUD_MOUNT_CB - #define TUD_MOUNT_CB NULL - #else - extern void TUD_MOUNT_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_UMOUNT_CB - #define TUD_UMOUNT_CB tud_umount_cb - #endif - #ifndef TUD_UMOUNT_CB - #define TUD_UMOUNT_CB NULL - #else - extern void TUD_UMOUNT_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_SUSPEND_CB - #define TUD_SUSPEND_CB tud_suspend_cb - #endif - #ifndef TUD_SUSPEND_CB - #define TUD_SUSPEND_CB NULL - #else - extern void TUD_SUSPEND_CB(bool remote_wakeup_en); - #endif - - #if ADD_WEAK_FUNC_TUD_RESUME_CB - #define TUD_RESUME_CB tud_resume_cb - #endif - #ifndef TUD_RESUME_CB - #define TUD_RESUME_CB NULL - #else - extern void TUD_RESUME_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB - #define TUD_VENDOR_CONTROL_XFER_CB tud_vendor_control_xfer_cb - #endif - #ifndef TUD_VENDOR_CONTROL_XFER_CB - #define TUD_VENDOR_CONTROL_XFER_CB NULL - #else - extern bool TUD_VENDOR_CONTROL_XFER_CB(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - #endif -#endif - //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 76f999f86..b3bab2e32 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -36,10 +36,6 @@ extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif -#if defined(TU_HAS_NO_ATTR_WEAK) -static void (*const MAKE_WEAK_FUNC(dcd_edpt0_status_complete))(uint8_t, tusb_control_request_t const *) = DCD_EDPT0_STATUS_COMPLETE; -#endif - enum { EDPT_CTRL_OUT = 0x00, @@ -184,7 +180,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (MAKE_WEAK_FUNC(dcd_edpt0_status_complete)) MAKE_WEAK_FUNC(dcd_edpt0_status_complete)(rhport, &_ctrl_xfer.request); + if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); if (_ctrl_xfer.complete_cb) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index c814353ae..bb2267d40 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -51,22 +51,10 @@ typedef struct void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; -#else - #if ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB - #define USBD_APP_DRIVER_GET_CB usbd_app_driver_get_cb - #endif - #ifndef USBD_APP_DRIVER_GET_CB - #define USBD_APP_DRIVER_GET_CB NULL - #else - extern usbd_class_driver_t const* USBD_APP_DRIVER_GET_CB(uint8_t* driver_count); - #endif -#endif - typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 0e7881383..13fc50ae5 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -90,45 +90,47 @@ #define FIFO_REQ_CLR (1u) #define FIFO_COMPLETE (1u<<1) +TU_BIT_FIELD_ORDER_BEGIN typedef struct { union { - TU_BIT_FIELD_ORDER_BEGIN struct { uint16_t : 8; uint16_t TRCLR: 1; uint16_t TRENB: 1; uint16_t : 0; }; - TU_BIT_FIELD_ORDER_END uint16_t TRE; }; uint16_t TRN; } reg_pipetre_t; +TU_BIT_FIELD_ORDER_END +TU_BIT_FIELD_ORDER_BEGIN typedef union { - TU_BIT_FIELD_ORDER_BEGIN struct { volatile uint16_t u8: 8; volatile uint16_t : 0; }; - TU_BIT_FIELD_ORDER_END volatile uint16_t u16; } hw_fifo_t; +TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ - TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t ep : 8; /* an assigned endpoint address */ uint32_t : 0; }; - TU_BIT_FIELD_ORDER_END } pipe_state_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) typedef struct { @@ -259,12 +261,6 @@ static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps) hw_fifo_t *reg = (hw_fifo_t*)fifo; uintptr_t addr = pipe->addr + pipe->length - rem; - if (addr & 1u) { - /* addr is not 2-byte aligned */ - reg->u8 = *(const uint8_t *)addr; - ++addr; - --len; - } while (len >= 2) { reg->u16 = *(const uint16_t *)addr; addr += 2; @@ -306,17 +302,10 @@ static void process_setup_packet(uint8_t rhport) uint16_t setup_packet[4]; if (0 == (USB0.INTSTS0.WORD & USB_IS0_VALID)) return; USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; - setup_packet[0] = USB0.USBREQ.WORD; + setup_packet[0] = tu_le16toh(USB0.USBREQ.WORD); setup_packet[1] = USB0.USBVAL; setup_packet[2] = USB0.USBINDX; setup_packet[3] = USB0.USBLENG; -#if TU_BYTE_ORDER==TU_BIG_ENDIAN - #if defined(__CCRX__) - setup_packet[0] = tu_le16toh(setup_packet[0]); - #else - //FIXME needs to implemented for other tool chains - #endif -#endif USB0.INTSTS0.WORD = ~USB_IS0_VALID; dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); } -- cgit v1.3.1 From 832d22d7addf9b1e4b88556c544f60bd9fa32dd6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 01:55:35 +0700 Subject: force single buffered for device mode, out endpoint --- src/device/usbd.c | 3 +- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 15 ++++---- src/portable/raspberrypi/rp2040/rp2040_usb.c | 52 +++++++++++++++++++++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 +-- 4 files changed, 55 insertions(+), 19 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 2935defd0..587d487dc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1254,14 +1254,13 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) { - TU_LOG2("OK\r\n"); return true; }else { // DCD error, mark endpoint as ready to allow next transfer _usbd_dev.ep_status[epnum][dir].busy = false; _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); + TU_LOG2("FAILED\r\n"); TU_BREAKPOINT(); return false; } diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index b87951421..f78a932f1 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -145,6 +145,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t // Now if it hasn't already been done //alloc a buffer and fill in endpoint control register + // TODO device may change configuration (dynamic), should clear and reallocate if(!(ep->configured)) { _hw_endpoint_alloc(ep); @@ -194,9 +195,6 @@ static void hw_handle_buff_status(void) { if (remaining_buffers & bit) { - uint __unused which = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; - // Should be single buffered - assert(which == 0); // clear this in advance usb_hw_clear->buf_status = bit; // IN transfer for even i, OUT transfer for odd i @@ -463,7 +461,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { - pico_info("dcd_edpt_open %d %02x\n", rhport, desc_edpt->bEndpointAddress); + pico_info("dcd_edpt_open %02x\n", desc_edpt->bEndpointAddress); assert(rhport == 0); hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer); return true; @@ -478,14 +476,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_stall %d %02x\n", rhport, ep_addr); + pico_trace("dcd_edpt_stall %02x\n", ep_addr); assert(rhport == 0); hw_endpoint_stall(ep_addr); } void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_clear_stall %d %02x\n", rhport, ep_addr); + pico_trace("dcd_edpt_clear_stall %02x\n", ep_addr); assert(rhport == 0); hw_endpoint_clear_stall(ep_addr); } @@ -493,8 +491,11 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { + (void) rhport; + (void) ep_addr; + // usbd.c says: In progress transfers on this EP may be delivered after this call - pico_trace("dcd_edpt_close %d %02x\n", rhport, ep_addr); + pico_trace("dcd_edpt_close %02x\n", ep_addr); } void dcd_int_handler(uint8_t rhport) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 5b2a5f5a0..dc12e6d82 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -148,10 +148,15 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) { uint32_t ep_ctrl = *ep->endpoint_control; - // always compute buffer 0 - uint32_t buf_ctrl = prepare_ep_buffer(ep, 0); + // always compute and start with buffer 0 + uint32_t buf_ctrl = prepare_ep_buffer(ep, 0) | USB_BUF_CTRL_SEL; - if(ep->remaining_len) + // For now: skip double buffered for Device mode, OUT endpoint since + // host could send < 64 bytes and cause short packet on buffer0 + // NOTE this could happen to Host mode IN endpoint + bool const force_single = !(usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) && !tu_edpt_dir(ep->ep_addr); + + if(ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) @@ -181,8 +186,7 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) { _hw_endpoint_lock_update(ep, 1); - pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), - ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + if ( ep->active ) { // TODO: Is this acceptable for interrupt packets? @@ -251,10 +255,42 @@ static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) // always sync buffer 0 uint16_t buf0_bytes = sync_ep_buffer(ep, 0); - // sync buffer 1 if double buffered and buffer 0 is not short packet - if ( ((*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS) && (buf0_bytes == ep->wMaxPacketSize) ) + // sync buffer 1 if double buffered + if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) { - sync_ep_buffer(ep, 1); + if (buf0_bytes == ep->wMaxPacketSize) + { + // sync buffer 1 if not short packet + sync_ep_buffer(ep, 1); + }else + { + // short packet on buffer 0 + // TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example + // At this time (currently trigger per 2 buffer), the buffer1 is probably filled with data from + // the next transfer (not current one). For now we disable double buffered for device OUT + // NOTE this could happen to Host IN +#if 0 + uint8_t const ep_num = tu_edpt_number(ep->ep_addr); + uint8_t const dir = (uint8_t) tu_edpt_dir(ep->ep_addr); + uint8_t const ep_id = 2*ep_num + (dir ? 0 : 1); + + // abort queued transfer on buffer 1 + usb_hw->abort |= TU_BIT(ep_id); + + while ( !(usb_hw->abort_done & TU_BIT(ep_id)) ) {} + + uint32_t ep_ctrl = *ep->endpoint_control; + ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); + ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; + + _hw_endpoint_buffer_control_set_value32(ep, 0); + + usb_hw->abort &= ~TU_BIT(ep_id); + + TU_LOG(3, "----SHORT PACKET buffer0 on EP %02X:\r\n", ep->ep_addr); + print_bufctrl32(buf_ctrl); +#endif + } } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 4c787f496..514152cd9 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -120,8 +120,8 @@ static inline void print_bufctrl16(uint32_t u16) .u16 = u16 }; - TU_LOG(3, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n", - bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full); + TU_LOG(3, "len = %u, available = %u, full = %u, last = %u, stall = %u, reset = %u, toggle = %u\r\n", + bufctrl.xfer_len, bufctrl.available, bufctrl.full, bufctrl.last_buf, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle); } static inline void print_bufctrl32(uint32_t u32) -- cgit v1.3.1 From 51c6444e1d8be85d5f4c8b4ebf7e48db7f589bc2 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Tue, 22 Jun 2021 23:49:24 +0200 Subject: final clean up --- src/common/tusb_compiler.h | 10 ---------- src/device/usbd.c | 4 ++-- src/device/usbd_control.c | 10 +--------- src/osal/osal_freertos.h | 25 ------------------------- src/portable/renesas/usba/dcd_usba.c | 11 +---------- 5 files changed, 4 insertions(+), 56 deletions(-) (limited to 'src/device') diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index f77cf94ee..538daa171 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -84,8 +84,6 @@ // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #define TU_ENDIAN_LITTLE_BEGIN - #define TU_ENDIAN_LITTLE_END #else #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif @@ -153,21 +151,13 @@ // Endian conversion use well-known host to network (big endian) naming #if defined(__LIT) #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #define TU_ENDIAN_LITTLE_BEGIN - #define TU_ENDIAN_LITTLE_END #else #define TU_BYTE_ORDER TU_BIG_ENDIAN - #define TU_ENDIAN_LITTLE_BEGIN _Pragma("endian little") - #define TU_ENDIAN_LITTLE_END _Pragma("endian") #endif #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) #define TU_BSWAP32(u32) (_builtin_revl(u32)) - /* activate the "aligned" emulation, because this toolchain does not know - the aligned attribute (or something similar yet) */ - #define TU_HAS_NO_ATTR_ALIGNED - #else #error "Compiler attribute porting is required" #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index cedca540e..00ec29c9a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1156,14 +1156,14 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, tu_le16toh(desc_ep->wMaxPacketSize.size)); switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_ISOCHRONOUS: { uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); } break; diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index b3bab2e32..5483406e5 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -55,17 +55,9 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; -#if defined(TU_HAS_NO_ATTR_ALIGNED) -// Helper union to overcome the lack of the alignment attribute/pragma -static union { - uint16_t : (sizeof(uint16_t) * 8); // Alignment of at least the size of the used type - uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; -} Align_usbd_ctrl_buf_; -static uint8_t *_usbd_ctrl_buf = (uint8_t*)&Align_usbd_ctrl_buf_; -#else CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; -#endif + //--------------------------------------------------------------------+ // Application API diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index ec33b317d..66070c273 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -51,7 +51,6 @@ static inline void osal_task_delay(uint32_t msec) typedef StaticSemaphore_t osal_semaphore_def_t; typedef SemaphoreHandle_t osal_semaphore_t; -#if (configSUPPORT_STATIC_ALLOCATION == 1) //FIXME Only static API supported static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { return xSemaphoreCreateBinaryStatic(semdef); @@ -77,7 +76,6 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) return res != 0; } } -#endif static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { @@ -98,12 +96,7 @@ typedef SemaphoreHandle_t osal_mutex_t; static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { -#if (configSUPPORT_STATIC_ALLOCATION == 0) //FIXME Only static API supported - (void)mdef; - return xSemaphoreCreateMutex(); -#else return xSemaphoreCreateMutexStatic(mdef); -#endif } static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) @@ -138,11 +131,7 @@ typedef QueueHandle_t osal_queue_t; static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { -#if defined(__Tx36V5_Maincard__) - return xQueueCreate(qdef->depth, qdef->item_sz); -#else return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); -#endif } static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) @@ -150,19 +139,6 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) return xQueueReceive(qhdl, data, portMAX_DELAY); } -#if defined(__Tx36V5_Maincard__) -extern BaseType_t UsbTaskWoken; -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if (!in_isr) { - return(xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER)); - - } else { - BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &UsbTaskWoken); - return(res != 0); - } -} -#else static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if ( !in_isr ) @@ -183,7 +159,6 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return res != 0; } } -#endif static inline bool osal_queue_empty(osal_queue_t qhdl) { diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 13fc50ae5..51729de06 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -518,22 +518,13 @@ static void process_set_address(uint8_t rhport) { const uint32_t addr = USB0.USBADDR.BIT.USBADDR; if (!addr) return; -#if defined(__CCRX__) - tusb_control_request_t setup_packet; - setup_packet.bmRequestType = 0; - setup_packet.bRequest = 5; - setup_packet.wValue = addr; - setup_packet.wIndex = 0; - setup_packet.wLength = 0; -#else const tusb_control_request_t setup_packet = { - .bmRequestType = 0, + .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */ .bRequest = 5, .wValue = addr, .wIndex = 0, .wLength = 0, }; -#endif dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true); } -- cgit v1.3.1 From b9e9773d04419032d9e8eb8ca568390f74382690 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 24 Jun 2021 11:35:05 +0200 Subject: fix warning --- src/class/cdc/cdc_device.h | 4 ++-- src/device/usbd.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 94678a660..f8a2216c1 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -248,13 +248,13 @@ static inline bool tud_cdc_write_clear(void) } // Get the Receive FIFO -static inline tu_fifo_t* tud_cdc_get_rx_ff (uint8_t itf) +static inline tu_fifo_t* tud_cdc_get_rx_ff (void) { return tud_cdc_n_get_rx_ff(0); } // Get the transmit FIFO -static inline tu_fifo_t* tud_cdc_get_tx_ff (uint8_t itf) +static inline tu_fifo_t* tud_cdc_get_tx_ff (void) { return tud_cdc_n_get_tx_ff(0); } diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..0a0f0bf00 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -236,7 +236,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint In */\ @@ -249,7 +249,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint Out */\ -- cgit v1.3.1 From ca98996e1f9ac802c60d9da4c28ab0e16ca640d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jul 2021 22:46:39 +0700 Subject: better support for hid device set/get protocol add caplock detection for hid_composite --- examples/device/hid_composite/src/main.c | 31 ++++++++++++++--- hw/bsp/board.c | 58 +++++++++++++++++++++++++++++--- hw/bsp/board.h | 9 +++-- src/class/hid/hid_device.c | 28 +++++++++++++-- src/device/usbd.c | 2 +- src/device/usbd_control.c | 1 + 6 files changed, 115 insertions(+), 14 deletions(-) (limited to 'src/device') diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 512f6f9d9..6ddad5aae 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -255,12 +255,30 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { - // TODO set LED based on CAPLOCK, NUMLOCK etc... (void) itf; - (void) report_id; - (void) report_type; - (void) buffer; - (void) bufsize; + + if (report_type == HID_REPORT_TYPE_OUTPUT) + { + // Set keyboard LED e.g Capslock, Numlock etc... + if (report_id == REPORT_ID_KEYBOARD) + { + // bufsize should be (at least) 1 + if ( bufsize < 1 ) return; + + uint8_t const kbd_leds = buffer[0]; + + if (kbd_leds & KEYBOARD_LED_CAPSLOCK) + { + // Capslock On: disable blink, turn led on + blink_interval_ms = 0; + board_led_write(true); + }else + { + // Caplocks Off: back to normal link + blink_interval_ms = BLINK_MOUNTED; + } + } + } } //--------------------------------------------------------------------+ @@ -271,6 +289,9 @@ void led_blinking_task(void) static uint32_t start_ms = 0; static bool led_state = false; + // blink is disabled + if (!blink_interval_ms) return; + // Blink every interval ms if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 383a02ef4..c21c9e976 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -25,6 +25,60 @@ #include "board.h" +#if 0 +#define LED_PHASE_MAX 8 + +static struct +{ + uint32_t phase[LED_PHASE_MAX]; + uint8_t phase_count; + + bool led_state; + uint8_t current_phase; + uint32_t current_ms; +}led_pattern; + +void board_led_pattern(uint32_t const phase_ms[], uint8_t count) +{ + memcpy(led_pattern.phase, phase_ms, 4*count); + led_pattern.phase_count = count; + + // reset with 1st phase is on + led_pattern.current_ms = board_millis(); + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); +} + +void board_led_task(void) +{ + if ( led_pattern.phase_count == 0 ) return; + + uint32_t const duration = led_pattern.phase[led_pattern.current_phase]; + + // return if not enough time + if (board_millis() - led_pattern.current_ms < duration) return; + + led_pattern.led_state = !led_pattern.led_state; + board_led_write(led_pattern.led_state); + + led_pattern.current_ms += duration; + led_pattern.current_phase++; + + if (led_pattern.current_phase == led_pattern.phase_count) + { + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); + } +} + +#endif + +//--------------------------------------------------------------------+ +// newlib read()/write() retarget +//--------------------------------------------------------------------+ + #if defined(__MSP430__) #define sys_write write #define sys_read read @@ -33,10 +87,6 @@ #define sys_read _read #endif -//--------------------------------------------------------------------+ -// newlib read()/write() retarget -//--------------------------------------------------------------------+ - #if defined(LOGGER_RTT) // Logging with RTT diff --git a/hw/bsp/board.h b/hw/bsp/board.h index 7b77def50..782e0939c 100644 --- a/hw/bsp/board.h +++ b/hw/bsp/board.h @@ -54,6 +54,10 @@ void board_init(void); // Turn LED on or off void board_led_write(bool state); +// Control led pattern using phase duration in ms. +// For each phase, LED is toggle then repeated, board_led_task() is required to be called +//void board_led_pattern(uint32_t const phase_ms[], uint8_t count); + // Get the current state of button // a '1' means active (pressed), a '0' means inactive. uint32_t board_button_read(void); @@ -81,11 +85,12 @@ int board_uart_write(void const * buf, int len); } #elif CFG_TUSB_OS == OPT_OS_PICO -#include "pico/time.h" -static inline uint32_t board_millis(void) + #include "pico/time.h" + static inline uint32_t board_millis(void) { return to_ms_since_boot(get_absolute_time()); } + #elif CFG_TUSB_OS == OPT_OS_RTTHREAD static inline uint32_t board_millis(void) { diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index e44f282c4..65c7d1a18 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -280,7 +280,21 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + uint8_t* report_buf = p_hid->epin_buf; + uint16_t req_len = request->wLength; + + uint16_t xferlen = 0; + + // If host request a specific Report ID, add ID to as 1 byte of response + if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) + { + *report_buf++ = report_id; + req_len--; + + xferlen++; + } + + xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -298,7 +312,17 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength); + uint8_t const* report_buf = p_hid->epout_buf; + uint16_t report_len = request->wLength; + + // If host request a specific Report ID, extract report ID in buffer before invoking callback + if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == p_hid->epout_buf[0]) ) + { + report_buf++; + report_len--; + } + + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); } break; diff --git a/src/device/usbd.c b/src/device/usbd.c index 587d487dc..af4fd58c4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1243,7 +1243,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 724c652e6..7a8244699 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -186,6 +186,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result { TU_VERIFY(_ctrl_xfer.buffer); memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); + TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += xferred_bytes; -- cgit v1.3.1 From 6e9da70c18a0dbabaedb1c9aadcc9fe53a0113a7 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 29 Jun 2021 22:40:21 +0200 Subject: Fix audiod_get_AS_interface_index in audio class. Enhance uac2_headset example with multiple sample rates. Add macro to calculate EP size. --- examples/device/uac2_headset/src/main.c | 69 ++++++++++++++++------ examples/device/uac2_headset/src/tusb_config.h | 13 ++-- examples/device/uac2_headset/src/usb_descriptors.c | 2 +- examples/device/uac2_headset/src/usb_descriptors.h | 8 +-- src/class/audio/audio_device.c | 16 ++--- src/device/usbd.h | 5 ++ 6 files changed, 77 insertions(+), 36 deletions(-) (limited to 'src/device') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 1b6a770a3..e76b081c8 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -34,9 +34,11 @@ // MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif +// List of supported sample rates +const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; +uint32_t current_sample_rate = 44100; + +#define N_SAMPLE_RATES (sizeof(sample_rates) / 4) /* Blink pattern * - 25 ms : streaming data @@ -166,24 +168,30 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - // Example supports only single frequency, same value will be used for current value and range if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG2("Clock get current freq %u\r\n", AUDIO_SAMPLE_RATE); + TU_LOG1("Clock get current freq %u\r\n", current_sample_rate); - audio_control_cur_4_t curf = { tu_htole32(AUDIO_SAMPLE_RATE) }; + audio_control_cur_4_t curf = { tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); } else if (request->bRequest == AUDIO_CS_REQ_RANGE) { - audio_control_range_4_n_t(1) rangef = + audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = { - .wNumSubRanges = tu_htole16(1), - .subrange[0] = { tu_htole32(AUDIO_SAMPLE_RATE), tu_htole32(AUDIO_SAMPLE_RATE), 0} + .wNumSubRanges = tu_htole16(N_SAMPLE_RATES) }; - TU_LOG2("Clock get freq range (%d, %d, %d)\r\n", (int)rangef.subrange[0].bMin, (int)rangef.subrange[0].bMax, (int)rangef.subrange[0].bRes); + TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES); + for(uint8_t i = 0; i < N_SAMPLE_RATES; i++) + { + rangef.subrange[i].bMin = sample_rates[i]; + rangef.subrange[i].bMax = sample_rates[i]; + rangef.subrange[i].bRes = 0; + TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes); + } + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef)); } } @@ -191,7 +199,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_1_t cur_valid = { .bCur = 1 }; - TU_LOG2("Clock get is valid %u\r\n", cur_valid.bCur); + TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid)); } TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n", @@ -199,6 +207,32 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t return false; } +// Helper for clock set requests +static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) +{ + (void)rhport; + + TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); + TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + + if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) + { + TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); + + current_sample_rate = ((audio_control_cur_4_t *)buf)->bCur; + + TU_LOG1("Clock set current freq: %d\r\n", current_sample_rate); + + return true; + } + else + { + TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n", + request->bEntityID, request->bControlSelector, request->bRequest); + return false; + } +} + // Helper for feature unit get requests static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) { @@ -207,7 +241,7 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] }; - TU_LOG2("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); + TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1)); } else if (UAC2_ENTITY_SPK_FEATURE_UNIT && request->bControlSelector == AUDIO_FU_CTRL_VOLUME) @@ -218,14 +252,14 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req .wNumSubRanges = tu_htole16(1), .subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) } }; - TU_LOG2("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, + TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol)); } else if (request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) }; - TU_LOG2("Get channel %u volume %u dB\r\n", request->bChannelNumber, cur_vol.bCur); + TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol)); } } @@ -249,7 +283,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req mute[request->bChannelNumber] = ((audio_control_cur_1_t *)buf)->bCur; - TU_LOG2("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); + TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; } @@ -259,7 +293,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur; - TU_LOG2("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); + TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); return true; } @@ -299,7 +333,8 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) return tud_audio_feature_unit_set_request(rhport, request, buf); - + if (request->bEntityID == UAC2_ENTITY_CLOCK) + return tud_audio_clock_set_request(rhport, request, buf); TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 88f9efcff..9b7ed337c 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -93,13 +93,12 @@ extern "C" { //-------------------------------------------------------------------- // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) //#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN 220 // This equals TUD_AUDIO_HEADSET_STEREO_DESC_LEN, however, including it from usb_descriptors.h is not possible due to some strange include hassle #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN // Audio format type I specifications +#define CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE 96000 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 @@ -108,18 +107,18 @@ extern "C" { // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 -#define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_OUT_SZ // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_OUT*3 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_SZ_OUT // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 // Size of control request buffer #define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index cd749eb65..f5d8e461b 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -93,7 +93,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_OUT_SZ, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_SZ_OUT, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index d9c5a63a7..1595d9c5d 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -77,7 +77,7 @@ enum /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 5, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ /* Input Terminal Descriptor(4.7.2.4) */\ TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ @@ -99,21 +99,21 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 2, Alternate 0 - default alternate setting with 0 bandwidth */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\ /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + /* Interface 2, Alternate 1 - alternate interface for data streaming */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epinsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epinsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)\ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7263958df..cb35adb82 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1997,15 +1997,17 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio while (p_desc < p_desc_end) { // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; + if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *pp_desc_int = p_desc; + return true; + } + // Increase index, bytes read, and pointer + tmp++; } - - // Increase index, bytes read, and pointer - tmp++; p_desc = tu_desc_next(p_desc); } } diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..45aefe53b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -542,6 +542,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ +// Calculate wMaxPacketSize of Endpoints +#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ + ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) + + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u -- cgit v1.3.1 From c2d8ed3fd1fdb722d67a30a6768720c9ed578779 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Mon, 5 Jul 2021 17:56:21 +0200 Subject: Add alt settings support in DFU class. --- examples/device/dfu/src/main.c | 25 ++++++++--------- examples/device/dfu/src/usb_descriptors.c | 8 ++++-- src/class/dfu/dfu_device.c | 46 ++++++++++++++++++++----------- src/class/dfu/dfu_device.h | 10 ++++--- src/device/usbd.h | 8 +++--- 5 files changed, 56 insertions(+), 41 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 1c09066a8..81532ee90 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -115,25 +115,20 @@ void tud_resume_cb(void) blink_interval_ms = BLINK_MOUNTED; } -// Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_runtime_reboot_to_dfu_cb(void) -{ - blink_interval_ms = BLINK_DFU_MODE; -} - //--------------------------------------------------------------------+ // Class callbacks //--------------------------------------------------------------------+ -bool tud_dfu_firmware_valid_check_cb(void) +bool tud_dfu_firmware_valid_check_cb(uint8_t alt) { + (void) alt; printf(" Firmware check\r\n"); return true; } -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; - printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; ibInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + uint16_t drv_len = 0; + uint8_t const * p_desc = (uint8_t*)itf_desc; - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + while (max_len) { - tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; - + // Ensure this is DFU Mode + TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), drv_len); + + p_desc = tu_desc_next( p_desc ); drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + max_len -= drv_len; + } return drv_len; } @@ -200,6 +208,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && TUSB_REQ_SET_INTERFACE == request->bRequest ) { + // Save Alt interface + _dfu_state_ctx.alt = request->wValue; tud_control_status(rhport, request); return true; } @@ -248,7 +258,11 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + uint16_t retval = 0; + if (tud_dfu_req_upload_data_cb) + { + tud_dfu_req_upload_data_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -285,7 +299,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt, request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } @@ -426,7 +440,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb() ) + if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -481,7 +495,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb() ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_IDLE; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 9a09a46b1..d5bc88ab2 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -39,13 +39,14 @@ //--------------------------------------------------------------------+ // Invoked during DFU_MANIFEST_SYNC get status request to check if firmware // is valid -bool tud_dfu_firmware_valid_check_cb(void); +bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data // provided by tud_dfu_req_dnload_data_cb @@ -56,7 +57,7 @@ void tud_dfu_dnload_complete(void); // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure -bool tud_dfu_device_data_done_check_cb(void); +bool tud_dfu_device_data_done_check_cb(uint8_t alt); // Invoked when the Host has terminated a download or upload transfer TU_ATTR_WEAK void tud_dfu_abort_cb(void); @@ -64,7 +65,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes // Return the number of bytes to write -uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..41c78de10 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -603,11 +603,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Length of template descriptr: 18 bytes #define TUD_DFU_MODE_DESC_LEN (9 + 9) -// DFU runtime descriptor -// Interface number, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ +// DFU mode descriptor +// Interface number, alt settings, string index, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -- cgit v1.3.1 From 941b02c6a98cd34eb84cf499db9810108871d49b Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 18:02:04 +0200 Subject: Reactor to one functional descriptor. --- examples/device/dfu/src/tusb_config.h | 8 +++-- examples/device/dfu/src/usb_descriptors.c | 7 ++--- src/class/dfu/dfu_device.c | 51 ++++++++++++++----------------- src/class/dfu/dfu_device.h | 7 +---- src/device/usbd.h | 47 +++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 48 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 0df46c14e..55aa19922 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,14 +76,16 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -// DFU buffer size, must to be set to the largest buffer size used by an any given storage type -#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 - //------------- CLASS -------------// #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 +// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) +#define CFG_TUD_DFU_ALT_COUNT 2 +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 + #ifdef __cplusplus } #endif diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 9565da9b2..200817eb4 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -87,7 +87,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,9 +96,8 @@ uint8_t const desc_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + // Interface number, detach timeout, transfer size, string index 0, [string index 1 ... string index n] + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8bf2e16be..834648c5a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; + uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; @@ -148,10 +148,7 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -165,10 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -180,15 +174,15 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *)itf_desc; uint16_t total_len = 0; - + uint8_t last_alt = 0; - while(max_len >= drv_len) + while(max_len > drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && @@ -208,25 +202,26 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); + TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); // Alt should increse by one every time TU_ASSERT(alt == last_alt++, 0); - //------------- DFU descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); - - _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; - - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - p_desc = tu_desc_next(p_desc); max_len -= drv_len; total_len += drv_len; } + //------------- DFU descriptor -------------// + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + + _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); + + total_len += sizeof(tusb_desc_dfu_functional_t); + return total_len; } @@ -272,7 +267,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -358,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -376,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -390,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -481,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -538,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 53be0005e..f41b4b651 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,13 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -// Maximum alternate settings (used for different partitons) supported -#if !defined(CFG_TUD_DFU_ATL_MAX) - #define CFG_TUD_DFU_ATL_MAX 2 -#endif - #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 41c78de10..fe1863706 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -600,17 +600,50 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Length of template descriptr: 18 bytes -#define TUD_DFU_MODE_DESC_LEN (9 + 9) +// Maximum alternate settings (used for different partitons) supported +#ifndef CFG_TUD_DFU_ALT_COUNT +#define CFG_TUD_DFU_ALT_COUNT 1 +#endif -// DFU mode descriptor -// Interface number, alt settings, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ +// Length of template descriptor: 18 bytes + number of alternatives * 9 +#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) + +/* Primary Interface */ +#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + +#define _TUD_DFU_FIRST(a, ...) a +#define _TUD_DFU_REST(a, ...) __VA_ARGS__ +#define _TUD_DFU_COMBINE(...) __VA_ARGS__ + +#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) + +#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ + TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) + +// Interface number, detach timeout, transfer size, string index 1, [string index 2, string index n] +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ + TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ + TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) //------------- CDC-ECM -------------// -- cgit v1.3.1 From 7e883e0f41a4fdda699bbaf1d64a28d82527b8f9 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 7 Jul 2021 19:01:00 +0200 Subject: Refactor with one DFU functionnal descriptor --- examples/device/dfu/src/tusb_config.h | 8 +++-- examples/device/dfu/src/usb_descriptors.c | 7 ++--- src/class/dfu/dfu_device.c | 51 ++++++++++++++----------------- src/class/dfu/dfu_device.h | 7 +---- src/device/usbd.h | 47 +++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 48 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 0df46c14e..55aa19922 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,14 +76,16 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -// DFU buffer size, must to be set to the largest buffer size used by an any given storage type -#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 - //------------- CLASS -------------// #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 +// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) +#define CFG_TUD_DFU_ALT_COUNT 2 +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 + #ifdef __cplusplus } #endif diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 9565da9b2..8c5eee455 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -87,7 +87,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,9 +96,8 @@ uint8_t const desc_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8bf2e16be..834648c5a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; + uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; @@ -148,10 +148,7 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -165,10 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -180,15 +174,15 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *)itf_desc; uint16_t total_len = 0; - + uint8_t last_alt = 0; - while(max_len >= drv_len) + while(max_len > drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && @@ -208,25 +202,26 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); + TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); // Alt should increse by one every time TU_ASSERT(alt == last_alt++, 0); - //------------- DFU descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); - - _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; - - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - p_desc = tu_desc_next(p_desc); max_len -= drv_len; total_len += drv_len; } + //------------- DFU descriptor -------------// + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + + _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); + + total_len += sizeof(tusb_desc_dfu_functional_t); + return total_len; } @@ -272,7 +267,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -358,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -376,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -390,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -481,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -538,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 53be0005e..f41b4b651 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,13 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -// Maximum alternate settings (used for different partitons) supported -#if !defined(CFG_TUD_DFU_ATL_MAX) - #define CFG_TUD_DFU_ATL_MAX 2 -#endif - #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 41c78de10..3d49d4b12 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -600,17 +600,50 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Length of template descriptr: 18 bytes -#define TUD_DFU_MODE_DESC_LEN (9 + 9) +// Maximum alternate settings (used for different partitons) supported +#ifndef CFG_TUD_DFU_ALT_COUNT +#define CFG_TUD_DFU_ALT_COUNT 1 +#endif -// DFU mode descriptor -// Interface number, alt settings, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ +// Length of template descriptor: 18 bytes + number of alternatives * 9 +#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) + +/* Primary Interface */ +#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + +#define _TUD_DFU_FIRST(a, ...) a +#define _TUD_DFU_REST(a, ...) __VA_ARGS__ +#define _TUD_DFU_COMBINE(...) __VA_ARGS__ + +#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) + +#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ + TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) + +// Interface number, attributes, detach timeout, transfer size, string index 1, [string index 2, string index n] +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ + TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ + TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) //------------- CDC-ECM -------------// -- cgit v1.3.1 From 2916cd45753ca579ee1d0b475b2daf3f715243b6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 18:51:57 +0700 Subject: rename TUD_DFU_MODE_DESCRIPTOR to TUD_DFU_DESCRIPTOR --- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 2 +- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 2 +- src/device/usbd.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 55aa19922..7e10b4321 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -83,7 +83,7 @@ // Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) #define CFG_TUD_DFU_ALT_COUNT 2 -// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 #ifdef __cplusplus diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 8c5eee455..870c18a04 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -97,7 +97,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 933946b7e..ae056b441 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -200,7 +200,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_state_ctx.attrs = func_desc->bAttributes; - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 73e5055cd..8edb2bae3 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -38,7 +38,7 @@ //--------------------------------------------------------------------+ #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index ba415abe8..8c5f0097d 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -646,7 +646,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1, string index n] -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ +#define TUD_DFU_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) -- cgit v1.3.1 From 680b000bd1471d731117ccf4f3fe35579d346cb8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 20:15:59 +0700 Subject: simplify TUD_DFU_DESCRIPTOR with alternate count remove CFG_TUD_DFU_ALT_COUNT since there is only one DFU functional descriptor --- examples/device/dfu/src/main.c | 3 +- examples/device/dfu/src/tusb_config.h | 2 - examples/device/dfu/src/usb_descriptors.c | 9 ++-- src/device/usbd.h | 79 ++++++++++++++++--------------- 4 files changed, 48 insertions(+), 45 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index f7c27174a..ee201c1c5 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -154,8 +154,9 @@ bool tud_dfu_device_data_done_check_cb(uint8_t alt) return true; } -void tud_dfu_abort_cb(void) +void tud_dfu_abort_cb(uint8_t alt) { + (void) alt; printf(" Host aborted transfer\r\n"); } diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 7e10b4321..77d907ffc 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -81,8 +81,6 @@ #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 -// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) -#define CFG_TUD_DFU_ALT_COUNT 2 // DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 870c18a04..78e94194e 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -81,13 +81,16 @@ uint8_t const * tud_descriptor_device_cb(void) // Configuration Descriptor //--------------------------------------------------------------------+ +// Number of Alternate Interface (each for 1 flash partition) +#define ALT_COUNT 2 + enum { ITF_NUM_DFU_MODE, ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(ALT_COUNT)) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,8 +99,8 @@ uint8_t const desc_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] - TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), + // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/device/usbd.h b/src/device/usbd.h index 8c5f0097d..9697b4497 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -605,50 +605,51 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Maximum alternate settings (used for different partitons) supported -#ifndef CFG_TUD_DFU_ALT_COUNT -#define CFG_TUD_DFU_ALT_COUNT 1 -#endif - -// Length of template descriptor: 18 bytes + number of alternatives * 9 -#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) +// Length of template descriptor: 9 bytes + number of alternatives * 9 +#define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9) -/* Primary Interface */ -#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ +// Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size +// Note: Alternate count must be numberic or macro, string index is increased by one for each Alt interface +#define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \ + TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ +#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ - -#define _TUD_DFU_FIRST(a, ...) a -#define _TUD_DFU_REST(a, ...) __VA_ARGS__ -#define _TUD_DFU_COMBINE(...) __VA_ARGS__ - -#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) - -#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ - TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) - -// Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1, string index n] -#define TUD_DFU_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ - TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ - TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx + +#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx) + +#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) + //------------- CDC-ECM -------------// -- cgit v1.3.1 From daca9e520bce0b4eb5882c5692986ec5c513f319 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Jul 2021 20:47:50 +0700 Subject: wrap up DFU update --- examples/device/dfu/src/main.c | 95 +++++--- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 4 +- src/class/dfu/dfu.h | 47 ++-- src/class/dfu/dfu_device.c | 393 +++++++++++++++++++----------- src/class/dfu/dfu_device.h | 68 +++--- src/class/dfu/dfu_rt_device.c | 6 +- src/common/tusb_types.h | 2 +- src/device/usbd.c | 2 +- src/tusb_option.h | 4 - 10 files changed, 368 insertions(+), 255 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 2c114c5a2..1621a330b 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -26,7 +26,7 @@ /* * After device is enumerated in dfu mode run the following commands * - * To transfer firmware from host to device: + * To transfer firmware from host to device (best to test with text file) * * $ dfu-util -d cafe -a 0 -D [filename] * $ dfu-util -d cafe -a 1 -D [filename] @@ -45,22 +45,21 @@ #include "bsp/board.h" #include "tusb.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#ifndef DFU_VERBOSE -#define DFU_VERBOSE 0 -#endif +const char* upload_image[2]= +{ + "Hello world from TinyUSB DFU! - Partition 0", + "Hello world from TinyUSB DFU! - Partition 1" +}; /* Blink pattern - * - 1000 ms : device should reboot * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ enum { - BLINK_DFU_MODE = 100, BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -118,65 +117,87 @@ void tud_resume_cb(void) } //--------------------------------------------------------------------+ -// Class callbacks +// DFU callbacks +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. //--------------------------------------------------------------------+ -bool tud_dfu_firmware_valid_check_cb(uint8_t alt) -{ - (void) alt; - printf(" Firmware check\r\n"); - return true; -} -uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) { - // For example Alt1 (EEPROM) is slow, add 2000ms timeout if ( state == DFU_DNBUSY ) { - if (alt == 1) return 2000; + // For this example + // - Atl0 Flash is fast : 1 ms + // - Alt1 EEPROM is slow: 100 ms + return (alt == 0) ? 1 : 100; } + else if (state == DFU_MANIFEST) + { + // since we don't buffer entire image and do any flashing in manifest stage + return 0; + } + return 0; } -void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t const* data, uint16_t length) { (void) data; - printf("Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); -#if DFU_VERBOSE for(uint16_t i=0; ibAttributes; - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR + // CFG_TUD_DFU_TRANSFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFSIZE, drv_len); return drv_len; } @@ -216,11 +201,10 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // return false to stall control endpoint (e.g unsupported request) bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - // nothing to do with DATA stage - if ( stage == CONTROL_STAGE_DATA ) return true; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); + if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) { // Standard request include GET/SET_INTERFACE @@ -229,8 +213,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case TUSB_REQ_SET_INTERFACE: if ( stage == CONTROL_STAGE_SETUP ) { - // Switch Alt interface and Re-initalize state machine - _dfu_ctx.alt_num = (uint8_t) request->wValue; + // Switch Alt interface and reset state machine + _dfu_ctx.alt = (uint8_t) request->wValue; reset_state(); return tud_control_status(rhport, request); } @@ -239,7 +223,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case TUSB_REQ_GET_INTERFACE: if(stage == CONTROL_STAGE_SETUP) { - return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); } break; @@ -249,6 +233,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) { + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + // Class request switch ( request->bRequest ) { @@ -259,73 +245,97 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } else if ( stage == CONTROL_STAGE_ACK ) { - if (tud_dfu_detach_cb) tud_dfu_detach_cb(); + if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); } break; - case DFU_REQUEST_ABORT: + case DFU_REQUEST_CLRSTATUS: if ( stage == CONTROL_STAGE_SETUP ) { - if (tud_dfu_abort_cb) tud_dfu_abort_cb(_dfu_ctx.alt_num); - reset_state(); tud_control_status(rhport, request); } break; - case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: if ( stage == CONTROL_STAGE_SETUP ) { - reset_state(); - tud_control_status(rhport, request); + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); } break; - case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: if ( stage == CONTROL_STAGE_SETUP ) { - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); + reset_state(); + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); } break; case DFU_REQUEST_UPLOAD: if ( stage == CONTROL_STAGE_SETUP ) { - TU_VERIFY(_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK); + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); - uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt_num, request->wValue, _dfu_ctx.transfer_buf, request->wLength); + uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); - tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); } break; case DFU_REQUEST_DNLOAD: - { - if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (_dfu_ctx.state == DFU_DNLOAD_SYNC)) + if ( stage == CONTROL_STAGE_SETUP ) { - _dfu_ctx.block = request->wValue; + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); + TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); + + // set to true for both download and manifest + _dfu_ctx.flashing_in_progress = true; + + // save block and length for flashing + _dfu_ctx.block = request->wValue; _dfu_ctx.length = request->wLength; - return true; + + if ( request->wLength ) + { + // Download with payload -> transition to DOWNLOAD SYNC + _dfu_ctx.state = DFU_DNLOAD_SYNC; + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); + } + else + { + // Download is complete -> transition to MANIFEST SYNC + _dfu_ctx.state = DFU_MANIFEST_SYNC; + return tud_control_status(rhport, request); + } } - } - // fallthrough - case DFU_REQUEST_GETSTATUS: + break; - { - if(stage == CONTROL_STAGE_SETUP) + case DFU_REQUEST_GETSTATUS: + switch ( _dfu_ctx.state ) { - return dfu_state_machine(rhport, request); + case DFU_DNLOAD_SYNC: + return process_download_get_status(rhport, stage, request); + break; + + case DFU_MANIFEST_SYNC: + return process_manifest_get_status(rhport, stage, request); + break; + + default: + if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); + break; } - } break; - default: - return false; // stall unsupported request - break; + default: return false; // stall unsupported request } }else { @@ -335,32 +345,130 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque return true; } -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +void tud_dfu_finish_flashing(uint8_t status) +{ + _dfu_ctx.flashing_in_progress = false; + + if ( status == DFU_STATUS_OK ) + { + if (_dfu_ctx.state == DFU_DNBUSY) + { + _dfu_ctx.state = DFU_DNLOAD_SYNC; + } + else if (_dfu_ctx.state == DFU_MANIFEST) + { + _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) + ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; + } + } + else + { + // failed while flashing, move to dfuError + _dfu_ctx.state = DFU_ERROR; + _dfu_ctx.status = status; + } +} + +static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_DNBUSY; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); + } + else + { + next_state = DFU_DNLOAD_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_DNBUSY; + tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); + }else + { + _dfu_ctx.state = DFU_DNLOAD_IDLE; + } + } + + return true; +} + +static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - uint32_t timeout = 0; - if ( tud_dfu_get_status_cb ) + if ( stage == CONTROL_STAGE_SETUP ) { - timeout = tud_dfu_get_status_cb(_dfu_ctx.alt_num, _dfu_ctx.state); + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_MANIFEST; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); + } + else + { + next_state = DFU_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_MANIFEST; + tud_dfu_manifest_cb(_dfu_ctx.alt); + } + else + { + _dfu_ctx.state = DFU_IDLE; + } } - dfu_status_req_payload_t resp; - resp.bStatus = _dfu_ctx.status; + return true; +} + +static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) +{ + dfu_status_response_t resp; + resp.bStatus = (uint8_t) status; resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = _dfu_ctx.state; - resp.iString = 0; + resp.bState = (uint8_t) state; + resp.iString = 0; - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); + return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } + +#if 0 + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { // TODO: add "zero" copy mode so the buffer we read into can be provided by the user // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); // setup for data phase tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); } @@ -368,21 +476,9 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_download_cb(_dfu_ctx.alt_num,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); - _dfu_ctx.blk_transfer_in_proc = false; -} - -void tud_dfu_download_complete(void) -{ - if (_dfu_ctx.state == DFU_DNBUSY) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_ctx.state == DFU_MANIFEST) - { - _dfu_ctx.state = ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); + tud_dfu_download_cb(_dfu_ctx.alt,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); + _dfu_ctx.flashing_in_progress = false; } static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) @@ -398,11 +494,11 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) && (request->wLength > 0) ) { _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.blk_transfer_in_proc = true; + _dfu_ctx.flashing_in_progress = true; dfu_req_dnload_setup(rhport, request); } else { _dfu_ctx.state = DFU_ERROR; @@ -411,7 +507,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -428,14 +524,14 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ( _dfu_ctx.blk_transfer_in_proc ) + if ( _dfu_ctx.flashing_in_progress ) { _dfu_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); dfu_req_dnload_reply(rhport, request); } else { _dfu_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } } break; @@ -466,14 +562,14 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) && (request->wLength > 0) ) { _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.blk_transfer_in_proc = true; + _dfu_ctx.flashing_in_progress = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb(_dfu_ctx.alt_num) ) + if ( tud_dfu_download_complete_cb(_dfu_ctx.alt) ) { _dfu_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -486,7 +582,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -503,17 +599,17 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) == 0) { _dfu_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb(_dfu_ctx.alt_num) ) + if ( tud_dfu_manifest_cb(_dfu_ctx.alt) ) { _dfu_ctx.state = DFU_IDLE; } - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } } break; @@ -556,7 +652,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -571,7 +667,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -590,5 +686,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req return true; } +#endif #endif diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index d5d464f3b..2d398aada 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,53 +37,51 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" +#if !defined(CFG_TUD_DFU_TRANSFER_BUFSIZE) + #error "CFG_TUD_DFU_TRANSFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Must be called when the application is done with flashing started by +// tud_dfu_download_cb() and tud_dfu_manifest_cb(). +// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError +void tud_dfu_finish_flashing(uint8_t status); + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware is valid -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -bool tud_dfu_firmware_valid_check_cb(uint8_t alt); - -// Invoked when a DFU_GETSTATUS request is received -// Return the bwPollTimeout value for host's response, useful for slow Flash in order to make host wait longer -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -TU_ATTR_WEAK uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state); - -// Invoked when a DFU_DNLOAD request is received -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Must be called when the application is done using the last block of data -// provided by tud_dfu_download_cb -void tud_dfu_download_complete(void); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_device_data_done_check_cb(uint8_t alt); -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// Invoked when a DFU_UPLOAD request is received -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// This callback must populate data with up to length bytes -// Return the number of bytes to write +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); + +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); + +// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) +// Application can do checksum, or actual flashing if buffered entire image previously. +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_manifest_cb(uint8_t alt); + +// Invoked when received DFU_UPLOAD request +// Application must populate data with up to length bytes and +// Return the number of written bytes TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received TU_ATTR_WEAK void tud_dfu_detach_cb(void); +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 07e6f30f3..afee2aa1f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -108,10 +108,10 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request case DFU_REQUEST_GETSTATUS: { TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); - dfu_status_req_payload_t resp; + dfu_status_response_t resp; // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 - memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); + memset(&resp, 0x00, sizeof(dfu_status_response_t)); + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } break; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fc1035e2c..eab67ebd5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -449,7 +449,7 @@ typedef struct TU_ATTR_PACKED /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED TU_ATTR_ALIGNED(4) { +typedef struct TU_ATTR_PACKED { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. diff --git a/src/device/usbd.c b/src/device/usbd.c index af4fd58c4..cf9af783d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,7 +190,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_MODE { - DRIVER_NAME("DFU-MODE") + DRIVER_NAME("DFU") .init = dfu_moded_init, .reset = dfu_moded_reset, .open = dfu_moded_open, diff --git a/src/tusb_option.h b/src/tusb_option.h index bf7591dcf..4351d9486 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -253,10 +253,6 @@ #define CFG_TUD_DFU_MODE 0 #endif -#ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE - #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 -#endif - #ifndef CFG_TUD_NET #define CFG_TUD_NET 0 #endif -- cgit v1.3.1 From 3960beece0ea3dccf7ca615bd7841daa6b703d56 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Jul 2021 20:52:58 +0700 Subject: rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU --- examples/device/dfu/src/main.c | 2 +- examples/device/dfu/src/tusb_config.h | 4 +--- src/class/dfu/dfu_device.c | 2 +- src/device/usbd.c | 2 +- src/tusb.h | 2 +- src/tusb_option.h | 4 ++-- 6 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src/device') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 1621a330b..7133d1624 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -148,7 +148,7 @@ uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t const* data, uint16_t length) { (void) data; - printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + //printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); for(uint16_t i=0; i Date: Wed, 21 Jul 2021 13:21:58 +0700 Subject: add dcd_attr for DCD_ATTR_ENDPOINT_MAX could be useful with more dcd specific attribute --- src/device/dcd.h | 2 + src/device/dcd_attr.h | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/device/usbd.c | 19 +++++-- src/device/usbd.h | 3 -- src/tusb_option.h | 34 +++++------- 5 files changed, 175 insertions(+), 29 deletions(-) create mode 100644 src/device/dcd_attr.h (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 63e97df96..11f8ca5d3 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -31,6 +31,8 @@ #include "osal/osal.h" #include "common/tusb_fifo.h" +#include "dcd_attr.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h new file mode 100644 index 000000000..5deba27b5 --- /dev/null +++ b/src/device/dcd_attr.h @@ -0,0 +1,146 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * 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_DCD_ATTR_H_ +#define TUSB_DCD_ATTR_H_ + +#include "tusb_option.h" + +// Attribute includes +// - ENDPOINT_MAX: max (logical) number of endpoint +// - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed, +// e.g EP1 OUT & EP1 IN cannot exist together + +//------------- NXP -------------// +#if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX) + #define DCD_ATTR_ENDPOINT_MAX 5 + +#elif TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX) + // TODO USB0 has 6, USB1 has 4 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(LPC51UXX) + #define DCD_ATTR_ENDPOINT_MAX 5 + +#elif TU_CHECK_MCU(LPC54XXX) || TU_CHECK_MCU(LPC55XX) + // TODO USB0 has 5, USB1 has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(MIMXRT10XX) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(MKL25ZXX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Nordic -------------// +#elif TU_CHECK_MCU(NRF5X) + // 8 CBI + 1 ISO + #define DCD_ATTR_ENDPOINT_MAX 9 + +//------------- Microchip -------------// +#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \ + TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(SAMG) + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +//------------- ST -------------// +#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \ + TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4) + // F1: F102, F103 + // L4: L4x2, L4x3 + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3) + // F1: F105, F107 only has 4 + // L4: L4x5, L4x6 has 6 + // For most mcu, FS has 4, HS has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(STM32F7) + // FS has 6, HS has 9 + #define DCD_ATTR_ENDPOINT_MAX 9 + +#elif TU_CHECK_MCU(STM32H7) + #define DCD_ATTR_ENDPOINT_MAX 9 + +//------------- Sony -------------// +#elif TU_CHECK_MCU(CXD56) + #define DCD_ATTR_ENDPOINT_MAX 7 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +//------------- TI -------------// +#elif TU_CHECK_MCU(MSP430x5xx) + #define DCD_ATTR_ENDPOINT_MAX 8 + +//------------- ValentyUSB -------------// +#elif TU_CHECK_MCU(VALENTYUSB_EPTRI) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Nuvoton -------------// +#elif TU_CHECK_MCU(NUC121) || TU_CHECK_MCU(NUC126) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(NUC120) + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(NUC505) + #define DCD_ATTR_ENDPOINT_MAX 12 + +//------------- Espressif -------------// +#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3) + #define DCD_ATTR_ENDPOINT_MAX 6 + +//------------- Dialog -------------// +#elif TU_CHECK_MCU(DA1469X) + #define DCD_ATTR_ENDPOINT_MAX 4 + +//------------- Raspberry Pi -------------// +#elif TU_CHECK_MCU(RP2040) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Silabs -------------// +#elif TU_CHECK_MCU(EFM32GG) + #define DCD_ATTR_ENDPOINT_MAX 7 + +//------------- Renesas -------------// +#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) + #define DCD_ATTR_ENDPOINT_MAX 10 + +//#elif TU_CHECK_MCU(MM32F327X) +// #define DCD_ATTR_ENDPOINT_MAX not knwon yet + +#else + #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" + #define DCD_ATTR_ENDPOINT_MAX 8 +#endif + +#endif diff --git a/src/device/usbd.c b/src/device/usbd.c index af4fd58c4..7de3c4377 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,12 +33,20 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" +//--------------------------------------------------------------------+ +// USBD Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUD_ENDPOINT0_SIZE + #define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + #ifndef CFG_TUD_TASK_QUEUE_SZ -#define CFG_TUD_TASK_QUEUE_SZ 16 + #define CFG_TUD_TASK_QUEUE_SZ 16 #endif -#ifndef CFG_TUD_EP_MAX -#define CFG_TUD_EP_MAX 9 +#ifndef CFG_TUD_ENDPPOINT_MAX + #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX #endif //--------------------------------------------------------------------+ @@ -65,7 +73,7 @@ typedef struct uint8_t speed; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED { @@ -74,7 +82,7 @@ typedef struct volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUD_EP_MAX][2]; + }ep_status[CFG_TUD_ENDPPOINT_MAX][2]; }usbd_device_t; @@ -1151,6 +1159,7 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < DCD_ATTR_ENDPOINT_MAX); switch (desc_ep->bmAttributes.xfer) { diff --git a/src/device/usbd.h b/src/device/usbd.h index 2de6a5cfd..e6a4d550b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -24,9 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbd - * @{ */ - #ifndef _TUSB_USBD_H_ #define _TUSB_USBD_H_ diff --git a/src/tusb_option.h b/src/tusb_option.h index 13d11fdfe..e24e5947c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -32,9 +32,11 @@ #define TUSB_VERSION_REVISION 1 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) -/** \defgroup group_mcu Supported MCU - * \ref CFG_TUSB_MCU must be defined to one of these - * @{ */ +//--------------------------------------------------------------------+ +// Supported MCUs +// CFG_TUSB_MCU must be defined to one of following value +//--------------------------------------------------------------------+ +#define TU_CHECK_MCU(_m) (CFG_TUSB_MCU == OPT_MCU_##_m) #define OPT_MCU_NONE 0 @@ -119,18 +121,16 @@ // Mind Motion #define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 -/** @} */ +//--------------------------------------------------------------------+ +// Supported OS +//--------------------------------------------------------------------+ -/** \defgroup group_supported_os Supported RTOS - * \ref CFG_TUSB_OS must be defined to one of these - * @{ */ #define OPT_OS_NONE 1 ///< No RTOS #define OPT_OS_FREERTOS 2 ///< FreeRTOS #define OPT_OS_MYNEWT 3 ///< Mynewt OS #define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application #define OPT_OS_PICO 5 ///< Raspberry Pi Pico SDK #define OPT_OS_RTTHREAD 6 ///< RT-Thread -/** @} */ // Allow to use command line to change the config name/location #ifdef CFG_TUSB_CONFIG_FILE @@ -139,10 +139,6 @@ #include "tusb_config.h" #endif -/** \addtogroup group_configuration - * @{ */ - - //-------------------------------------------------------------------- // RootHub Mode Configuration // CFG_TUSB_RHPORTx_MODE contains operation mode and speed for that port @@ -214,10 +210,6 @@ // DEVICE OPTIONS //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - #ifndef CFG_TUD_CDC #define CFG_TUD_CDC 0 #endif @@ -277,7 +269,7 @@ //------------- HUB CLASS -------------// #if CFG_TUH_HUB && (CFG_TUSB_HOST_DEVICE_MAX == 1) - #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX + #error There is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX #endif #ifndef CFG_TUH_ENUMERATION_BUFSIZE @@ -288,12 +280,11 @@ #endif // TUSB_OPT_HOST_ENABLED //--------------------------------------------------------------------+ -// Port Options -// TUP for TinyUSB Port (can be renamed) +// Port Specific +// TUP stand for TinyUSB Port (can be renamed) //--------------------------------------------------------------------+ -// TUP_ARCH_STRICT_ALIGN if arch cannot access unaligned memory - +//------------- Unaligned Memory -------------// // ARMv7+ (M3-M7, M23-M33) can access unaligned memory #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) @@ -312,6 +303,7 @@ #define TUP_MCU_STRICT_ALIGN 0 #endif + //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -- cgit v1.3.1 From 37cac414f83fb939d8b9e4c41d5fa49a6f0e309e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Jul 2021 17:00:02 +0700 Subject: fix ci --- src/device/dcd.h | 13 ++++++++++++- src/device/dcd_attr.h | 12 +++++++++++- src/device/usbd.c | 8 -------- src/device/usbd.h | 4 ++-- src/tusb_option.h | 4 ++++ 5 files changed, 29 insertions(+), 12 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 11f8ca5d3..8bfad9b72 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -30,13 +30,24 @@ #include "common/tusb_common.h" #include "osal/osal.h" #include "common/tusb_fifo.h" - #include "dcd_attr.h" #ifdef __cplusplus extern "C" { #endif +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUD_ENDPPOINT_MAX + #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + typedef enum { DCD_EVENT_INVALID = 0, diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 5deba27b5..2fd235a96 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -33,6 +33,7 @@ // - ENDPOINT_MAX: max (logical) number of endpoint // - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed, // e.g EP1 OUT & EP1 IN cannot exist together +// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. //------------- NXP -------------// #if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX) @@ -48,7 +49,11 @@ #elif TU_CHECK_MCU(LPC51UXX) #define DCD_ATTR_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(LPC54XXX) || TU_CHECK_MCU(LPC55XX) +#elif TU_CHECK_MCU(LPC54XXX) + // TODO USB0 has 5, USB1 has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(LPC55XX) // TODO USB0 has 5, USB1 has 6 #define DCD_ATTR_ENDPOINT_MAX 6 @@ -143,4 +148,9 @@ #define DCD_ATTR_ENDPOINT_MAX 8 #endif +// Default to fullspeed if not defined +//#ifndef PORT_HIGHSPEED +// #define DCD_ATTR_PORT_HIGHSPEED 0x00 +//#endif + #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 7de3c4377..b724c73e8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -37,18 +37,10 @@ // USBD Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif -#ifndef CFG_TUD_ENDPPOINT_MAX - #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX -#endif - //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index e6a4d550b..9500ad70c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -27,12 +27,12 @@ #ifndef _TUSB_USBD_H_ #define _TUSB_USBD_H_ +#include "common/tusb_common.h" + #ifdef __cplusplus extern "C" { #endif -#include "common/tusb_common.h" - //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index e24e5947c..dfac46374 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -210,6 +210,10 @@ // DEVICE OPTIONS //-------------------------------------------------------------------- +#ifndef CFG_TUD_ENDPOINT0_SIZE + #define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + #ifndef CFG_TUD_CDC #define CFG_TUD_CDC 0 #endif -- cgit v1.3.1 From a9f3532252c09d2bcc0fc23994be3d0753a974ef Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Jul 2021 18:08:19 +0700 Subject: more ci --- src/device/dcd_attr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 2fd235a96..4bba03c87 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -133,7 +133,7 @@ #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Silabs -------------// -#elif TU_CHECK_MCU(EFM32GG) +#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(OPT_MCU_EFM32GG11) || TU_CHECK_MCU(OPT_MCU_EFM32GG12) #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -- cgit v1.3.1 From 8ee1141a70dd40063c667ea2b117590a174d9ea6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Jul 2021 18:25:53 +0700 Subject: correct check --- src/device/dcd_attr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 4bba03c87..544b0a75b 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -133,7 +133,7 @@ #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Silabs -------------// -#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(OPT_MCU_EFM32GG11) || TU_CHECK_MCU(OPT_MCU_EFM32GG12) +#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12) #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -- cgit v1.3.1 From aff7b100ca87482e9e1d29f7e854d77cadbd6b98 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 00:28:37 +0700 Subject: update dcd attr for samx7x --- src/device/dcd_attr.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/device') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 544b0a75b..306335642 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -77,6 +77,10 @@ #define DCD_ATTR_ENDPOINT_MAX 6 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER +#elif TU_CHECK_MCU(SAMX7X) + #define DCD_ATTR_ENDPOINT_MAX 10 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + //------------- ST -------------// #elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \ TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4) -- cgit v1.3.1 From b35ad6edcb8b723c481246532349d21b35c46ac1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:04:55 +0700 Subject: clean up max packet size endian --- src/device/dcd_attr.h | 4 ++-- src/device/usbd.c | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 306335642..18f369332 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -141,11 +141,11 @@ #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) +#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N) #define DCD_ATTR_ENDPOINT_MAX 10 //#elif TU_CHECK_MCU(MM32F327X) -// #define DCD_ATTR_ENDPOINT_MAX not knwon yet +// #define DCD_ATTR_ENDPOINT_MAX not known yet #else #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" diff --git a/src/device/usbd.c b/src/device/usbd.c index e4f2e1cf9..5a7d0ab0f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1150,15 +1150,17 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, tu_le16toh(desc_ep->wMaxPacketSize.size)); - TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < DCD_ATTR_ENDPOINT_MAX); + uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); + + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); + TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_ISOCHRONOUS: { - uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); + uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(max_packet_size <= spec_size); } break; @@ -1166,18 +1168,18 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) if (_usbd_dev.speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) == 512); + TU_ASSERT(max_packet_size == 512); }else { // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= 64); + TU_ASSERT(max_packet_size <= 64); } break; case TUSB_XFER_INTERRUPT: { - uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); + uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); + TU_ASSERT(max_packet_size <= spec_size); } break; -- cgit v1.3.1 From 8cd23489d518e96594850207c91dfeefb6d6fb05 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:45:24 +0700 Subject: update endian --- src/device/usbd.c | 10 ++++------ src/device/usbd_control.c | 1 - src/portable/renesas/usba/dcd_usba.c | 13 +++++-------- 3 files changed, 9 insertions(+), 15 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 5a7d0ab0f..a30eab217 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -953,11 +953,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); - uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address - memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength)) ); - return tud_control_xfer(rhport, p_request, (void*) desc_bos, tu_le16toh(total_len)); + return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } break; @@ -968,11 +967,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); TU_ASSERT(desc_config); - uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address - memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); - return tud_control_xfer(rhport, p_request, (void*) desc_config, tu_le16toh(total_len)); + return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } break; diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 124f711a7..7a8244699 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -58,7 +58,6 @@ static usbd_control_xfer_t _ctrl_xfer; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; - //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index f68f97458..0b78a6e46 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -95,7 +95,10 @@ #define FIFO_REQ_CLR (1u) #define FIFO_COMPLETE (1u<<1) +// Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN + typedef struct { union { struct { @@ -108,9 +111,7 @@ typedef struct { }; uint16_t TRN; } reg_pipetre_t; -TU_ATTR_BIT_FIELD_ORDER_END -TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef union { struct { volatile uint16_t u8: 8; @@ -118,11 +119,7 @@ typedef union { }; volatile uint16_t u16; } hw_fifo_t; -TU_ATTR_BIT_FIELD_ORDER_END -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) - -TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ @@ -133,9 +130,9 @@ typedef struct TU_ATTR_PACKED uint32_t : 0; }; } pipe_state_t; -TU_ATTR_BIT_FIELD_ORDER_END TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_BIT_FIELD_ORDER_END typedef struct { @@ -147,7 +144,7 @@ typedef struct //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static dcd_data_t _dcd; +static dcd_data_t _dcd; static uint32_t disable_interrupt(void) { -- cgit v1.3.1 From 768282982039001128cecfe125d88f58ce640713 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sat, 7 Aug 2021 09:01:01 +0200 Subject: Add correct endpoint count for GD32VF103 This controller family only supports USB FS with four endpoints --- src/device/dcd_attr.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/device') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 18f369332..7772a6d96 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -147,6 +147,10 @@ //#elif TU_CHECK_MCU(MM32F327X) // #define DCD_ATTR_ENDPOINT_MAX not known yet +//------------- GigaDevice -------------// +#elif TU_CHECK_MCU(GD32VF103) + #define DCD_ATTR_ENDPOINT_MAX 4 + #else #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" #define DCD_ATTR_ENDPOINT_MAX 8 -- cgit v1.3.1 From 88d4cb402d5db6cb88ffa0aecb78fccfe3ab0afd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 00:11:04 +0700 Subject: simplify hw_endpoint_init() --- src/device/dcd.h | 1 + src/portable/raspberrypi/rp2040/dcd_rp2040.c | 65 +++++++++++++--------------- 2 files changed, 31 insertions(+), 35 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 8bfad9b72..66767c1fe 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -152,6 +152,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // clear stall, data toggle is also reset to DATA0 +// This API never calls with control endpoints, since it is auto cleared when receiving setup packet void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 0dabdd1d7..ca083d500 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -101,8 +101,29 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) *ep->endpoint_control = reg; } -static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) +#if 0 // todo unused +static void _hw_endpoint_close(struct hw_endpoint *ep) +{ + // Clear hardware registers and then zero the struct + // Clears endpoint enable + *ep->endpoint_control = 0; + // Clears buffer available, etc + *ep->buffer_control = 0; + // Clear any endpoint state + memset(ep, 0, sizeof(struct hw_endpoint)); +} + +static void hw_endpoint_close(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_close(ep); +} +#endif + +static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + const uint8_t num = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); @@ -112,7 +133,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t ep->rx = (dir == TUSB_DIR_OUT); // Response to a setup packet on EP0 starts with pid of 1 - ep->next_pid = num == 0 ? 1u : 0u; + ep->next_pid = (num == 0 ? 1u : 0u); ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; @@ -152,7 +173,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t } // Now if it hasn't already been done - //alloc a buffer and fill in endpoint control register + // alloc a buffer and fill in endpoint control register // TODO device may change configuration (dynamic), should clear and reallocate if(!(ep->configured)) { @@ -163,31 +184,6 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t ep->configured = true; } -#if 0 // todo unused -static void _hw_endpoint_close(struct hw_endpoint *ep) -{ - // Clear hardware registers and then zero the struct - // Clears endpoint enable - *ep->endpoint_control = 0; - // Clears buffer available, etc - *ep->buffer_control = 0; - // Clear any endpoint state - memset(ep, 0, sizeof(struct hw_endpoint)); -} - -static void hw_endpoint_close(uint8_t ep_addr) -{ - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_close(ep); -} -#endif - -static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t bmAttributes) -{ - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes); -} - static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); @@ -290,7 +286,6 @@ static void dcd_rp2040_irq(void) usb_hw->dev_addr_ctrl = 0; bus_reset(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); - usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX @@ -394,13 +389,13 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { - pico_trace("dcd_set_address %d %d\n", rhport, dev_addr); - assert(rhport == 0); + pico_trace("dcd_set_address %d %d\n", rhport, dev_addr); + assert(rhport == 0); - // Can't set device address in hardware until status xfer has complete - // Send 0len complete response on EP0 IN - reset_ep0(); - hw_endpoint_xfer(0x80, NULL, 0); + // Can't set device address in hardware until status xfer has complete + // Send 0len complete response on EP0 IN + reset_ep0(); + hw_endpoint_xfer(0x80, NULL, 0); } void dcd_remote_wakeup(uint8_t rhport) -- cgit v1.3.1 From 17ef9f4843250e8c6b6b1fde53ed6a54a4f20470 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 15:46:33 +0700 Subject: add ready check for edpt claim --- src/device/usbd.c | 5 +++++ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index a30eab217..bef7725b5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1191,6 +1191,8 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) { (void) rhport; + TU_VERIFY(tud_ready()); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1244,6 +1246,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + // TODO skip ready() check for now since enumeration also use this API + // TU_VERIFY(tud_ready()); + TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 63d8278da..49284e92e 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -284,9 +284,6 @@ static void dcd_rp2040_irq(void) #endif } -#if 1 - // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection - /* Note from pico datasheet 4.1.2.6.4 (v1.2) * If you enable the suspend interrupt, it is likely you will see a suspend interrupt when * the device is first connected but the bus is idle. The bus can be idle for a few ms before @@ -308,7 +305,6 @@ static void dcd_rp2040_irq(void) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS; } -#endif if (status ^ handled) { -- cgit v1.3.1 From d52b981c3af06233891e827edcd484ece244a5a8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 17:07:39 +0700 Subject: revert ready() check in claim (do it later in separated PR) --- src/device/usbd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index bef7725b5..a15959710 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1191,7 +1191,8 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - TU_VERIFY(tud_ready()); + // TODO add this check later, also make sure we don't starve an out endpoint while suspending + // TU_VERIFY(tud_ready()); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); -- cgit v1.3.1 From ab2eec77d46b0c4984ff0daa13467dde2dc4ad3c Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Aug 2021 20:22:14 +0700 Subject: complete suspend, resume, remote wakeup for nrf52 --- src/device/usbd.c | 29 ++++++++-- src/portable/nordic/nrf5x/dcd_nrf5x.c | 103 ++++++++++++++++++++++++---------- 2 files changed, 97 insertions(+), 35 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index a30eab217..538964a3d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -37,6 +37,9 @@ // USBD Configuration //--------------------------------------------------------------------+ +// Debug level of USBD +#define USBD_DBG_LVL 2 + #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -556,7 +559,7 @@ void tud_task (void) break; case DCD_EVENT_SUSPEND: - TU_LOG2("\r\n"); + TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; @@ -684,6 +687,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); + TU_LOG(USBD_DBG_LVL, " Enable Remote Wakeup\r\n"); + // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; tud_control_status(rhport, p_request); @@ -693,6 +698,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); + TU_LOG(USBD_DBG_LVL, " Disable Remote Wakeup\r\n"); + // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; tud_control_status(rhport, p_request); @@ -1036,10 +1043,6 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) } break; - case DCD_EVENT_SOF: - return; // skip SOF event for now - break; - case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). @@ -1061,6 +1064,17 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) } break; + case DCD_EVENT_SOF: + // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup + // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational + if ( _usbd_dev.suspended ) + { + _usbd_dev.suspended = 0; + dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME }; + osal_queue_send(_usbd_q, &event_resume, in_isr); + } + break; + default: osal_queue_send(_usbd_q, event, in_isr); break; @@ -1312,6 +1326,8 @@ bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + TU_LOG(USBD_DBG_LVL, " Stall EP %02X", ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1322,9 +1338,12 @@ void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + TU_LOG(USBD_DBG_LVL, " Clear Stall EP %02X", ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + dcd_edpt_clear_stall(rhport, ep_addr); _usbd_dev.ep_status[epnum][dir].stalled = false; _usbd_dev.ep_status[epnum][dir].busy = false; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 5f4fe08ad..f6b64c986 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -85,7 +85,7 @@ static struct // Number of pending DMA that is started but not handled yet by dcd_int_handler(). // Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1. // However, in critical section with interrupt disabled, the DMA can be finished and added up - // until handled by dcd_init_handler() when exiting critical section. + // until handled by dcd_int_handler() when exiting critical section. volatile uint8_t dma_pending; }_dcd; @@ -277,14 +277,8 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; // Bring controller out of low power mode + // will start wakeup when USBWUALLOWED is set NRF_USBD->LOWPOWER = 0; - - // Initiate RESUME signal - NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume; - NRF_USBD->TASKS_DPDMDRIVE = 1; - - // TODO There is no USBEVENT Resume interrupt - // We may manually raise DCD_EVENT_RESUME event here } // disconnect by disabling internal pull-up resistor on D+/D- @@ -339,10 +333,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { // SPLIT ISO buffer when ISO IN endpoint is already opened. if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; + // Clear old events NRF_USBD->EVENTS_ENDISOOUT = 0; + // Clear SOF event in case interrupt was not enabled yet. if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + // Enable SOF and ISOOUT interrupts, and ISOOUT endpoint. NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk; NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk; @@ -350,10 +347,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) else { NRF_USBD->EVENTS_ENDISOIN = 0; + // SPLIT ISO buffer when ISO OUT endpoint is already opened. if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_OUT].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; + // Clear SOF event in case interrupt was not enabled yet. if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + // Enable SOF and ISOIN interrupts, and ISOIN endpoint. NRF_USBD->INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk; NRF_USBD->EPINEN |= USBD_EPINEN_ISOIN_Msk; @@ -507,6 +507,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) *------------------------------------------------------------------*/ void bus_reset(void) { + // 6.35.6 USB controller automatically disabled all endpoints (except control) + // i.e EPOUTEN and EPINEN and reset USBADDR to 0 for(int i=0; i<8; i++) { NRF_USBD->TASKS_STARTEPIN[i] = 0; @@ -516,6 +518,15 @@ void bus_reset(void) NRF_USBD->TASKS_STARTISOIN = 0; NRF_USBD->TASKS_STARTISOOUT = 0; + // Clear USB Event Interrupt + NRF_USBD->EVENTS_USBEVENT = 0; + NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE; + + // Reset interrupt + NRF_USBD->INTENCLR = NRF_USBD->INTEN; + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk | + USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk; + tu_varclr(&_dcd); _dcd.xfer[0][TUSB_DIR_IN].mps = MAX_PACKET_SIZE; _dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE; @@ -561,39 +572,71 @@ void dcd_int_handler(uint8_t rhport) if ( int_status & USBD_INTEN_SOF_Msk ) { + bool iso_enabled = false; + // ISOOUT: Transfer data gathered in previous frame from buffer to RAM if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk) { + iso_enabled = true; xact_out_dma(EP_ISO_NUM); } + // ISOIN: Notify client that data was transferred - xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN); - if ( xfer->iso_in_transfer_ready ) + if (NRF_USBD->EPINEN & USBD_EPINEN_ISOIN_Msk) { - xfer->iso_in_transfer_ready = false; - dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + iso_enabled = true; + + xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN); + if ( xfer->iso_in_transfer_ready ) + { + xfer->iso_in_transfer_ready = false; + dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + } } + + if ( !iso_enabled ) + { + // ISO endpoint is not used, SOF is only enabled one-time for remote wakeup + // so we disable it now + NRF_USBD->INTENCLR = USBD_INTENSET_SOF_Msk; + } + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } if ( int_status & USBD_INTEN_USBEVENT_Msk ) { - uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & (USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk); + TU_LOG(2, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE); + + enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk }; + uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK; NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk ) { - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); - // Put controller into low power mode + // Leave HFXO disable to application, since it may be used by other peripherals NRF_USBD->LOWPOWER = 1; - // Leave HFXO disable to application, since it may be used by other + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } - if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk ) + if ( evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk ) { - dcd_event_bus_signal(0, DCD_EVENT_RESUME , true); + // USB is out of low power mode, and wakeup is allowed + // Initiate RESUME signal + NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume; + NRF_USBD->TASKS_DPDMDRIVE = 1; + + // There is no Resume interrupt for remote wakeup, enable SOF for to report bus ready state + // Clear SOF event in case interrupt was not enabled yet. + if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk; + } + + if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk ) + { + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } } @@ -845,18 +888,22 @@ void tusb_hal_nrf_power_event (uint32_t event) USB_EVT_READY = 2 }; +#if CFG_TUSB_DEBUG >= 2 + const char* const power_evt_str[] = { "Detected", "Removed", "Ready" }; + TU_LOG(2, "Power USB event: %s\r\n", power_evt_str[event]); +#endif + switch ( event ) { case USB_EVT_DETECTED: - TU_LOG2("Power USB Detect\r\n"); - if ( !NRF_USBD->ENABLE ) { - /* Prepare for READY event receiving */ + // Prepare for receiving READY event: disable interrupt since we will blocking wait + NRF_USBD->INTENCLR = USBD_INTEN_USBEVENT_Msk; NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; __ISB(); __DSB(); // for sync -#ifdef NRF52_SERIES +#ifdef NRF52_SERIES // NRF53 does not need this errata // ERRATA 171, 187, 166 if ( nrfx_usbd_errata_187() ) { @@ -891,7 +938,7 @@ void tusb_hal_nrf_power_event (uint32_t event) } #endif - /* Enable the peripheral */ + // Enable the peripheral (will cause Ready event) NRF_USBD->ENABLE = 1; __ISB(); __DSB(); // for sync @@ -901,13 +948,11 @@ void tusb_hal_nrf_power_event (uint32_t event) break; case USB_EVT_READY: - TU_LOG2("Power USB Ready\r\n"); - // Skip if pull-up is enabled and HCLK is already running. // Application probably call this more than necessary. if ( NRF_USBD->USBPULLUP && hfclk_running() ) break; - /* Waiting for USBD peripheral enabled */ + // Waiting for USBD peripheral enabled while ( !(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE) ) { } NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; @@ -959,9 +1004,8 @@ void tusb_hal_nrf_power_event (uint32_t event) // ISO buffer Lower half for IN, upper half for OUT NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; - // Enable interrupt - NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_EPDATA_Msk | - USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk; + // Enable bus-reset interrupt + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk; // Enable interrupt, priorities should be set by application NVIC_ClearPendingIRQ(USBD_IRQn); @@ -976,7 +1020,6 @@ void tusb_hal_nrf_power_event (uint32_t event) break; case USB_EVT_REMOVED: - TU_LOG2("Power USB Removed\r\n"); if ( NRF_USBD->ENABLE ) { // Abort all transfers -- cgit v1.3.1 From 9b869463ddd7277befa30f8e781b9d72ae005c07 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Aug 2021 17:00:53 +0700 Subject: skipped suspend/resume if not connected --- src/device/usbd.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 538964a3d..e8a50352c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -559,13 +559,28 @@ void tud_task (void) break; case DCD_EVENT_SUSPEND: - TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + // NOTE: When plugging/unplugging device, the D+/D- state are unstable and + // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event + // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected + if ( _usbd_dev.connected ) + { + TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); + if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + }else + { + TU_LOG2(" Skipped\r\n"); + } break; case DCD_EVENT_RESUME: - TU_LOG2("\r\n"); - if (tud_resume_cb) tud_resume_cb(); + if ( _usbd_dev.connected ) + { + TU_LOG2("\r\n"); + if (tud_resume_cb) tud_resume_cb(); + }else + { + TU_LOG2(" Skipped\r\n"); + } break; case DCD_EVENT_SOF: -- cgit v1.3.1 From 1cef2b6a42d93704847c1a6ab82617e5baf04f4a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 18:01:10 +0700 Subject: extra common edpt helper for device and host stack tu_edpt_validate() and tu_edpt_bind_driver() --- src/common/tusb_common.h | 14 ++ src/device/usbd.c | 58 +------- src/host/usbh.c | 338 ++++++++++++++++++++++++-------------------- src/host/usbh_classdriver.h | 2 + src/tusb.c | 62 ++++++++ 5 files changed, 265 insertions(+), 209 deletions(-) (limited to 'src/device') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index c8a66a879..302e75277 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -73,6 +73,20 @@ #include "tusb_error.h" // TODO remove #include "tusb_timeout.h" // TODO remove +//--------------------------------------------------------------------+ +// Internal Helper used by Host and Device Stack +//--------------------------------------------------------------------+ + +// Check if endpoint descriptor is valid per USB specs +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); + +// Bind all endpoint of a interface descriptor to class driver +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); + +//--------------------------------------------------------------------+ +// Internal Inline Functions +//--------------------------------------------------------------------+ + //------------- Mem -------------// #define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) diff --git a/src/device/usbd.c b/src/device/usbd.c index 8b4f4e7e3..23f174dab 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -274,7 +274,6 @@ static osal_mutex_t _usbd_mutex; //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ -static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -901,7 +900,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor + // bind all endpoints for this driver + tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); p_desc += drv_len; // next interface @@ -919,25 +919,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } -// Helper marking endpoint of interface belongs to class driver -static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -{ - uint16_t len = 0; - - while( len < desc_len ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; - } - - len = (uint16_t)(len + tu_desc_len(p_desc)); - p_desc = tu_desc_next(p_desc); - } -} - // return descriptor's buffer and update desc_len static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request) { @@ -1177,41 +1158,8 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); - - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); - - switch (desc_ep->bmAttributes.xfer) - { - case TUSB_XFER_ISOCHRONOUS: - { - uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - case TUSB_XFER_BULK: - if (_usbd_dev.speed == TUSB_SPEED_HIGH) - { - // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(max_packet_size == 512); - }else - { - // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(max_packet_size <= 64); - } - break; - - case TUSB_XFER_INTERRUPT: - { - uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - default: return false; - } + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); return dcd_edpt_open(rhport, desc_ep); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 93621c42a..36c2ea7c8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -28,16 +28,23 @@ #if TUSB_OPT_HOST_ENABLED -#ifndef CFG_TUH_TASK_QUEUE_SZ -#define CFG_TUH_TASK_QUEUE_SZ 16 -#endif - #include "tusb.h" #include "host/usbh.h" #include "host/usbh_classdriver.h" #include "hub.h" #include "usbh_hcd.h" +//--------------------------------------------------------------------+ +// USBH Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_TASK_QUEUE_SZ +#define CFG_TUH_TASK_QUEUE_SZ 16 +#endif + +// Debug level of USBD +#define USBH_DBG_LVL 2 + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -135,6 +142,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); @@ -314,151 +322,6 @@ uint8_t* usbh_get_enum_buf(void) return _usbh_ctrl_buf; } -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() - // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; - - if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); - - tusb_desc_endpoint_t ep0_desc = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = max_packet_size }, - .bInterval = 0 - }; - - return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); -} - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -{ - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); - - bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep); - - if (ret) - { - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - // new endpoints belongs to latest interface (last valid value) - // TODO FIXME not true with ISO - uint8_t drvid = 0xff; - for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) - { - if ( dev->itf2drv[i] == 0xff ) break; - drvid = dev->itf2drv[i]; - } - TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); - - uint8_t const ep_addr = desc_ep->bEndpointAddress; - dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; - } - - return ret; -} - -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - return dev->ep_status[epnum][dir].busy; -} - - //--------------------------------------------------------------------+ // HCD Event Handler //--------------------------------------------------------------------+ @@ -841,7 +704,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address - TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); + TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); @@ -981,6 +844,34 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +// Get total length of n interface (depending on IAD) +static uint16_t get_interface_length(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) break; + + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; +} + static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -992,20 +883,25 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura while( p_desc < desc_end ) { // TODO Do we need to use IAD - // tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + tusb_desc_interface_assoc_t const * desc_iad = NULL; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - // desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; p_desc = tu_desc_next(p_desc); } + TU_LOG_INT(2, p_desc - (uint8_t*) desc_cfg); + TU_LOG_INT(2, tu_desc_type(p_desc)); TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; uint16_t const remaining_len = desc_end-p_desc; + uint16_t const drv_len = get_interface_length(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, remaining_len); + TU_ASSERT(drv_len); + // Check if class is supported TODO drop class_code uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) @@ -1015,8 +911,11 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura if( drv_id >= USBH_CLASS_DRIVER_COUNT ) { - // skip unsupported class - p_desc = tu_desc_next(p_desc); + TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + + // skip unsupported class until next Interface or IAD descriptor + p_desc += drv_len; } else { @@ -1038,6 +937,10 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len); TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len); + + // bind all endpoints for this driver + tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); + p_desc += itf_len; } } @@ -1046,4 +949,131 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura return true; } +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); + + tusb_desc_endpoint_t ep0_desc = + { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = max_packet_size }, + .bInterval = 0 + }; + + return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); +} + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); + + return hcd_edpt_open(rhport, dev_addr, desc_ep); +} + +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + return dev->ep_status[epnum][dir].busy; +} + + + #endif diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 0736fefa1..b05a33580 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -73,6 +73,8 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); diff --git a/src/tusb.c b/src/tusb.c index 0350fa1de..260a6506f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -63,6 +63,68 @@ bool tusb_inited(void) return ret; } +//--------------------------------------------------------------------+ +// Internal Helper for both Host and Device stack +//--------------------------------------------------------------------+ + +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) +{ + uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); + + switch (desc_ep->bmAttributes.xfer) + { + case TUSB_XFER_ISOCHRONOUS: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + case TUSB_XFER_BULK: + if (speed == TUSB_SPEED_HIGH) + { + // Bulk highspeed must be EXACTLY 512 + TU_ASSERT(max_packet_size == 512); + }else + { + // TODO Bulk fullspeed can only be 8, 16, 32, 64 + TU_ASSERT(max_packet_size <= 64); + } + break; + + case TUSB_XFER_INTERRUPT: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + default: return false; + } + + return true; +} + +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while( len < desc_len ) + { + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + + ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; + } + + len = (uint16_t)(len + tu_desc_len(p_desc)); + p_desc = tu_desc_next(p_desc); + } +} + /*------------------------------------------------------------------*/ /* Debug *------------------------------------------------------------------*/ -- cgit v1.3.1 From beb1a5c678dd50c3142d2c74a29e92affa0b06c9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:39:33 +0700 Subject: minor clean up --- src/device/usbd.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 23f174dab..e12dafcfd 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -856,12 +856,12 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + tusb_desc_interface_assoc_t const * desc_iad = NULL; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; p_desc = tu_desc_next(p_desc); // next to Interface } @@ -870,6 +870,13 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; uint16_t const remaining_len = desc_end-p_desc; + // Interface number must not be used already + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); + + // TODO usbd can calculate the total length used for driver --> driver open() does not need to calculate it + // uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); + + // Find driver for this interface uint8_t drv_id; for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { @@ -881,31 +888,30 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Open successfully, check if length is correct TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); - // Interface number must not be used already - TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - TU_LOG2(" %s opened\r\n", driver->name); + + // bind interface to found driver _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - // If IAD exist, assign all interfaces to the same driver - if (desc_itf_assoc) + // If using IAD, bind all interfaces to the same driver + if (desc_iad) { // IAD's first interface number and class should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); + TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - for(uint8_t i=1; ibInterfaceCount; i++) + for(uint8_t i=1; ibInterfaceCount; i++) { _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; } } - // bind all endpoints for this driver + // bind all endpoints to found driver tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); p_desc += drv_len; // next interface - break; + break; // exit driver find loop } } -- cgit v1.3.1