diff --git a/makefiles/stdio.inc.mk b/makefiles/stdio.inc.mk index 90047a7f5d..5ceb452228 100644 --- a/makefiles/stdio.inc.mk +++ b/makefiles/stdio.inc.mk @@ -9,6 +9,7 @@ STDIO_MODULES = \ stdio_semihosting \ stdio_uart \ stdio_telnet \ + stdio_tinyusb_cdc_acm \ # # select stdio_uart if no other stdio module is slected @@ -22,6 +23,10 @@ ifneq (,$(filter stdio_cdc_acm,$(USEMODULE))) USEMODULE += stdio_available endif +ifneq (,$(filter stdio_tinyusb_cdc_acm,$(USEMODULE))) + USEPKG += tinyusb +endif + ifneq (,$(filter stdio_rtt,$(USEMODULE))) USEMODULE += ztimer_msec endif diff --git a/pkg/tinyusb/Makefile b/pkg/tinyusb/Makefile index f4947cafd7..9fc37cb78b 100644 --- a/pkg/tinyusb/Makefile +++ b/pkg/tinyusb/Makefile @@ -11,9 +11,12 @@ PSRC = $(PKG_SOURCE_DIR)/src .PHONY: all -all: $(filter tinyusb_%,$(USEMODULE)) +all: $(filter tinyusb_% stdio_tinyusb_cdc_acm,$(USEMODULE)) $(QQ)"$(MAKE)" -C $(PSRC) -f $(RIOTBASE)/Makefile.base MODULE=tinyusb +stdio_tinyusb_cdc_acm: + $(QQ)"$(MAKE)" -C $(RIOTPKG)/$(PKG_NAME)/cdc_acm_stdio + tinyusb_contrib: $(QQ)"$(MAKE)" -C $(RIOTPKG)/$(PKG_NAME)/contrib diff --git a/pkg/tinyusb/Makefile.dep b/pkg/tinyusb/Makefile.dep index 2658b63799..fb62f89d19 100644 --- a/pkg/tinyusb/Makefile.dep +++ b/pkg/tinyusb/Makefile.dep @@ -8,6 +8,11 @@ USEMODULE += tinyusb_hw DEFAULT_MODULE += auto_init_tinyusb +ifneq (,$(filter stdio_tinyusb_cdc_acm, $(USEMODULE))) + USEMODULE += tinyusb_class_cdc + USEMODULE += tinyusb_device +endif + ifeq (,$(filter tinyusb_class_%,$(USEMODULE))) $(error At least one tinyusb_class_* module has to be enabled) endif diff --git a/pkg/tinyusb/cdc_acm_stdio/Makefile b/pkg/tinyusb/cdc_acm_stdio/Makefile new file mode 100644 index 0000000000..4ccfa930ea --- /dev/null +++ b/pkg/tinyusb/cdc_acm_stdio/Makefile @@ -0,0 +1,3 @@ +MODULE = stdio_tinyusb_cdc_acm + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/tinyusb/cdc_acm_stdio/cdc_acm_stdio.c b/pkg/tinyusb/cdc_acm_stdio/cdc_acm_stdio.c new file mode 100644 index 0000000000..00c75404ce --- /dev/null +++ b/pkg/tinyusb/cdc_acm_stdio/cdc_acm_stdio.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 ML!PA Consulting GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_tinyusb + * @{ + * + * @file + * @brief CDC ACM stdio implementation for tinyUSB CDC ACM + * + * This file implements a USB CDC ACM callback and read/write functions. + * + * @author Benjamin Valentin + * + * @} + */ + +#include +#include + +#include "tusb.h" +#include "tinyusb.h" + +#if MODULE_VFS +#include "vfs.h" +#endif + +#ifdef MODULE_USB_BOARD_RESET +#include "usb_board_reset_internal.h" +#endif + +static mutex_t data_lock = MUTEX_INIT_LOCKED; + +void stdio_init(void) +{ + /* Initialize this side of the CDC ACM pipe */ +#if MODULE_VFS + vfs_bind_stdio(); +#endif +} + +#if IS_USED(MODULE_STDIO_AVAILABLE) +int stdio_available(void) +{ + return tud_cdc_available(); +} +#endif + +ssize_t stdio_read(void* buffer, size_t len) +{ + mutex_lock(&data_lock); + return tud_cdc_read(buffer, len); +} + +ssize_t stdio_write(const void* buffer, size_t len) +{ + const char *start = buffer; + + while (tud_cdc_connected() && len) { + size_t n = tud_cdc_write(buffer, len); + buffer = (char *)buffer + n; + len -= n; + }; + + tud_cdc_write_flush(); + + return (char *)buffer - start; +} + +void tud_cdc_rx_cb(uint8_t itf) +{ + (void)itf; + + mutex_unlock(&data_lock); +}