diff --git a/boards/common/usb/Kconfig.cdc_acm_serial.defconfig b/boards/common/usb/Kconfig.cdc_acm_serial.defconfig index 3a5661a98f413..9af2bfd3125a1 100644 --- a/boards/common/usb/Kconfig.cdc_acm_serial.defconfig +++ b/boards/common/usb/Kconfig.cdc_acm_serial.defconfig @@ -23,23 +23,20 @@ config SHELL_BACKEND_SERIAL_CHECK_DTR config UART_LINE_CTRL default SHELL -config USB_DEVICE_STACK +config USB_DEVICE_STACK_NEXT default y -config USB_DEVICE_INITIALIZE_AT_BOOT +config CDC_ACM_SERIAL_INITIALIZE_AT_BOOT default y if !MCUBOOT -config USB_DEVICE_REMOTE_WAKEUP - default n - if LOG -choice USB_CDC_ACM_LOG_LEVEL_CHOICE - default USB_CDC_ACM_LOG_LEVEL_OFF +choice USBD_CDC_ACM_LOG_LEVEL_CHOICE + default USBD_CDC_ACM_LOG_LEVEL_OFF endchoice -choice USB_DEVICE_LOG_LEVEL_CHOICE - default USB_DEVICE_LOG_LEVEL_OFF +choice USBD_LOG_LEVEL_CHOICE + default USBD_LOG_LEVEL_OFF endchoice # Wait 4000ms at startup for logging diff --git a/boards/common/usb/Kconfig.cdc_acm_serial_legacy.defconfig b/boards/common/usb/Kconfig.cdc_acm_serial_legacy.defconfig new file mode 100644 index 0000000000000..3a5661a98f413 --- /dev/null +++ b/boards/common/usb/Kconfig.cdc_acm_serial_legacy.defconfig @@ -0,0 +1,51 @@ +# Copyright (c) 2023-2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_REQUIRES_SERIAL_BACKEND_CDC_ACM + default y + +if BOARD_SERIAL_BACKEND_CDC_ACM + +config SERIAL + default y + +config CONSOLE + default y + +config UART_CONSOLE + default CONSOLE + +config SHELL_BACKEND_SERIAL_CHECK_DTR + default SHELL + depends on UART_LINE_CTRL + +config UART_LINE_CTRL + default SHELL + +config USB_DEVICE_STACK + default y + +config USB_DEVICE_INITIALIZE_AT_BOOT + default y if !MCUBOOT + +config USB_DEVICE_REMOTE_WAKEUP + default n + +if LOG + +choice USB_CDC_ACM_LOG_LEVEL_CHOICE + default USB_CDC_ACM_LOG_LEVEL_OFF +endchoice + +choice USB_DEVICE_LOG_LEVEL_CHOICE + default USB_DEVICE_LOG_LEVEL_OFF +endchoice + +# Wait 4000ms at startup for logging +config LOG_PROCESS_THREAD_STARTUP_DELAY_MS + default 4000 + +endif # LOG + +endif # BOARD_SERIAL_BACKEND_CDC_ACM diff --git a/boards/seeed/wio_terminal/Kconfig.defconfig b/boards/seeed/wio_terminal/Kconfig.defconfig index 3ff8b29601596..77f3b2fc1c769 100644 --- a/boards/seeed/wio_terminal/Kconfig.defconfig +++ b/boards/seeed/wio_terminal/Kconfig.defconfig @@ -6,4 +6,4 @@ configdefault LV_COLOR_16_SWAP default y if LVGL -source "boards/common/usb/Kconfig.cdc_acm_serial.defconfig" +source "boards/common/usb/Kconfig.cdc_acm_serial_legacy.defconfig" diff --git a/doc/connectivity/usb/device/usb_device.rst b/doc/connectivity/usb/device/usb_device.rst index 2e5649edbe10a..0d38ecec18340 100644 --- a/doc/connectivity/usb/device/usb_device.rst +++ b/doc/connectivity/usb/device/usb_device.rst @@ -212,7 +212,7 @@ DFU USB DFU class implementation is tightly coupled to :ref:`dfu` and :ref:`mcuboot_api`. This means that the target platform must support the :ref:`flash_img_api` API. -See :zephyr:code-sample:`usb-dfu` sample for reference. +See :zephyr:code-sample:`legacy-usb-dfu` sample for reference. USB Human Interface Devices (HID) support ========================================= @@ -373,9 +373,7 @@ Ethernet connection between the remote (USB host) and Zephyr network support. * CDC EEM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_EEM` * RNDIS support, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_RNDIS` -See :zephyr:code-sample:`zperf` or :zephyr:code-sample:`socket-dumb-http-server` for reference. -Typically, users will need to add a configuration file overlay to the build, -such as :zephyr_file:`samples/net/zperf/overlay-netusb.conf`. +See :zephyr:code-sample:`legacy-netusb` sample for reference. Applications using RNDIS support should enable :kconfig:option:`CONFIG_USB_DEVICE_OS_DESC` for a better user experience on a host running Microsoft Windows OS. @@ -389,62 +387,7 @@ The application should register descriptors such as Capability Descriptor using :c:func:`usb_bos_register_cap`. Registered descriptors are added to the root BOS descriptor and handled by the stack. -See :zephyr:code-sample:`webusb` sample for reference. - -Implementing a non-standard USB class -************************************* - -The configuration of USB device is done in the stack layer. - -The following structures and callbacks need to be defined: - -* Part of USB Descriptor table -* USB Endpoint configuration table -* USB Device configuration structure -* Endpoint callbacks -* Optionally class, vendor and custom handlers - -For example, for the USB loopback application: - -.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst config structure start - :end-before: usb.rst config structure end - :linenos: - -Endpoint configuration: - -.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst endpoint configuration start - :end-before: usb.rst endpoint configuration end - :linenos: - -USB Device configuration structure: - -.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst device config data start - :end-before: usb.rst device config data end - :linenos: - - -The vendor device requests are forwarded by the USB stack core driver to the -class driver through the registered vendor handler. - -For the loopback class driver, :c:func:`loopback_vendor_handler` processes -the vendor requests: - -.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst vendor handler start - :end-before: usb.rst vendor handler end - :linenos: - -The class driver waits for the :makevar:`USB_DC_CONFIGURED` device status code -before transmitting any data. - -.. _testing_USB_native_sim: +See :zephyr:code-sample:`legacy-webusb` sample for reference. Interface number and endpoint address assignment ************************************************ @@ -510,6 +453,8 @@ prevent you from implementing a hardware-clone firmware. Instead, if possible, the host driver implementation should be fixed to use values from the interface and endpoint descriptor. +.. _testing_USB_native_sim: + Testing over USBIP in native_sim ******************************** diff --git a/doc/releases/release-notes-4.1.rst b/doc/releases/release-notes-4.1.rst index c8ec631fe2e66..3900a63f570ab 100644 --- a/doc/releases/release-notes-4.1.rst +++ b/doc/releases/release-notes-4.1.rst @@ -615,7 +615,7 @@ New Samples * :zephyr:code-sample:`stream_fifo` * :zephyr:code-sample:`tdk_apex` * :zephyr:code-sample:`uart` -* :zephyr:code-sample:`webusb-next` +* :zephyr:code-sample:`webusb` Other notable changes ********************* diff --git a/samples/bluetooth/hci_uart/boards/nrf52840dongle_nrf52840.conf b/samples/bluetooth/hci_uart/boards/nrf52840dongle_nrf52840.conf index 72c806e1d3d08..a42efdf0fb5d9 100644 --- a/samples/bluetooth/hci_uart/boards/nrf52840dongle_nrf52840.conf +++ b/samples/bluetooth/hci_uart/boards/nrf52840dongle_nrf52840.conf @@ -1,4 +1,3 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr HCI UART sample" -CONFIG_USB_CDC_ACM=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +# The board uses the CDC ACM UART as the serial backend by default, nothing +# else needs to be configured here. +CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="Zephyr HCI UART sample" diff --git a/samples/bluetooth/hci_uart/src/main.c b/samples/bluetooth/hci_uart/src/main.c index 626ff56ec70f1..4d5fcdfdd218e 100644 --- a/samples/bluetooth/hci_uart/src/main.c +++ b/samples/bluetooth/hci_uart/src/main.c @@ -20,8 +20,6 @@ #include #include -#include - #include #include #include @@ -332,13 +330,6 @@ static int hci_uart_init(void) { LOG_DBG(""); - if (IS_ENABLED(CONFIG_USB_CDC_ACM)) { - if (usb_enable(NULL)) { - LOG_ERR("Failed to enable USB"); - return -EINVAL; - } - } - if (!device_is_ready(hci_uart_dev)) { LOG_ERR("HCI UART %s is not ready", hci_uart_dev->name); return -EINVAL; diff --git a/samples/bluetooth/hci_usb/README.rst b/samples/bluetooth/hci_usb/README.rst index c8ac294a72fc2..d3bd3df4b5cd9 100644 --- a/samples/bluetooth/hci_usb/README.rst +++ b/samples/bluetooth/hci_usb/README.rst @@ -1,6 +1,6 @@ .. zephyr:code-sample:: bluetooth_hci_usb :name: HCI USB - :relevant-api: hci_raw bluetooth _usb_device_core_api usbd_api + :relevant-api: hci_raw bluetooth usbd_api Turn a Zephyr board into a USB Bluetooth dongle (compatible with all operating systems). diff --git a/samples/bluetooth/hci_usb/prj.conf b/samples/bluetooth/hci_usb/prj.conf index 0f809e424d6dc..a245b49f4beff 100644 --- a/samples/bluetooth/hci_usb/prj.conf +++ b/samples/bluetooth/hci_usb/prj.conf @@ -1,17 +1,8 @@ CONFIG_BT=y CONFIG_BT_HCI_RAW=y - -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PID=0x000B -CONFIG_USB_DEVICE_BLUETOOTH=y -CONFIG_USB_DEVICE_BLUETOOTH_VS_H4=n -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - -# We dont want any console or CDC ACM that may cause BlueZ to not detect hci_usb -CONFIG_SERIAL=n -CONFIG_CONSOLE=n -CONFIG_UART_CONSOLE=n - -# Workaround: Unable to allocate command buffer when using K_NO_WAIT since -# Host number of completed commands does not follow normal flow control. CONFIG_BT_BUF_CMD_TX_COUNT=10 + +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_SAMPLE_USBD_PID=0x000b +CONFIG_SAMPLE_USBD_PRODUCT="Zephyr USBD BT HCI" +CONFIG_USBD_BT_HCI=y diff --git a/samples/bluetooth/hci_usb/sample.yaml b/samples/bluetooth/hci_usb/sample.yaml index c04cf1b8ae7dc..87ca6a32bf0ed 100644 --- a/samples/bluetooth/hci_usb/sample.yaml +++ b/samples/bluetooth/hci_usb/sample.yaml @@ -4,18 +4,8 @@ tests: sample.bluetooth.hci_usb: harness: bluetooth depends_on: - - usb_device + - usbd - ble tags: - usb - bluetooth - sample.bluetooth.hci_usb.device_next: - harness: bluetooth - depends_on: - - usb_device - - ble - tags: - - usb - - bluetooth - extra_args: CONF_FILE="usbd_next_prj.conf" - platform_allow: nrf52840dk/nrf52840 diff --git a/samples/bluetooth/hci_usb/src/main.c b/samples/bluetooth/hci_usb/src/main.c index 18c7f0d5edc51..ceb5128226761 100644 --- a/samples/bluetooth/hci_usb/src/main.c +++ b/samples/bluetooth/hci_usb/src/main.c @@ -6,35 +6,22 @@ #include #include -#include #include -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) #include -static int enable_usb_device_next(void) +int main(void) { - struct usbd_context *sample_usbd = sample_usbd_init_device(NULL); + struct usbd_context *sample_usbd; + int ret; + sample_usbd = sample_usbd_init_device(NULL); if (sample_usbd == NULL) { printk("Failed to initialize USB device"); return -ENODEV; } - return usbd_enable(sample_usbd); -} -#endif /* CONFIG_USB_DEVICE_STACK_NEXT */ - -int main(void) -{ - int ret; - -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - ret = enable_usb_device_next(); -#else - ret = usb_enable(NULL); -#endif - + ret = usbd_enable(sample_usbd); if (ret != 0) { printk("Failed to enable USB"); return 0; diff --git a/samples/bluetooth/hci_usb/usbd_next_prj.conf b/samples/bluetooth/hci_usb/usbd_next_prj.conf deleted file mode 100644 index e1daa84f47d67..0000000000000 --- a/samples/bluetooth/hci_usb/usbd_next_prj.conf +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG_STDOUT_CONSOLE=y -CONFIG_GPIO=y -CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - -CONFIG_BT=y -CONFIG_BT_HCI_RAW=y - -CONFIG_USB_DEVICE_STACK_NEXT=y -CONFIG_SAMPLE_USBD_PID=0x000b -CONFIG_SAMPLE_USBD_PRODUCT="Zephyr USBD BT HCI" -CONFIG_USBD_BT_HCI=y - -CONFIG_LOG=y -CONFIG_USBD_LOG_LEVEL_WRN=y -CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y diff --git a/samples/boards/st/sensortile_box/prj.conf b/samples/boards/st/sensortile_box/prj.conf index 0f6ffa4f97ec9..fa0a42ec657bd 100644 --- a/samples/boards/st/sensortile_box/prj.conf +++ b/samples/boards/st/sensortile_box/prj.conf @@ -17,12 +17,10 @@ CONFIG_IIS3DHHC_TRIGGER_OWN_THREAD=y CONFIG_LIS2MDL_TRIGGER_NONE=y # config USB and USB console -CONFIG_USB_DEVICE_VID=0x0483 -CONFIG_USB_DEVICE_PID=0x1234 -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC SensorTile.box" -CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y +CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="Zephyr CDC SensorTile.box" +CONFIG_USBD_CDC_ACM_LOG_LEVEL_OFF=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_UART_LINE_CTRL=y diff --git a/samples/boards/st/sensortile_box/src/main.c b/samples/boards/st/sensortile_box/src/main.c index 92c7aac5cd9f5..4248ef0e820f0 100644 --- a/samples/boards/st/sensortile_box/src/main.c +++ b/samples/boards/st/sensortile_box/src/main.c @@ -256,8 +256,7 @@ int main(void) int cnt = 1; uint32_t dtr = 0; - /* Application must enable USB by itself */ - if (!device_is_ready(dev) || usb_enable(NULL)) { + if (!device_is_ready(dev)) { return 0; } diff --git a/samples/net/sockets/dumb_http_server/overlay-netusb.conf b/samples/net/sockets/dumb_http_server/overlay-netusb.conf deleted file mode 100644 index b39bdaac0f63e..0000000000000 --- a/samples/net/sockets/dumb_http_server/overlay-netusb.conf +++ /dev/null @@ -1,9 +0,0 @@ -# USB Device settings -CONFIG_USB_DEVICE_STACK=y - -# Select USB Configurations -CONFIG_USB_DEVICE_NETWORK_ECM=y - -# Logging -CONFIG_USB_DRIVER_LOG_LEVEL_INF=y -CONFIG_USB_DEVICE_LOG_LEVEL_INF=y diff --git a/samples/net/sockets/dumb_http_server/sample.yaml b/samples/net/sockets/dumb_http_server/sample.yaml index 7e076a94eb1ad..301f70820d413 100644 --- a/samples/net/sockets/dumb_http_server/sample.yaml +++ b/samples/net/sockets/dumb_http_server/sample.yaml @@ -14,25 +14,3 @@ tests: sample.net.sockets.dumb_http_server: extra_configs: - CONFIG_POSIX_API=y - sample.net.sockets.dumb_http_server.netusb: - depends_on: usb_device - harness: net - extra_args: EXTRA_CONF_FILE="overlay-netusb.conf" - tags: usb - # native_sim usb driver does not work with CONFIG_POSIX_API - platform_exclude: - - native_sim - - native_sim/native/64 - - native_posix - - native_posix/native/64 - sample.net.sockets.dumb_http_server.netusb_zeroconf: - depends_on: usb_device - harness: net - extra_args: EXTRA_CONF_FILE="overlay-netusb.conf;overlay-zeroconf.conf" - tags: usb - # native_sim usb driver does not work with CONFIG_POSIX_API - platform_exclude: - - native_sim - - native_sim/native/64 - - native_posix - - native_posix/native/64 diff --git a/samples/net/sockets/echo_server/CMakeLists.txt b/samples/net/sockets/echo_server/CMakeLists.txt index 52251bca3949f..06e05727e9bb7 100644 --- a/samples/net/sockets/echo_server/CMakeLists.txt +++ b/samples/net/sockets/echo_server/CMakeLists.txt @@ -24,10 +24,6 @@ target_sources_ifdef(CONFIG_NET_TCP app PRIVATE src/tcp.c) target_sources_ifdef(CONFIG_NET_VLAN app PRIVATE src/vlan.c) target_sources_ifdef(CONFIG_NET_L2_IPIP app PRIVATE src/tunnel.c) -if (CONFIG_USB_DEVICE_STACK) - target_sources(app PRIVATE src/usb.c) -endif() - if (CONFIG_USB_DEVICE_STACK_NEXT) target_sources(app PRIVATE src/usb.c) include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) diff --git a/samples/net/sockets/echo_server/overlay-netusb.conf b/samples/net/sockets/echo_server/overlay-netusb.conf deleted file mode 100644 index ca03d24a61833..0000000000000 --- a/samples/net/sockets/echo_server/overlay-netusb.conf +++ /dev/null @@ -1,10 +0,0 @@ -# USB Device settings -CONFIG_USB_DEVICE_STACK=y - -# Select USB Configurations -CONFIG_USB_DEVICE_NETWORK_ECM=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - -# Logging -CONFIG_USB_DRIVER_LOG_LEVEL_INF=y -CONFIG_USB_DEVICE_LOG_LEVEL_INF=y diff --git a/samples/net/sockets/echo_server/overlay-usbd_next.conf b/samples/net/sockets/echo_server/overlay-usbd.conf similarity index 85% rename from samples/net/sockets/echo_server/overlay-usbd_next.conf rename to samples/net/sockets/echo_server/overlay-usbd.conf index 9db1e48835b7c..8f04cb281865a 100644 --- a/samples/net/sockets/echo_server/overlay-usbd_next.conf +++ b/samples/net/sockets/echo_server/overlay-usbd.conf @@ -4,4 +4,6 @@ CONFIG_LOG=y CONFIG_USBD_LOG_LEVEL_WRN=y CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_NET_L2_ETHERNET=y + CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 diff --git a/samples/net/sockets/echo_server/sample.yaml b/samples/net/sockets/echo_server/sample.yaml index deaa6247aa495..498607f20a4ce 100644 --- a/samples/net/sockets/echo_server/sample.yaml +++ b/samples/net/sockets/echo_server/sample.yaml @@ -75,19 +75,14 @@ tests: sample.net.sockets.echo_server.b91_802154: extra_args: EXTRA_CONF_FILE="overlay-802154.conf" platform_allow: tlsr9518adk80d - sample.net.sockets.echo_server.usbnet: - depends_on: usb_device + sample.net.sockets.echo_server.usbd_cdc_ncm: + depends_on: usbd harness: net - extra_args: EXTRA_CONF_FILE="overlay-netusb.conf" + extra_args: EXTRA_CONF_FILE="overlay-usbd.conf" + EXTRA_DTC_OVERLAY_FILE="usbd_cdc_ncm.overlay" tags: - net - usb - # native_sim usb driver does not work with CONFIG_POSIX_API - platform_exclude: - - native_sim - - native_sim/native/64 - - native_posix - - native_posix/native/64 sample.net.sockets.echo_server.nrf_openthread: extra_args: EXTRA_CONF_FILE="overlay-ot.conf" slow: true diff --git a/samples/net/sockets/echo_server/src/common.h b/samples/net/sockets/echo_server/src/common.h index d5641fdf5f745..e85ecba9a3fb4 100644 --- a/samples/net/sockets/echo_server/src/common.h +++ b/samples/net/sockets/echo_server/src/common.h @@ -107,7 +107,7 @@ static inline bool is_tunnel(struct net_if *iface) } #endif /* CONFIG_NET_L2_IPIP */ -#if defined(CONFIG_USB_DEVICE_STACK) || defined(CONFIG_USB_DEVICE_STACK_NEXT) +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) int init_usb(void); #else static inline int init_usb(void) diff --git a/samples/net/sockets/echo_server/src/usb.c b/samples/net/sockets/echo_server/src/usb.c index a528f065658ba..95b33443457de 100644 --- a/samples/net/sockets/echo_server/src/usb.c +++ b/samples/net/sockets/echo_server/src/usb.c @@ -7,15 +7,12 @@ #include LOG_MODULE_DECLARE(net_echo_server_sample, LOG_LEVEL_DBG); -#include -#include - -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) #include +#include static struct usbd_context *sample_usbd; -static int enable_usb_device_next(void) +int init_usb(void) { int err; @@ -29,28 +26,6 @@ static int enable_usb_device_next(void) return err; } - return 0; -} -#endif /* CONFIG_USB_DEVICE_STACK_NEXT */ - -int init_usb(void) -{ -#if defined(CONFIG_USB_DEVICE_STACK) - int ret; - - ret = usb_enable(NULL); - if (ret != 0) { - LOG_ERR("Cannot enable USB (%d)", ret); - return ret; - } -#endif /* CONFIG_USB_DEVICE_STACK */ - -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - if (enable_usb_device_next()) { - return 0; - } -#endif /* CONFIG_USB_DEVICE_STACK_NEXT */ - (void)net_config_init_app(NULL, "Initializing network"); return 0; diff --git a/samples/net/sockets/echo_server/usbd_next_ncm.overlay b/samples/net/sockets/echo_server/usbd_cdc_ncm.overlay similarity index 100% rename from samples/net/sockets/echo_server/usbd_next_ncm.overlay rename to samples/net/sockets/echo_server/usbd_cdc_ncm.overlay diff --git a/samples/net/sockets/http_server/CMakeLists.txt b/samples/net/sockets/http_server/CMakeLists.txt index b860f8a07ce6b..659c45525f51d 100644 --- a/samples/net/sockets/http_server/CMakeLists.txt +++ b/samples/net/sockets/http_server/CMakeLists.txt @@ -41,7 +41,10 @@ target_sources(app PRIVATE src/main.c) set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/) target_sources_ifdef(CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE app PRIVATE src/ws.c) -target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c) + +if (CONFIG_USB_DEVICE_STACK_NEXT) + include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) +endif() target_link_libraries(app PRIVATE zephyr_interface zephyr) diff --git a/samples/net/sockets/http_server/Kconfig b/samples/net/sockets/http_server/Kconfig index 861178a09d291..edfc9522f76c2 100644 --- a/samples/net/sockets/http_server/Kconfig +++ b/samples/net/sockets/http_server/Kconfig @@ -68,4 +68,11 @@ config NET_SAMPLE_WEBSOCKET_STATS_INTERVAL This interval controls how often the net stats data shown on the web page will be updated. +if USB_DEVICE_STACK_NEXT +# Source common USB sample options used to initialize new experimental USB +# device stack. The scope of these options is limited to USB samples in project +# tree, you cannot use them in your own application. + source "samples/subsys/usb/common/Kconfig.sample_usbd" +endif + source "Kconfig.zephyr" diff --git a/samples/net/sockets/http_server/README.rst b/samples/net/sockets/http_server/README.rst index 9d33cb2e26afe..b7351ef290ac8 100644 --- a/samples/net/sockets/http_server/README.rst +++ b/samples/net/sockets/http_server/README.rst @@ -31,7 +31,7 @@ There are configuration files for various setups in the * - :zephyr_file:`ieee802154-overlay.conf ` - This overlay config can be added for IEEE 802.15.4 support. - * - :zephyr_file:`overlay-netusb.conf ` + * - :zephyr_file:`overlay-usbd.conf ` - This overlay config can be added for connecting via network USB. To build and run the application: diff --git a/samples/net/sockets/http_server/overlay-netusb.conf b/samples/net/sockets/http_server/overlay-netusb.conf deleted file mode 100644 index ca03d24a61833..0000000000000 --- a/samples/net/sockets/http_server/overlay-netusb.conf +++ /dev/null @@ -1,10 +0,0 @@ -# USB Device settings -CONFIG_USB_DEVICE_STACK=y - -# Select USB Configurations -CONFIG_USB_DEVICE_NETWORK_ECM=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - -# Logging -CONFIG_USB_DRIVER_LOG_LEVEL_INF=y -CONFIG_USB_DEVICE_LOG_LEVEL_INF=y diff --git a/samples/subsys/usb/webusb-next/prj.conf b/samples/net/sockets/http_server/overlay-usbd.conf similarity index 60% rename from samples/subsys/usb/webusb-next/prj.conf rename to samples/net/sockets/http_server/overlay-usbd.conf index 1c730a0ec56a3..20abbfb4fc2cf 100644 --- a/samples/subsys/usb/webusb-next/prj.conf +++ b/samples/net/sockets/http_server/overlay-usbd.conf @@ -3,5 +3,5 @@ CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_LOG=y CONFIG_USBD_LOG_LEVEL_WRN=y CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y -CONFIG_SAMPLE_USBD_PID=0x000A -CONFIG_SAMPLE_USBD_20_EXTENSION_DESC=y + +CONFIG_NET_L2_ETHERNET=y diff --git a/samples/net/sockets/http_server/sample.yaml b/samples/net/sockets/http_server/sample.yaml index 38206644533fd..1b93cc4c76aaf 100644 --- a/samples/net/sockets/http_server/sample.yaml +++ b/samples/net/sockets/http_server/sample.yaml @@ -16,3 +16,9 @@ common: - nrf5340dk/nrf5340/cpuapp/ns # Excluding due to ROM overflow. tests: sample.net.sockets.http.server: {} + sample.net.sockets.http.server.usbd_cdc_ncm: + depends_on: usbd + extra_args: EXTRA_CONF_FILE="overlay-usbd.conf" + EXTRA_DTC_OVERLAY_FILE="usbd_cdc_ncm.overlay" + tags: + - usb diff --git a/samples/net/sockets/http_server/src/main.c b/samples/net/sockets/http_server/src/main.c index 1341a91169be3..a95d7ba9c2ec3 100644 --- a/samples/net/sockets/http_server/src/main.c +++ b/samples/net/sockets/http_server/src/main.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "ws.h" @@ -347,14 +349,27 @@ static void setup_tls(void) #endif /* defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) */ } -#if defined(CONFIG_USB_DEVICE_STACK) -int init_usb(void); -#else -static inline int init_usb(void) +static int init_usb(void) { +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + struct usbd_context *sample_usbd; + int err; + + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + return -ENODEV; + } + + err = usbd_enable(sample_usbd); + if (err) { + return err; + } + + (void)net_config_init_app(NULL, "Initializing network"); +#endif /* CONFIG_USB_DEVICE_STACK_NEXT */ + return 0; } -#endif /* CONFIG_USB_DEVICE_STACK */ int main(void) { diff --git a/samples/net/zperf/usbd_next_ncm.overlay b/samples/net/sockets/http_server/usbd_cdc_ncm.overlay similarity index 100% rename from samples/net/zperf/usbd_next_ncm.overlay rename to samples/net/sockets/http_server/usbd_cdc_ncm.overlay diff --git a/samples/net/wpan_serial/prj.conf b/samples/net/wpan_serial/prj.conf index 7ad05d3e458eb..14c182119ae03 100644 --- a/samples/net/wpan_serial/prj.conf +++ b/samples/net/wpan_serial/prj.conf @@ -1,9 +1,11 @@ CONFIG_GPIO=y -CONFIG_USB_DEVICE_STACK=y CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_UART_LINE_CTRL=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y +CONFIG_USBD_CDC_ACM_LOG_LEVEL_OFF=y +CONFIG_LOG_DEFAULT_LEVEL=1 CONFIG_NETWORKING=y diff --git a/samples/net/wpan_serial/sample.yaml b/samples/net/wpan_serial/sample.yaml index 78c8c9c517bc8..846092d258fff 100644 --- a/samples/net/wpan_serial/sample.yaml +++ b/samples/net/wpan_serial/sample.yaml @@ -2,7 +2,7 @@ sample: description: Test wpan_serial sample name: wpan_serial common: - depends_on: usb_device + depends_on: usbd harness: net tags: - usb diff --git a/samples/net/wpan_serial/src/main.c b/samples/net/wpan_serial/src/main.c index 804e2cb6a4883..423bc492a65fb 100644 --- a/samples/net/wpan_serial/src/main.c +++ b/samples/net/wpan_serial/src/main.c @@ -13,11 +13,10 @@ */ #include -LOG_MODULE_REGISTER(wpan_serial, CONFIG_USB_DEVICE_LOG_LEVEL); +LOG_MODULE_REGISTER(wpan_serial, LOG_LEVEL_DBG); #include #include -#include #include #include @@ -544,12 +543,6 @@ int main(void) return 0; } - ret = usb_enable(NULL); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; - } - LOG_DBG("Wait for DTR"); while (1) { diff --git a/samples/net/zperf/overlay-netusb.conf b/samples/net/zperf/overlay-netusb.conf deleted file mode 100644 index a85e73ea93af4..0000000000000 --- a/samples/net/zperf/overlay-netusb.conf +++ /dev/null @@ -1,6 +0,0 @@ -# USB Device Settings -CONFIG_USB_DEVICE_STACK=y - -# Select USB Configurations -CONFIG_USB_DEVICE_NETWORK_ECM=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n diff --git a/samples/net/zperf/overlay-usbd_next.conf b/samples/net/zperf/overlay-usbd.conf similarity index 100% rename from samples/net/zperf/overlay-usbd_next.conf rename to samples/net/zperf/overlay-usbd.conf diff --git a/samples/net/zperf/sample.yaml b/samples/net/zperf/sample.yaml index 7dbb0cb8acff3..27d5b5b0efe86 100644 --- a/samples/net/zperf/sample.yaml +++ b/samples/net/zperf/sample.yaml @@ -34,74 +34,26 @@ tests: extra_configs: - CONFIG_NET_SHELL=n platform_allow: qemu_x86 - sample.net.zperf.netusb_ecm: - harness: net - extra_args: EXTRA_CONF_FILE="overlay-netusb.conf" - tags: - - usb - - net - - zperf - depends_on: usb_device - # native_sim usb driver does not work with CONFIG_POSIX_API - platform_exclude: - - native_sim - - native_sim/native/64 - sample.net.zperf.device_next_ecm: + sample.net.zperf.usbd_cdc_ecm: harness: net extra_args: - - EXTRA_CONF_FILE="overlay-usbd_next.conf" - - DTC_OVERLAY_FILE="usbd_next_ecm.overlay" + - EXTRA_CONF_FILE="overlay-usbd.conf" + - DTC_OVERLAY_FILE="usbd_cdc_ecm.overlay" platform_allow: - nrf52840dk/nrf52840 - frdm_k64f - tags: - - usb - - net - - zperf - depends_on: usb_device - sample.net.zperf.device_next_ncm: + tags: usb net zperf + depends_on: usbd + sample.net.zperf.usbd_cdc_ncm: harness: net extra_args: - - EXTRA_CONF_FILE="overlay-usbd_next.conf" - - DTC_OVERLAY_FILE="usbd_next_ncm.overlay" + - EXTRA_CONF_FILE="overlay-usbd.conf" + - DTC_OVERLAY_FILE="usbd_cdc_ncm.overlay" platform_allow: - nrf52840dk/nrf52840 - frdm_k64f - tags: - - usb - - net - - zperf - depends_on: usb_device - sample.net.zperf.netusb_eem: - harness: net - extra_args: EXTRA_CONF_FILE="overlay-netusb.conf" - extra_configs: - - CONFIG_USB_DEVICE_NETWORK_ECM=n - - CONFIG_USB_DEVICE_NETWORK_EEM=y - tags: - - usb - - net - - zperf - depends_on: usb_device - # native_sim usb driver does not work with CONFIG_POSIX_API - platform_exclude: - - native_sim - - native_sim/native/64 - sample.net.zperf.netusb_rndis: - harness: net - extra_args: EXTRA_CONF_FILE="overlay-netusb.conf" - extra_configs: - - CONFIG_USB_DEVICE_NETWORK_ECM=n - - CONFIG_USB_DEVICE_NETWORK_RNDIS=y - tags: - - usb - - net - - zperf - depends_on: usb_device - # native_sim usb driver does not work with CONFIG_POSIX_API - platform_exclude: - - native_sim - - native_sim/native/64 + tags: usb net zperf + depends_on: usbd sample.net.zperf.shield: harness: net platform_allow: reel_board diff --git a/samples/net/zperf/src/main.c b/samples/net/zperf/src/main.c index 648adacf2235d..1c96796c3e9ea 100644 --- a/samples/net/zperf/src/main.c +++ b/samples/net/zperf/src/main.c @@ -8,7 +8,6 @@ * @file * @brief Zperf sample. */ -#include #include #include @@ -20,11 +19,12 @@ LOG_MODULE_REGISTER(zperf, CONFIG_NET_ZPERF_LOG_LEVEL); #if defined(CONFIG_USB_DEVICE_STACK_NEXT) #include +#endif -static struct usbd_context *sample_usbd; - -static int enable_usb_device_next(void) +int main(void) { +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + struct usbd_context *sample_usbd; int err; sample_usbd = sample_usbd_init_device(NULL); @@ -37,28 +37,6 @@ static int enable_usb_device_next(void) return err; } - return 0; -} -#endif /* CONFIG_USB_DEVICE_STACK_NEXT */ - -int main(void) -{ -#if defined(CONFIG_USB_DEVICE_STACK) - int ret; - - ret = usb_enable(NULL); - if (ret != 0) { - printk("usb enable error %d\n", ret); - } - - (void)net_config_init_app(NULL, "Initializing network"); -#endif /* CONFIG_USB_DEVICE_STACK */ - -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - if (enable_usb_device_next()) { - return 0; - } - (void)net_config_init_app(NULL, "Initializing network"); #endif /* CONFIG_USB_DEVICE_STACK_NEXT */ diff --git a/samples/net/zperf/usbd_next_ecm.overlay b/samples/net/zperf/usbd_cdc_ecm.overlay similarity index 100% rename from samples/net/zperf/usbd_next_ecm.overlay rename to samples/net/zperf/usbd_cdc_ecm.overlay diff --git a/samples/net/zperf/usbd_cdc_ncm.overlay b/samples/net/zperf/usbd_cdc_ncm.overlay new file mode 100644 index 0000000000000..51c6decea7c84 --- /dev/null +++ b/samples/net/zperf/usbd_cdc_ncm.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + cdc_ncm_eth0: cdc_ncm_eth0 { + compatible = "zephyr,cdc-ncm-ethernet"; + remote-mac-address = "00005E005301"; + }; +}; diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf index 1d98bc9899d51..436ff459dcc45 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/overlay-cdc.conf @@ -1,9 +1,9 @@ # Enable USB subsystem -CONFIG_USB_DEVICE_STACK=y CONFIG_SERIAL=y CONFIG_UART_LINE_CTRL=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n CONFIG_CONSOLE=y +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y # USB backend is serial device CONFIG_MCUMGR_TRANSPORT_UART=y CONFIG_BASE64=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c b/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c index 8b0c0b44a885f..a66afb702cd49 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c +++ b/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c @@ -71,15 +71,6 @@ int main(void) start_smp_bluetooth_adverts(); #endif - if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) { - rc = usb_enable(NULL); - - /* Ignore EALREADY error as USB CDC is likely already initialised */ - if (rc != 0 && rc != -EALREADY) { - LOG_ERR("Failed to enable USB"); - return 0; - } - } /* using __TIME__ ensure that a new binary will be built on every * compile which is convenient when testing firmware upgrade. */ diff --git a/samples/subsys/modbus/rtu_server/overlay-cdc-acm.conf b/samples/subsys/modbus/rtu_server/overlay-cdc-acm.conf index bc052b8511835..901af535c48a2 100644 --- a/samples/subsys/modbus/rtu_server/overlay-cdc-acm.conf +++ b/samples/subsys/modbus/rtu_server/overlay-cdc-acm.conf @@ -1,4 +1,4 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC ACM MODBUS sample" +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y +CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="Zephyr CDC ACM MODBUS sample" CONFIG_UART_LINE_CTRL=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n diff --git a/samples/subsys/modbus/rtu_server/sample.yaml b/samples/subsys/modbus/rtu_server/sample.yaml index f69d51f4eeb82..5898aab40193a 100644 --- a/samples/subsys/modbus/rtu_server/sample.yaml +++ b/samples/subsys/modbus/rtu_server/sample.yaml @@ -33,4 +33,4 @@ tests: extra_args: - EXTRA_CONF_FILE="overlay-cdc-acm.conf" - DTC_OVERLAY_FILE="cdc-acm.overlay" - depends_on: usb_device + depends_on: usbd diff --git a/samples/subsys/modbus/rtu_server/src/main.c b/samples/subsys/modbus/rtu_server/src/main.c index ec1ab41c05f23..8c49da5be85da 100644 --- a/samples/subsys/modbus/rtu_server/src/main.c +++ b/samples/subsys/modbus/rtu_server/src/main.c @@ -9,7 +9,6 @@ #include #include #include -#include #include LOG_MODULE_REGISTER(mbs_sample, LOG_LEVEL_INF); @@ -147,7 +146,7 @@ int main(void) const struct device *const dev = DEVICE_DT_GET(DT_PARENT(MODBUS_NODE)); uint32_t dtr = 0; - if (!device_is_ready(dev) || usb_enable(NULL)) { + if (!device_is_ready(dev)) { return 0; } diff --git a/samples/subsys/shell/shell_module/overlay-usb.conf b/samples/subsys/shell/shell_module/overlay-usb.conf index f5e0e86d60bb2..0044fb03a58f6 100644 --- a/samples/subsys/shell/shell_module/overlay-usb.conf +++ b/samples/subsys/shell/shell_module/overlay-usb.conf @@ -1,9 +1,10 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr USB shell sample" +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y +CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="Zephyr USB shell sample" CONFIG_SHELL_BACKEND_SERIAL_CHECK_DTR=y -CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y +CONFIG_USBD_CDC_ACM_LOG_LEVEL_OFF=y CONFIG_UART_LINE_CTRL=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_LOG_DEFAULT_LEVEL=1 # POSIX_TIMERS requires an embedded C library while the native USB driver is incompatible with it. # So let's disable it. Once USB_NATIVE_POSIX supports embedded C libraries this can be removed. diff --git a/samples/subsys/shell/shell_module/sample.yaml b/samples/subsys/shell/shell_module/sample.yaml index 46c7fbb127f6a..4cfbcd51d3688 100644 --- a/samples/subsys/shell/shell_module/sample.yaml +++ b/samples/subsys/shell/shell_module/sample.yaml @@ -15,7 +15,7 @@ tests: - native_sim - intel_socfpga_agilex5_socdk sample.shell.shell_module.usb: - depends_on: usb_device + depends_on: usbd tags: - shell - usb @@ -25,7 +25,7 @@ tests: - EXTRA_CONF_FILE="overlay-usb.conf" - DTC_OVERLAY_FILE="usb.overlay" integration_platforms: - - native_sim + - frdm_k64f sample.shell.shell_module.minimal: filter: CONFIG_SERIAL and dt_chosen_enabled("zephyr,shell-uart") tags: shell diff --git a/samples/subsys/shell/shell_module/src/main.c b/samples/subsys/shell/shell_module/src/main.c index 3dff64d885ede..7c633eb7c7f7d 100644 --- a/samples/subsys/shell/shell_module/src/main.c +++ b/samples/subsys/shell/shell_module/src/main.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #ifdef CONFIG_ARCH_POSIX @@ -378,7 +377,7 @@ int main(void) uint32_t dtr = 0; dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart)); - if (!device_is_ready(dev) || usb_enable(NULL)) { + if (!device_is_ready(dev)) { return 0; } diff --git a/samples/subsys/usb/audio/headphones_microphone/sample.yaml b/samples/subsys/usb/audio/headphones_microphone/sample.yaml deleted file mode 100644 index 16420c75f440d..0000000000000 --- a/samples/subsys/usb/audio/headphones_microphone/sample.yaml +++ /dev/null @@ -1,19 +0,0 @@ -sample: - name: USB audio Headphones Microphone sample -tests: - sample.usb.audio.headphones_microphone: - depends_on: usb_device - tags: usb - arch_exclude: posix - integration_platforms: - - nrf52840dk/nrf52840 - - nrf5340dk/nrf5340/cpuapp - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "Entered main" - - "Found USB Headphones Device" - - "Found USB Microphone Device" - - "USB enabled" diff --git a/samples/subsys/usb/audio/headset/sample.yaml b/samples/subsys/usb/audio/headset/sample.yaml deleted file mode 100644 index 6c61a4ce7ef52..0000000000000 --- a/samples/subsys/usb/audio/headset/sample.yaml +++ /dev/null @@ -1,18 +0,0 @@ -sample: - name: USB audio headset sample -tests: - sample.usb.audio.headset: - depends_on: usb_device - tags: usb - arch_exclude: posix - integration_platforms: - - nrf52840dk/nrf52840 - - nrf5340dk/nrf5340/cpuapp - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "Entered main" - - "Found USB Headset Device" - - "USB enabled" diff --git a/samples/subsys/usb/cdc_acm/README.rst b/samples/subsys/usb/cdc_acm/README.rst index e30edfcec7bdc..840a618f36255 100644 --- a/samples/subsys/usb/cdc_acm/README.rst +++ b/samples/subsys/usb/cdc_acm/README.rst @@ -1,8 +1,8 @@ .. zephyr:code-sample:: usb-cdc-acm - :name: USB CDC-ACM - :relevant-api: usbd_api _usb_device_core_api uart_interface + :name: USB CDC ACM UART sample + :relevant-api: usbd_api uart_interface - Use USB CDC-ACM driver to implement a serial port echo. + Use USB CDC ACM UART driver to implement a serial port echo. Overview ******** diff --git a/samples/subsys/usb/cdc_acm/prj.conf b/samples/subsys/usb/cdc_acm/prj.conf index 55e4fe9217fb5..e0012027ec6aa 100644 --- a/samples/subsys/usb/cdc_acm/prj.conf +++ b/samples/subsys/usb/cdc_acm/prj.conf @@ -1,11 +1,14 @@ +CONFIG_USB_DEVICE_STACK_NEXT=y + CONFIG_STDOUT_CONSOLE=y -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC ACM sample" -CONFIG_USB_DEVICE_PID=0x0001 -CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_UART_LINE_CTRL=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USBD_CDC_ACM_CLASS=y + +CONFIG_LOG=y +CONFIG_USBD_LOG_LEVEL_ERR=y +CONFIG_UDC_DRIVER_LOG_LEVEL_ERR=y +CONFIG_USBD_CDC_ACM_LOG_LEVEL_ERR=y + +CONFIG_SAMPLE_USBD_PID=0x0001 +CONFIG_SAMPLE_USBD_PRODUCT="USBD CDC ACM sample" diff --git a/samples/subsys/usb/cdc_acm/sample.yaml b/samples/subsys/usb/cdc_acm/sample.yaml index d1906f58502c3..0852c0d21e60d 100644 --- a/samples/subsys/usb/cdc_acm/sample.yaml +++ b/samples/subsys/usb/cdc_acm/sample.yaml @@ -1,19 +1,9 @@ sample: name: CDC ACM USB tests: - sample.usb.cdc-acm: - depends_on: usb_device - tags: usb - arch_exclude: posix - harness: console - harness_config: - type: one_line - regex: - - "Wait for DTR" sample.usb_device_next.cdc-acm: depends_on: usbd tags: usb - extra_args: CONF_FILE="usbd_next_prj.conf" integration_platforms: - nrf52840dk/nrf52840 - nrf54h20dk/nrf54h20/cpuapp @@ -27,10 +17,3 @@ tests: type: one_line regex: - "Wait for DTR" - sample.usb.cdc-acm.buildonly: - depends_on: usb_device - tags: usb - arch_allow: posix - build_only: true - integration_platforms: - - native_sim diff --git a/samples/subsys/usb/cdc_acm/src/main.c b/samples/subsys/usb/cdc_acm/src/main.c index ab1cbdc6a4c0e..c80d253966b7f 100644 --- a/samples/subsys/usb/cdc_acm/src/main.c +++ b/samples/subsys/usb/cdc_acm/src/main.c @@ -4,14 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** - * @file - * @brief Sample echo app for CDC ACM class - * - * Sample app for USB CDC ACM class driver. The received data is echoed back - * to the serial port. - */ - #include #include @@ -21,7 +13,6 @@ #include #include -#include #include #include LOG_MODULE_REGISTER(cdc_acm_echo, LOG_LEVEL_INF); @@ -48,7 +39,6 @@ static inline void print_baudrate(const struct device *dev) } } -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) static struct usbd_context *sample_usbd; K_SEM_DEFINE(dtr_sem, 0, 1); @@ -106,7 +96,6 @@ static int enable_usb_device_next(void) return 0; } -#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */ static void interrupt_handler(const struct device *dev, void *user_data) { @@ -178,37 +167,16 @@ int main(void) return 0; } -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - ret = enable_usb_device_next(); -#else - ret = usb_enable(NULL); -#endif - + ret = enable_usb_device_next(); if (ret != 0) { - LOG_ERR("Failed to enable USB"); + LOG_ERR("Failed to enable USB device support"); return 0; } ring_buf_init(&ringbuf, sizeof(ring_buffer), ring_buffer); LOG_INF("Wait for DTR"); - -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) k_sem_take(&dtr_sem, K_FOREVER); -#else - while (true) { - uint32_t dtr = 0U; - - uart_line_ctrl_get(uart_dev, UART_LINE_CTRL_DTR, &dtr); - if (dtr) { - break; - } else { - /* Give CPU resources to low priority threads. */ - k_sleep(K_MSEC(100)); - } - } -#endif - LOG_INF("DTR set"); /* They are optional, we use them to test the interrupt endpoint */ @@ -225,11 +193,7 @@ int main(void) /* Wait 100ms for the host to do all settings */ k_msleep(100); -#ifndef CONFIG_USB_DEVICE_STACK_NEXT - print_baudrate(uart_dev); -#endif uart_irq_callback_set(uart_dev, interrupt_handler); - /* Enable rx interrupts */ uart_irq_rx_enable(uart_dev); diff --git a/samples/subsys/usb/cdc_acm/usbd_next_prj.conf b/samples/subsys/usb/cdc_acm/usbd_next_prj.conf deleted file mode 100644 index f08928438b777..0000000000000 --- a/samples/subsys/usb/cdc_acm/usbd_next_prj.conf +++ /dev/null @@ -1,14 +0,0 @@ -CONFIG_USB_DEVICE_STACK_NEXT=y - -CONFIG_STDOUT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_UART_LINE_CTRL=y -CONFIG_USBD_CDC_ACM_CLASS=y - -CONFIG_LOG=y -CONFIG_USBD_LOG_LEVEL_WRN=y -CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y -CONFIG_USBD_CDC_ACM_LOG_LEVEL_ERR=y - -CONFIG_SAMPLE_USBD_PID=0x0001 -CONFIG_SAMPLE_USBD_PRODUCT="USBD CDC ACM sample" diff --git a/samples/subsys/usb/console/CMakeLists.txt b/samples/subsys/usb/console/CMakeLists.txt index 8ef0ebe2e708f..cf1601304ab6b 100644 --- a/samples/subsys/usb/console/CMakeLists.txt +++ b/samples/subsys/usb/console/CMakeLists.txt @@ -4,6 +4,5 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(console) -include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/console/prj.conf b/samples/subsys/usb/console/prj.conf index 61baa5ba45db6..67da9bee34352 100644 --- a/samples/subsys/usb/console/prj.conf +++ b/samples/subsys/usb/console/prj.conf @@ -1,9 +1,12 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr USB console sample" -CONFIG_USB_DEVICE_PID=0x0004 -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y +CONFIG_STDOUT_CONSOLE=y CONFIG_UART_LINE_CTRL=y + +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_CDC_ACM_CLASS=y + +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y +CONFIG_CDC_ACM_SERIAL_PID=0x0004 +CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="USBD console sample" diff --git a/samples/subsys/usb/console/sample.yaml b/samples/subsys/usb/console/sample.yaml index 4b590862b31fa..ae16dc544c84f 100644 --- a/samples/subsys/usb/console/sample.yaml +++ b/samples/subsys/usb/console/sample.yaml @@ -1,9 +1,9 @@ sample: - name: Console over USB + name: Console over CDC ACM serial tests: sample.usb.console: depends_on: - - usb_device + - usbd tags: usb harness: console harness_config: diff --git a/samples/subsys/usb/console/src/main.c b/samples/subsys/usb/console/src/main.c index bf2230687e1c9..674c233e5e159 100644 --- a/samples/subsys/usb/console/src/main.c +++ b/samples/subsys/usb/console/src/main.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - #include #include #include @@ -15,42 +13,11 @@ BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart), "Console device is not ACM CDC UART device"); -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static struct usbd_context *sample_usbd; - -static int enable_usb_device_next(void) -{ - int err; - - sample_usbd = sample_usbd_init_device(NULL); - if (sample_usbd == NULL) { - return -ENODEV; - } - - err = usbd_enable(sample_usbd); - if (err) { - return err; - } - - return 0; -} -#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */ - int main(void) { const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); uint32_t dtr = 0; -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - if (enable_usb_device_next()) { - return 0; - } -#else - if (usb_enable(NULL)) { - return 0; - } -#endif - /* Poll if the DTR flag was set */ while (!dtr) { uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); diff --git a/samples/subsys/usb/console/usbd_next_prj.conf b/samples/subsys/usb/console/usbd_next_prj.conf deleted file mode 100644 index 841bffbf012b5..0000000000000 --- a/samples/subsys/usb/console/usbd_next_prj.conf +++ /dev/null @@ -1,13 +0,0 @@ -CONFIG_USB_DEVICE_STACK_NEXT=y - -CONFIG_STDOUT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_UART_LINE_CTRL=y -CONFIG_USBD_CDC_ACM_CLASS=y - -CONFIG_LOG=y -CONFIG_USBD_LOG_LEVEL_WRN=y -CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y - -CONFIG_SAMPLE_USBD_PID=0x0004 -CONFIG_SAMPLE_USBD_PRODUCT="USBD console sample" diff --git a/samples/subsys/usb/dfu-next/README.rst b/samples/subsys/usb/dfu-next/README.rst deleted file mode 100644 index 7d78fedc07900..0000000000000 --- a/samples/subsys/usb/dfu-next/README.rst +++ /dev/null @@ -1,137 +0,0 @@ -.. zephyr:code-sample:: dfu-next - :name: USB DFU - :relevant-api: usbd_api usbd_dfu - - Implement a basic USB DFU device - -Overview -******** - -This sample application demonstrates the USB DFU implementation using the -new experimental USB device stack. - -Requirements -************ - -This project requires an experimental USB device driver (UDC API) and uses the -:ref:`disk_access_api` and RAM-disk to download/upload the image. - -Building and Running -******************** - -This sample can be built for multiple boards, in this example we will build it -for the reel board: - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/usb/dfu-next - :board: reel_board - :goals: build flash - :compact: - -`dfu-util`_ tool can be used to download or upload the images. There are two -modes of operation in the USB DFU, runtime and DFU. The example starts in -runtime mode. To switch to DFU mode without uploading or downloading, the -following command can be used: - -.. code-block:: console - - dfu-util --detach - -Use the following command to upload the ``ramdisk0`` image to the host: - -.. code-block:: console - - dfu-util --alt 0 --upload ramdisk0_backup.bin - -Use the following command to download the ``ramdisk0`` image to the device: - -.. code-block:: console - - dfu-util --alt 0 --download ramdisk0_backup.bin - -Building with flash backend enabled -*********************************** - -The USB DFU device support has a built-in flash backend. This backend uses -:ref:`flash_img_api` and :ref:`flash_map_api` to write or read flash image, the -implementation is similar to the one we had in the previous USB DFU device -example. - -To use flash backend set the :kconfig:option:`CONFIG_APP_USB_DFU_USE_FLASH_BACKEND`. -An additional interface will be available in DFU mode to upload/download the -SLOT-1 image. - -It is also possible to try the sample together with the MCUboot bootloader -library. The following example shows how to build MCUboot and this sample with -flash backend and MCUboot support enabled using the :ref:`sysbuild`: - -.. zephyr-app-commands:: - :tool: west - :zephyr-app: samples/subsys/usb/dfu-next - :board: reel_board - :goals: build flash - :west-args: --sysbuild - :gen-args: -DSB_CONFIG_BOOTLOADER_MCUBOOT=y -DCONFIG_APP_USB_DFU_USE_FLASH_BACKEND=y - -Another application image is required to be used as a firmware update and -downloaded to SLOT-1. Build and sign a second application image e.g. -:zephyr:code-sample:`hello_world`, which will be used as an image for the -update. Do not forget to enable the required :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` -option (as described in :ref:`mcuboot`). For example: - -.. zephyr-app-commands:: - :app: zephyr/samples/hello_world - :board: reel_board - :gen-args: -DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE=\"bootloader/mcuboot/root-rsa-2048.pem\" -DCONFIG_BOOTLOADER_MCUBOOT=y - :goals: flash - -Use the following command to download new image to the device: - -.. code-block:: console - - dfu-util --alt 1 --download build/zephyr/zephyr.signed.bin - -Reset the SoC. MCUboot boot will swap the images and boot the new application, -showing this output to the console: - -.. code-block:: console - - *** Booting MCUboot v2.1.0-rc1-134-gb9d69dd2a2d6 *** - *** Using Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** - I: Starting bootloader - I: Primary image: magic=good, swap_type=0x4, copy_done=0x1, image_ok=0x1 - I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3 - I: Boot source: none - I: Image index: 0, Swap type: test - I: Starting swap using move algorithm. - I: Bootloader chainload address offset: 0xc000 - I: Image version: v0.0.0 - I: Jumping to the first image slot - *** Booting Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** - Hello World! reel_board@1/nrf52840 - - -Reset the SoC again and MCUboot should revert the images and boot -USB DFU sample, showing this output to the console: - -.. code-block:: console - - *** Booting MCUboot v2.1.0-rc1-134-gb9d69dd2a2d6 *** - *** Using Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** - I: Starting bootloader - I: Primary image: magic=good, swap_type=0x2, copy_done=0x1, image_ok=0x3 - I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 - I: Boot source: none - I: Image index: 0, Swap type: revert - I: Starting swap using move algorithm. - I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 - I: Bootloader chainload address offset: 0xc000 - I: Image version: v0.0.0 - I: Jumping to the first image slot - *** Booting Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** - [00:00:00.000,335] main: USBD message: VBUS ready - [00:00:00.000,427] main: USB DFU sample is initialized - - -.. _dfu-util: https://dfu-util.sourceforge.net/ -.. _Using MCUboot with Zephyr: https://docs.mcuboot.com/readme-zephyr diff --git a/samples/subsys/usb/dfu-next/prj.conf b/samples/subsys/usb/dfu-next/prj.conf deleted file mode 100644 index 4ac6e6dd8d2ee..0000000000000 --- a/samples/subsys/usb/dfu-next/prj.conf +++ /dev/null @@ -1,10 +0,0 @@ -CONFIG_USB_DEVICE_STACK_NEXT=y -CONFIG_USBD_DFU=y - -CONFIG_LOG=y -CONFIG_USBD_LOG_LEVEL_WRN=y -CONFIG_USBD_DFU_LOG_LEVEL_WRN=y -CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y -CONFIG_SAMPLE_USBD_PID=0x0005 - -CONFIG_DISK_ACCESS=y diff --git a/samples/subsys/usb/dfu-next/sample.yaml b/samples/subsys/usb/dfu-next/sample.yaml deleted file mode 100644 index 02b53e25d5362..0000000000000 --- a/samples/subsys/usb/dfu-next/sample.yaml +++ /dev/null @@ -1,25 +0,0 @@ -sample: - name: USB DFU sample -common: - min_ram: 64 - depends_on: - - usbd -tests: - sample.usbd.dfu: - integration_platforms: - - nrf52840dk/nrf52840 - - nrf54h20dk/nrf54h20/cpuapp - - frdm_k64f - - stm32f723e_disco - - nucleo_f413zh - - mimxrt685_evk/mimxrt685s/cm33 - - mimxrt1060_evk/mimxrt1062/qspi - tags: usb - sample.usbd.dfu-flash: - platform_allow: - - nrf52840dk/nrf52840 - - frdm_k64f - min_flash: 1024 - tags: usb - extra_configs: - - CONFIG_APP_USB_DFU_USE_FLASH_BACKEND=y diff --git a/samples/subsys/usb/dfu-next/src/main.c b/samples/subsys/usb/dfu-next/src/main.c deleted file mode 100644 index 81f8aa6c89c00..0000000000000 --- a/samples/subsys/usb/dfu-next/src/main.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include -#include -#include -#include - -#include -LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); - -USBD_DEVICE_DEFINE(dfu_usbd, - DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), - 0x2fe3, 0xffff); - -USBD_DESC_LANG_DEFINE(sample_lang); -USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "DFU FS Configuration"); -USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "DFU HS Configuration"); - -static const uint8_t attributes = (IS_ENABLED(CONFIG_SAMPLE_USBD_SELF_POWERED) ? - USB_SCD_SELF_POWERED : 0) | - (IS_ENABLED(CONFIG_SAMPLE_USBD_REMOTE_WAKEUP) ? - USB_SCD_REMOTE_WAKEUP : 0); -/* Full speed configuration */ -USBD_CONFIGURATION_DEFINE(sample_fs_config, - attributes, - CONFIG_SAMPLE_USBD_MAX_POWER, &fs_cfg_desc); - -/* High speed configuration */ -USBD_CONFIGURATION_DEFINE(sample_hs_config, - attributes, - CONFIG_SAMPLE_USBD_MAX_POWER, &hs_cfg_desc); - -static void switch_to_dfu_mode(struct usbd_context *const ctx); - -struct dfu_ramdisk_data { - const char *name; - uint32_t last_block; - uint32_t sector_size; - uint32_t sector_count; - union { - uint32_t uploaded; - uint32_t downloaded; - }; -}; - -static struct dfu_ramdisk_data ramdisk0_data = { - .name = "image0", -}; - -static int init_dfu_ramdisk_data(struct dfu_ramdisk_data *const data) -{ - int err; - - err = disk_access_init(data->name); - if (err) { - return err; - } - - err = disk_access_status(data->name); - if (err) { - return err; - } - - err = disk_access_ioctl(data->name, DISK_IOCTL_GET_SECTOR_COUNT, &data->sector_count); - if (err) { - return err; - } - - err = disk_access_ioctl(data->name, DISK_IOCTL_GET_SECTOR_SIZE, &data->sector_size); - if (err) { - return err; - } - - LOG_INF("disk %s sector count %u sector size %u", - data->name, data->sector_count, data->sector_size); - - return err; -} - -static int ramdisk_read(void *const priv, const uint32_t block, const uint16_t size, - uint8_t buf[static CONFIG_USBD_DFU_TRANSFER_SIZE]) -{ - struct dfu_ramdisk_data *const data = priv; - int err; - - if (size == 0) { - /* There is nothing to upload */ - return 0; - } - - if (block == 0) { - if (init_dfu_ramdisk_data(data)) { - LOG_ERR("Failed to init ramdisk data"); - return -EINVAL; - } - - data->last_block = 0; - data->uploaded = 0; - } else { - if (data->last_block + 1U != block) { - return -EINVAL; - } - - } - - if (block >= data->sector_count) { - /* Nothing to upload */ - return 0; - } - - err = disk_access_read(data->name, buf, block, 1); - if (err) { - LOG_ERR("Failed to read from RAMdisk"); - return err; - } - - data->last_block = block; - data->uploaded += MIN(size, data->sector_size); - LOG_INF("block %u size %u uploaded %u", block, size, data->uploaded); - - return size; -} - -static int ramdisk_write(void *const priv, const uint32_t block, const uint16_t size, - const uint8_t buf[static CONFIG_USBD_DFU_TRANSFER_SIZE]) -{ - struct dfu_ramdisk_data *const data = priv; - int err; - - if (block == 0) { - if (init_dfu_ramdisk_data(data)) { - LOG_ERR("Failed to init ramdisk data"); - return -EINVAL; - } - - data->last_block = 0; - data->downloaded = 0; - } else { - if (data->last_block + 1U != block) { - return -EINVAL; - } - - } - - if (size == 0) { - /* Nothing to write */ - return 0; - } - - err = disk_access_write(data->name, buf, block, 1); - if (err) { - LOG_ERR("Failed to write to RAMdisk"); - return err; - } - - data->last_block = block; - data->downloaded += size; - LOG_INF("block %u size %u downloaded %u", block, size, data->downloaded); - - return 0; -} - -USBD_DFU_DEFINE_IMG(ramdisk0, "ramdisk0", &ramdisk0_data, ramdisk_read, ramdisk_write, NULL); - -static void msg_cb(struct usbd_context *const usbd_ctx, - const struct usbd_msg *const msg) -{ - LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); - - if (msg->type == USBD_MSG_CONFIGURATION) { - LOG_INF("\tConfiguration value %d", msg->status); - } - - if (usbd_can_detect_vbus(usbd_ctx)) { - if (msg->type == USBD_MSG_VBUS_READY) { - if (usbd_enable(usbd_ctx)) { - LOG_ERR("Failed to enable device support"); - } - } - - if (msg->type == USBD_MSG_VBUS_REMOVED) { - if (usbd_disable(usbd_ctx)) { - LOG_ERR("Failed to disable device support"); - } - } - } - - if (msg->type == USBD_MSG_DFU_APP_DETACH) { - switch_to_dfu_mode(usbd_ctx); - } - - if (msg->type == USBD_MSG_DFU_DOWNLOAD_COMPLETED) { - if (IS_ENABLED(CONFIG_BOOTLOADER_MCUBOOT) && - IS_ENABLED(CONFIG_APP_USB_DFU_USE_FLASH_BACKEND)) { - boot_request_upgrade(false); - } - } -} - -static void switch_to_dfu_mode(struct usbd_context *const ctx) -{ - int err; - - LOG_INF("Detach USB device"); - usbd_disable(ctx); - usbd_shutdown(ctx); - - err = usbd_add_descriptor(&dfu_usbd, &sample_lang); - if (err) { - LOG_ERR("Failed to initialize language descriptor (%d)", err); - return; - } - - if (usbd_caps_speed(&dfu_usbd) == USBD_SPEED_HS) { - err = usbd_add_configuration(&dfu_usbd, USBD_SPEED_HS, &sample_hs_config); - if (err) { - LOG_ERR("Failed to add High-Speed configuration"); - return; - } - - err = usbd_register_class(&dfu_usbd, "dfu_dfu", USBD_SPEED_HS, 1); - if (err) { - LOG_ERR("Failed to add register classes"); - return; - } - - usbd_device_set_code_triple(&dfu_usbd, USBD_SPEED_HS, 0, 0, 0); - } - - err = usbd_add_configuration(&dfu_usbd, USBD_SPEED_FS, &sample_fs_config); - if (err) { - LOG_ERR("Failed to add Full-Speed configuration"); - return; - } - - err = usbd_register_class(&dfu_usbd, "dfu_dfu", USBD_SPEED_FS, 1); - if (err) { - LOG_ERR("Failed to add register classes"); - return; - } - - usbd_device_set_code_triple(&dfu_usbd, USBD_SPEED_FS, 0, 0, 0); - - err = usbd_init(&dfu_usbd); - if (err) { - LOG_ERR("Failed to initialize USB device support"); - return; - } - - err = usbd_msg_register_cb(&dfu_usbd, msg_cb); - if (err) { - LOG_ERR("Failed to register message callback"); - return; - } - - err = usbd_enable(&dfu_usbd); - if (err) { - LOG_ERR("Failed to enable USB device support"); - } -} - -int main(void) -{ - struct usbd_context *sample_usbd; - int ret; - - sample_usbd = sample_usbd_init_device(msg_cb); - if (sample_usbd == NULL) { - LOG_ERR("Failed to initialize USB device"); - return -ENODEV; - } - - if (!usbd_can_detect_vbus(sample_usbd)) { - ret = usbd_enable(sample_usbd); - if (ret) { - LOG_ERR("Failed to enable device support"); - return ret; - } - } - - LOG_INF("USB DFU sample is initialized"); - - return 0; -} diff --git a/samples/subsys/usb/dfu/CMakeLists.txt b/samples/subsys/usb/dfu/CMakeLists.txt index 2da1508d6a1e1..defe46f998fb6 100644 --- a/samples/subsys/usb/dfu/CMakeLists.txt +++ b/samples/subsys/usb/dfu/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(dfu) +project(usb-dfu) +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/dfu-next/Kconfig b/samples/subsys/usb/dfu/Kconfig similarity index 100% rename from samples/subsys/usb/dfu-next/Kconfig rename to samples/subsys/usb/dfu/Kconfig diff --git a/samples/subsys/usb/dfu/README.rst b/samples/subsys/usb/dfu/README.rst index 44b173184a583..a83cd7d553cc4 100644 --- a/samples/subsys/usb/dfu/README.rst +++ b/samples/subsys/usb/dfu/README.rst @@ -1,94 +1,114 @@ .. zephyr:code-sample:: usb-dfu - :name: USB DFU (Device Firmware Upgrade) - :relevant-api: _usb_device_core_api + :name: USB DFU + :relevant-api: usbd_api usbd_dfu - Implement device firmware upgrade using the USB DFU class driver. + Implement a basic USB DFU device Overview ******** -This sample app demonstrates use of a USB DFU Class driver provided -by the Zephyr project. +This sample application demonstrates the USB DFU implementation using the +new experimental USB device stack. Requirements ************ -This project requires an USB device driver. Currently, the USB DFU -class provided by the Zephyr project depends on DFU image manager and -partition layout. Refer to :ref:`flash_map_api` for details about -partition layout. You SoC must run MCUboot as the stage 1 bootloader. -This sample is built as an application for the MCUboot bootloader. +This project requires an experimental USB device driver (UDC API) and uses the +:ref:`disk_access_api` and RAM-disk to download/upload the image. -.. note:: - This example explicitly turns :kconfig:option:`CONFIG_USB_DFU_ENABLE_UPLOAD` on. - -Building and Testing +Building and Running ******************** -Building and signing the application -==================================== - -This sample can be built in the usual way (see :ref:`build_an_application` -for more details) and flashed with regular flash tools, but will need -to be loaded at the offset of SLOT-0. +This sample can be built for multiple boards, in this example we will build it +for the reel board: -Application images (such as this sample) must be signed. -The build system can do this for you by setting the :kconfig:option:`CONFIG_MCUBOOT_SIGNATURE_KEY_FILE` symbol. +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/dfu + :board: reel_board + :goals: build flash + :compact: -For example: +`dfu-util`_ tool can be used to download or upload the images. There are two +modes of operation in the USB DFU, runtime and DFU. The example starts in +runtime mode. To switch to DFU mode without uploading or downloading, the +following command can be used: .. code-block:: console - west build -b nrf52840dk/nrf52840 zephyr/samples/subsys/usb/dfu -d build-dfu -- \ - -DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE=\"bootloader/mcuboot/root-rsa-2048.pem\" + dfu-util --detach + +Use the following command to upload the ``ramdisk0`` image to the host: + +.. code-block:: console -Build and flash MCUboot bootloader for Zephyr project as it is described in -the `Using MCUboot with Zephyr`_ documentation. Then build, sign and flash -the USB DFU sample at the offset of SLOT-0. + dfu-util --alt 0 --upload ramdisk0_backup.bin -Build and sign a second application image e.g. :zephyr:code-sample:`hello_world`, -which will be used as an image for the update. -Do not forget to enable the required :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` option (as described -in :ref:`mcuboot`). For example: +Use the following command to download the ``ramdisk0`` image to the device: .. code-block:: console - west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -d build-hello_world -- \ - -DCONFIG_BOOTLOADER_MCUBOOT=y '-DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE="bootloader/mcuboot/root-rsa-2048.pem"' + dfu-util --alt 0 --download ramdisk0_backup.bin -Testing -======= +Building with flash backend enabled +*********************************** -The Linux ``dfu-util`` tool can be used to backup or update the application -image. +The USB DFU device support has a built-in flash backend. This backend uses +:ref:`flash_img_api` and :ref:`flash_map_api` to write or read flash image, the +implementation is similar to the one we had in the previous USB DFU device +example. -Use the following command to backup the SLOT-0 image: +To use flash backend set the :kconfig:option:`CONFIG_APP_USB_DFU_USE_FLASH_BACKEND`. +An additional interface will be available in DFU mode to upload/download the +SLOT-1 image. -.. code-block:: console +It is also possible to try the sample together with the MCUboot bootloader +library. The following example shows how to build MCUboot and this sample with +flash backend and MCUboot support enabled using the :ref:`sysbuild`: + +.. zephyr-app-commands:: + :tool: west + :zephyr-app: samples/subsys/usb/dfu + :board: reel_board + :goals: build flash + :west-args: --sysbuild + :gen-args: -DSB_CONFIG_BOOTLOADER_MCUBOOT=y -DCONFIG_APP_USB_DFU_USE_FLASH_BACKEND=y + +Another application image is required to be used as a firmware update and +downloaded to SLOT-1. Build and sign a second application image e.g. +:zephyr:code-sample:`hello_world`, which will be used as an image for the +update. Do not forget to enable the required :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` +option (as described in :ref:`mcuboot`). For example: - dfu-util --alt 0 --upload slot0_backup.bin +.. zephyr-app-commands:: + :app: zephyr/samples/hello_world + :board: reel_board + :gen-args: -DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE=\"bootloader/mcuboot/root-rsa-2048.pem\" -DCONFIG_BOOTLOADER_MCUBOOT=y + :goals: flash -Use the following command to update the application: +Use the following command to download new image to the device: .. code-block:: console - dfu-util --alt 1 --download build-hello_world/zephyr/zephyr.signed.bin + dfu-util --alt 1 --download build/zephyr/zephyr.signed.bin Reset the SoC. MCUboot boot will swap the images and boot the new application, showing this output to the console: .. code-block:: console - *** Booting Zephyr OS build zephyr-v3.0.0-360-gc0dd594d4d3d *** + *** Booting MCUboot v2.1.0-rc1-134-gb9d69dd2a2d6 *** + *** Using Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** I: Starting bootloader - I: Primary image: magic=good, swap_type=0x3, copy_done=0x1, image_ok=0x1 + I: Primary image: magic=good, swap_type=0x4, copy_done=0x1, image_ok=0x1 I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3 I: Boot source: none - I: Swap type: test + I: Image index: 0, Swap type: test + I: Starting swap using move algorithm. I: Bootloader chainload address offset: 0xc000 + I: Image version: v0.0.0 I: Jumping to the first image slot - *** Booting Zephyr OS build zephyr-v3.0.0-361-gb987e6daa2f9 *** - Hello World! nrf52840dk + *** Booting Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** + Hello World! reel_board@1/nrf52840 Reset the SoC again and MCUboot should revert the images and boot @@ -96,62 +116,22 @@ USB DFU sample, showing this output to the console: .. code-block:: console - *** Booting Zephyr OS build zephyr-v3.0.0-360-gc0dd594d4d3d *** + *** Booting MCUboot v2.1.0-rc1-134-gb9d69dd2a2d6 *** + *** Using Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** I: Starting bootloader I: Primary image: magic=good, swap_type=0x2, copy_done=0x1, image_ok=0x3 I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 I: Boot source: none - I: Swap type: revert + I: Image index: 0, Swap type: revert + I: Starting swap using move algorithm. I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 I: Bootloader chainload address offset: 0xc000 + I: Image version: v0.0.0 I: Jumping to the first image slot - *** Booting Zephyr OS build zephyr-v3.0.0-361-gb987e6daa2f9 *** - [00:00:00.005,920] main: This device supports USB DFU class. - -Permanent download and automatic reboot -======================================= - -There are some symbols that can be used to enable a hands free download: - -To mark SLOT-1 as permanent after the download completes, -enable the :kconfig:option:`CONFIG_USB_DFU_PERMANENT_DOWNLOAD` symbol. - -To automatically reboot after the download completes, -enable the :kconfig:option:`CONFIG_USB_DFU_REBOOT` symbol. - -.. warning:: - Enabling :kconfig:option:`CONFIG_USB_DFU_PERMANENT_DOWNLOAD` can lead to a bricked device! - Make sure there is another way to download firmware. - For example via a debugger or Mcuboot's recovery mode. - -Both symbols can be enabled with the :file:`overlay-permanent-download.conf` overlay. For example: - -.. code-block:: console - - west build -b nrf52840dk/nrf52840 zephyr/samples/subsys/usb/dfu -d build-dfu -- \ - -DCONFIG_BOOTLOADER_MCUBOOT=y '-DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE="bootloader/mcuboot/root-rsa-2048.pem"' \ - -DEXTRA_CONF_FILE=overlay-permanent-download.conf - - -The listing below shows the output to the console when downloading via dfu-util. -Note the ``Swap type: perm``. - -.. code-block:: console - - *** Booting Zephyr OS build zephyr-v3.0.0-361-ge6900e2451d5 *** - [00:00:00.005,920] main: This device supports USB DFU class. - - *** Booting Zephyr OS build zephyr-v3.0.0-360-gc0dd594d4d3d *** - I: Starting bootloader - I: Primary image: magic=good, swap_type=0x4, copy_done=0x1, image_ok=0x1 - I: Secondary image: magic=good, swap_type=0x3, copy_done=0x3, image_ok=0x1 - I: Boot source: none - I: Swap type: perm - I: Bootloader chainload address offset: 0xc000 - I: Jumping to the first image slot - *** Booting Zephyr OS build zephyr-v3.0.0-361-gb987e6daa2f9 *** - Hello World! nrf52840dk + *** Booting Zephyr OS build v3.7.0-4345-ga5d0d8533a41 *** + [00:00:00.000,335] main: USBD message: VBUS ready + [00:00:00.000,427] main: USB DFU sample is initialized -.. _MCUboot GitHub repo: https://github.com/zephyrproject-rtos/mcuboot +.. _dfu-util: https://dfu-util.sourceforge.net/ .. _Using MCUboot with Zephyr: https://docs.mcuboot.com/readme-zephyr diff --git a/samples/subsys/usb/dfu-next/app.overlay b/samples/subsys/usb/dfu/app.overlay similarity index 100% rename from samples/subsys/usb/dfu-next/app.overlay rename to samples/subsys/usb/dfu/app.overlay diff --git a/samples/subsys/usb/dfu/prj.conf b/samples/subsys/usb/dfu/prj.conf index 6bf6f1ee310b5..4ac6e6dd8d2ee 100644 --- a/samples/subsys/usb/dfu/prj.conf +++ b/samples/subsys/usb/dfu/prj.conf @@ -1,16 +1,10 @@ -CONFIG_STDOUT_CONSOLE=y -CONFIG_GPIO=y -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr DFU sample" -CONFIG_USB_DEVICE_PID=0x0005 -CONFIG_USB_DFU_CLASS=y -CONFIG_USB_DFU_ENABLE_UPLOAD=y -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_STREAM_FLASH=y -CONFIG_IMG_MANAGER=y +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_DFU=y + CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y -CONFIG_BOOTLOADER_MCUBOOT=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_USBD_DFU_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x0005 + +CONFIG_DISK_ACCESS=y diff --git a/samples/subsys/usb/dfu/sample.yaml b/samples/subsys/usb/dfu/sample.yaml index dea42901cc7b9..02b53e25d5362 100644 --- a/samples/subsys/usb/dfu/sample.yaml +++ b/samples/subsys/usb/dfu/sample.yaml @@ -1,43 +1,25 @@ sample: name: USB DFU sample - common: - build_only: true - arch_exclude: posix - platform_exclude: - - mimxrt1010_evk - - mimxrt1020_evk - - mimxrt1015_evk - - mimxrt1060_evk@A/mimxrt1062/qspi - - mimxrt1060_evk@B/mimxrt1062/qspi - - mimxrt1060_evk@C/mimxrt1062/qspi - - sam4l_ek - - same54_xpro - - samr21_xpro - - mimxrt1050_evk/mimxrt1052/hyperflash - - mimxrt1050_evk/mimxrt1052/qspi - - mimxrt1060_evk/mimxrt1062/hyperflash - - mimxrt1180_evk/mimxrt1189/cm7 - - nucleo_f207zg - - teensy40 - - teensy41 - - b_u585i_iot02a - - frdm_kl25z - - frdm_mcxc242 - - frdm_mcxc444 - - frdm_mcxa156 - - lpcxpresso55s69/lpc55s69/cpu0 - - stm32l562e_dk/stm32l562xx/ns - depends_on: usb_device - filter: dt_label_with_parent_compat_enabled("slot0_partition", "fixed-partitions") - and dt_label_with_parent_compat_enabled("slot1_partition", "fixed-partitions") - and dt_chosen_enabled("zephyr,flash-controller") and CONFIG_FLASH_HAS_DRIVER_ENABLED - integration_platforms: - - nrf52840dk/nrf52840 - - frdm_k64f + min_ram: 64 + depends_on: + - usbd tests: - sample.usb.dfu: + sample.usbd.dfu: + integration_platforms: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - frdm_k64f + - stm32f723e_disco + - nucleo_f413zh + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk/mimxrt1062/qspi tags: usb - sample.usb.dfu.permanent.download: + sample.usbd.dfu-flash: + platform_allow: + - nrf52840dk/nrf52840 + - frdm_k64f + min_flash: 1024 tags: usb - extra_args: EXTRA_CONF_FILE=overlay-permanent-download.conf + extra_configs: + - CONFIG_APP_USB_DFU_USE_FLASH_BACKEND=y diff --git a/samples/subsys/usb/dfu/src/main.c b/samples/subsys/usb/dfu/src/main.c index 2c10c2e65ff03..81f8aa6c89c00 100644 --- a/samples/subsys/usb/dfu/src/main.c +++ b/samples/subsys/usb/dfu/src/main.c @@ -1,27 +1,291 @@ /* - * Copyright (c) 2016 Intel Corporation - * Copyright (c) 2017 Phytec Messtechnik GmbH + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -/* Sample app for USB DFU class driver. */ +#include #include +#include +#include +#include +#include + #include -#include -LOG_MODULE_REGISTER(main); +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); + +USBD_DEVICE_DEFINE(dfu_usbd, + DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), + 0x2fe3, 0xffff); + +USBD_DESC_LANG_DEFINE(sample_lang); +USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "DFU FS Configuration"); +USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "DFU HS Configuration"); + +static const uint8_t attributes = (IS_ENABLED(CONFIG_SAMPLE_USBD_SELF_POWERED) ? + USB_SCD_SELF_POWERED : 0) | + (IS_ENABLED(CONFIG_SAMPLE_USBD_REMOTE_WAKEUP) ? + USB_SCD_REMOTE_WAKEUP : 0); +/* Full speed configuration */ +USBD_CONFIGURATION_DEFINE(sample_fs_config, + attributes, + CONFIG_SAMPLE_USBD_MAX_POWER, &fs_cfg_desc); + +/* High speed configuration */ +USBD_CONFIGURATION_DEFINE(sample_hs_config, + attributes, + CONFIG_SAMPLE_USBD_MAX_POWER, &hs_cfg_desc); + +static void switch_to_dfu_mode(struct usbd_context *const ctx); + +struct dfu_ramdisk_data { + const char *name; + uint32_t last_block; + uint32_t sector_size; + uint32_t sector_count; + union { + uint32_t uploaded; + uint32_t downloaded; + }; +}; + +static struct dfu_ramdisk_data ramdisk0_data = { + .name = "image0", +}; + +static int init_dfu_ramdisk_data(struct dfu_ramdisk_data *const data) +{ + int err; + + err = disk_access_init(data->name); + if (err) { + return err; + } + + err = disk_access_status(data->name); + if (err) { + return err; + } + + err = disk_access_ioctl(data->name, DISK_IOCTL_GET_SECTOR_COUNT, &data->sector_count); + if (err) { + return err; + } + + err = disk_access_ioctl(data->name, DISK_IOCTL_GET_SECTOR_SIZE, &data->sector_size); + if (err) { + return err; + } + + LOG_INF("disk %s sector count %u sector size %u", + data->name, data->sector_count, data->sector_size); + + return err; +} + +static int ramdisk_read(void *const priv, const uint32_t block, const uint16_t size, + uint8_t buf[static CONFIG_USBD_DFU_TRANSFER_SIZE]) +{ + struct dfu_ramdisk_data *const data = priv; + int err; + + if (size == 0) { + /* There is nothing to upload */ + return 0; + } + + if (block == 0) { + if (init_dfu_ramdisk_data(data)) { + LOG_ERR("Failed to init ramdisk data"); + return -EINVAL; + } + + data->last_block = 0; + data->uploaded = 0; + } else { + if (data->last_block + 1U != block) { + return -EINVAL; + } + + } + + if (block >= data->sector_count) { + /* Nothing to upload */ + return 0; + } + + err = disk_access_read(data->name, buf, block, 1); + if (err) { + LOG_ERR("Failed to read from RAMdisk"); + return err; + } + + data->last_block = block; + data->uploaded += MIN(size, data->sector_size); + LOG_INF("block %u size %u uploaded %u", block, size, data->uploaded); + + return size; +} + +static int ramdisk_write(void *const priv, const uint32_t block, const uint16_t size, + const uint8_t buf[static CONFIG_USBD_DFU_TRANSFER_SIZE]) +{ + struct dfu_ramdisk_data *const data = priv; + int err; + + if (block == 0) { + if (init_dfu_ramdisk_data(data)) { + LOG_ERR("Failed to init ramdisk data"); + return -EINVAL; + } + + data->last_block = 0; + data->downloaded = 0; + } else { + if (data->last_block + 1U != block) { + return -EINVAL; + } + + } + + if (size == 0) { + /* Nothing to write */ + return 0; + } + + err = disk_access_write(data->name, buf, block, 1); + if (err) { + LOG_ERR("Failed to write to RAMdisk"); + return err; + } + + data->last_block = block; + data->downloaded += size; + LOG_INF("block %u size %u downloaded %u", block, size, data->downloaded); + + return 0; +} + +USBD_DFU_DEFINE_IMG(ramdisk0, "ramdisk0", &ramdisk0_data, ramdisk_read, ramdisk_write, NULL); + +static void msg_cb(struct usbd_context *const usbd_ctx, + const struct usbd_msg *const msg) +{ + LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); + + if (msg->type == USBD_MSG_CONFIGURATION) { + LOG_INF("\tConfiguration value %d", msg->status); + } + + if (usbd_can_detect_vbus(usbd_ctx)) { + if (msg->type == USBD_MSG_VBUS_READY) { + if (usbd_enable(usbd_ctx)) { + LOG_ERR("Failed to enable device support"); + } + } + + if (msg->type == USBD_MSG_VBUS_REMOVED) { + if (usbd_disable(usbd_ctx)) { + LOG_ERR("Failed to disable device support"); + } + } + } + + if (msg->type == USBD_MSG_DFU_APP_DETACH) { + switch_to_dfu_mode(usbd_ctx); + } + + if (msg->type == USBD_MSG_DFU_DOWNLOAD_COMPLETED) { + if (IS_ENABLED(CONFIG_BOOTLOADER_MCUBOOT) && + IS_ENABLED(CONFIG_APP_USB_DFU_USE_FLASH_BACKEND)) { + boot_request_upgrade(false); + } + } +} + +static void switch_to_dfu_mode(struct usbd_context *const ctx) +{ + int err; + + LOG_INF("Detach USB device"); + usbd_disable(ctx); + usbd_shutdown(ctx); + + err = usbd_add_descriptor(&dfu_usbd, &sample_lang); + if (err) { + LOG_ERR("Failed to initialize language descriptor (%d)", err); + return; + } + + if (usbd_caps_speed(&dfu_usbd) == USBD_SPEED_HS) { + err = usbd_add_configuration(&dfu_usbd, USBD_SPEED_HS, &sample_hs_config); + if (err) { + LOG_ERR("Failed to add High-Speed configuration"); + return; + } + + err = usbd_register_class(&dfu_usbd, "dfu_dfu", USBD_SPEED_HS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return; + } + + usbd_device_set_code_triple(&dfu_usbd, USBD_SPEED_HS, 0, 0, 0); + } + + err = usbd_add_configuration(&dfu_usbd, USBD_SPEED_FS, &sample_fs_config); + if (err) { + LOG_ERR("Failed to add Full-Speed configuration"); + return; + } + + err = usbd_register_class(&dfu_usbd, "dfu_dfu", USBD_SPEED_FS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return; + } + + usbd_device_set_code_triple(&dfu_usbd, USBD_SPEED_FS, 0, 0, 0); + + err = usbd_init(&dfu_usbd); + if (err) { + LOG_ERR("Failed to initialize USB device support"); + return; + } + + err = usbd_msg_register_cb(&dfu_usbd, msg_cb); + if (err) { + LOG_ERR("Failed to register message callback"); + return; + } + + err = usbd_enable(&dfu_usbd); + if (err) { + LOG_ERR("Failed to enable USB device support"); + } +} int main(void) { + struct usbd_context *sample_usbd; int ret; - ret = usb_enable(NULL); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; + sample_usbd = sample_usbd_init_device(msg_cb); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); + return -ENODEV; } - LOG_INF("This device supports USB DFU class.\n"); + if (!usbd_can_detect_vbus(sample_usbd)) { + ret = usbd_enable(sample_usbd); + if (ret) { + LOG_ERR("Failed to enable device support"); + return ret; + } + } + + LOG_INF("USB DFU sample is initialized"); + return 0; } diff --git a/samples/subsys/usb/hid-mouse/README.rst b/samples/subsys/usb/hid-mouse/README.rst index e2f099f98f447..0c1d908f05b8e 100644 --- a/samples/subsys/usb/hid-mouse/README.rst +++ b/samples/subsys/usb/hid-mouse/README.rst @@ -1,6 +1,6 @@ .. zephyr:code-sample:: usb-hid-mouse :name: USB HID mouse - :relevant-api: _usb_device_core_api usb_hid_device_api input_interface + :relevant-api: usbd_api usbd_hid_device input_interface Implement a basic HID mouse device. diff --git a/samples/subsys/usb/hid-mouse/usbd_next.overlay b/samples/subsys/usb/hid-mouse/app.overlay similarity index 100% rename from samples/subsys/usb/hid-mouse/usbd_next.overlay rename to samples/subsys/usb/hid-mouse/app.overlay diff --git a/samples/subsys/usb/hid-mouse/prj.conf b/samples/subsys/usb/hid-mouse/prj.conf index b797a7382e814..9c8894b2126c6 100644 --- a/samples/subsys/usb/hid-mouse/prj.conf +++ b/samples/subsys/usb/hid-mouse/prj.conf @@ -1,13 +1,11 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_HID=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr HID mouse sample" -CONFIG_USB_DEVICE_PID=0x0007 -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_HID_SUPPORT=y CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_USBD_HID_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x0007 CONFIG_GPIO=y CONFIG_INPUT=y -CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/samples/subsys/usb/hid-mouse/sample.yaml b/samples/subsys/usb/hid-mouse/sample.yaml index ea670e849e9f9..0f56b990da7d7 100644 --- a/samples/subsys/usb/hid-mouse/sample.yaml +++ b/samples/subsys/usb/hid-mouse/sample.yaml @@ -6,12 +6,6 @@ common: depends_on: - gpio tests: - sample.usb.hid-mouse: - depends_on: - - usb_device - platform_exclude: - - frdm_mcxn947/mcxn947/cpu0 - tags: usb sample.usb_device_next.hid-mouse: depends_on: - usbd @@ -22,7 +16,5 @@ tests: - stm32f723e_disco - nucleo_f413zh - mimxrt1060_evk/mimxrt1062/qspi - extra_args: - - CONF_FILE="usbd_next_prj.conf" - - EXTRA_DTC_OVERLAY_FILE="usbd_next.overlay" + - mimxrt685_evk/mimxrt685s/cm33 tags: usb diff --git a/samples/subsys/usb/hid-mouse/src/main.c b/samples/subsys/usb/hid-mouse/src/main.c index 4e579832cf9db..967591b2a7119 100644 --- a/samples/subsys/usb/hid-mouse/src/main.c +++ b/samples/subsys/usb/hid-mouse/src/main.c @@ -15,16 +15,14 @@ #include #include -#include #include -#include +#include #include LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); static const uint8_t hid_report_desc[] = HID_MOUSE_REPORT_DESC(2); -static enum usb_dc_status_code usb_status; #define MOUSE_BTN_LEFT 0 #define MOUSE_BTN_RIGHT 1 @@ -38,22 +36,7 @@ enum mouse_report_idx { }; K_MSGQ_DEFINE(mouse_msgq, MOUSE_REPORT_COUNT, 2, 1); -static K_SEM_DEFINE(ep_write_sem, 0, 1); - -static inline void status_cb(enum usb_dc_status_code status, const uint8_t *param) -{ - usb_status = status; -} - -static ALWAYS_INLINE void rwup_if_suspended(void) -{ - if (IS_ENABLED(CONFIG_USB_DEVICE_REMOTE_WAKEUP)) { - if (usb_status == USB_DC_SUSPEND) { - usb_wakeup_request(); - return; - } - } -} +static bool mouse_ready; static void input_cb(struct input_event *evt, void *user_data) { @@ -63,11 +46,9 @@ static void input_cb(struct input_event *evt, void *user_data) switch (evt->code) { case INPUT_KEY_0: - rwup_if_suspended(); WRITE_BIT(tmp[MOUSE_BTN_REPORT_IDX], MOUSE_BTN_LEFT, evt->value); break; case INPUT_KEY_1: - rwup_if_suspended(); WRITE_BIT(tmp[MOUSE_BTN_REPORT_IDX], MOUSE_BTN_RIGHT, evt->value); break; case INPUT_KEY_2: @@ -99,42 +80,30 @@ static void input_cb(struct input_event *evt, void *user_data) INPUT_CALLBACK_DEFINE(NULL, input_cb, NULL); -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static int enable_usb_device_next(void) +static void mouse_iface_ready(const struct device *dev, const bool ready) { - struct usbd_context *sample_usbd; - int err; - - sample_usbd = sample_usbd_init_device(NULL); - if (sample_usbd == NULL) { - LOG_ERR("Failed to initialize USB device"); - return -ENODEV; - } - - err = usbd_enable(sample_usbd); - if (err) { - LOG_ERR("Failed to enable device support"); - return err; - } - - LOG_DBG("USB device support enabled"); - - return 0; + LOG_INF("HID device %s interface is %s", + dev->name, ready ? "ready" : "not ready"); + mouse_ready = ready; } -#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */ -static void int_in_ready_cb(const struct device *dev) +static int mouse_get_report(const struct device *dev, + const uint8_t type, const uint8_t id, const uint16_t len, + uint8_t *const buf) { - ARG_UNUSED(dev); - k_sem_give(&ep_write_sem); + LOG_WRN("Get Report not implemented, Type %u ID %u", type, id); + + return 0; } -static const struct hid_ops ops = { - .int_in_ready = int_in_ready_cb, +struct hid_device_ops mouse_ops = { + .iface_ready = mouse_iface_ready, + .get_report = mouse_get_report, }; int main(void) { + struct usbd_context *sample_usbd; const struct device *hid_dev; int ret; @@ -143,51 +112,58 @@ int main(void) return 0; } -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - hid_dev = DEVICE_DT_GET_ONE(zephyr_hid_device); -#else - hid_dev = device_get_binding("HID_0"); -#endif - if (hid_dev == NULL) { - LOG_ERR("Cannot get USB HID Device"); - return 0; - } - ret = gpio_pin_configure_dt(&led0, GPIO_OUTPUT); - if (ret < 0) { + if (ret != 0) { LOG_ERR("Failed to configure the LED pin, error: %d", ret); return 0; } - usb_hid_register_device(hid_dev, - hid_report_desc, sizeof(hid_report_desc), - &ops); + hid_dev = DEVICE_DT_GET_ONE(zephyr_hid_device); + if (!device_is_ready(hid_dev)) { + LOG_ERR("HID Device is not ready"); + return -EIO; + } - usb_hid_init(hid_dev); + ret = hid_device_register(hid_dev, + hid_report_desc, sizeof(hid_report_desc), + &mouse_ops); + if (ret != 0) { + LOG_ERR("Failed to register HID Device, %d", ret); + return ret; + } -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - ret = enable_usb_device_next(); -#else - ret = usb_enable(status_cb); -#endif + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); + return -ENODEV; + } + + ret = usbd_enable(sample_usbd); if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; + LOG_ERR("Failed to enable device support"); + return ret; } + LOG_DBG("USB device support enabled"); + while (true) { UDC_STATIC_BUF_DEFINE(report, MOUSE_REPORT_COUNT); k_msgq_get(&mouse_msgq, &report, K_FOREVER); - ret = hid_int_ep_write(hid_dev, report, MOUSE_REPORT_COUNT, NULL); + if (!mouse_ready) { + LOG_INF("USB HID device is not ready"); + continue; + } + + ret = hid_device_submit_report(hid_dev, MOUSE_REPORT_COUNT, report); if (ret) { - LOG_ERR("HID write error, %d", ret); + LOG_ERR("HID submit report error, %d", ret); } else { - k_sem_take(&ep_write_sem, K_FOREVER); /* Toggle LED on sent report */ (void)gpio_pin_toggle(led0.port, led0.pin); } } + return 0; } diff --git a/samples/subsys/usb/hid-mouse/usbd_next_prj.conf b/samples/subsys/usb/hid-mouse/usbd_next_prj.conf deleted file mode 100644 index 9c8894b2126c6..0000000000000 --- a/samples/subsys/usb/hid-mouse/usbd_next_prj.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_USB_DEVICE_STACK_NEXT=y -CONFIG_USBD_HID_SUPPORT=y - -CONFIG_LOG=y -CONFIG_USBD_LOG_LEVEL_WRN=y -CONFIG_USBD_HID_LOG_LEVEL_WRN=y -CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y -CONFIG_SAMPLE_USBD_PID=0x0007 - -CONFIG_GPIO=y -CONFIG_INPUT=y diff --git a/samples/subsys/usb/audio/headphones_microphone/CMakeLists.txt b/samples/subsys/usb/legacy/audio_headphones_microphone/CMakeLists.txt similarity index 100% rename from samples/subsys/usb/audio/headphones_microphone/CMakeLists.txt rename to samples/subsys/usb/legacy/audio_headphones_microphone/CMakeLists.txt diff --git a/samples/subsys/usb/audio/headphones_microphone/README.rst b/samples/subsys/usb/legacy/audio_headphones_microphone/README.rst similarity index 84% rename from samples/subsys/usb/audio/headphones_microphone/README.rst rename to samples/subsys/usb/legacy/audio_headphones_microphone/README.rst index e1506f8b20d64..df7fd3993145a 100644 --- a/samples/subsys/usb/audio/headphones_microphone/README.rst +++ b/samples/subsys/usb/legacy/audio_headphones_microphone/README.rst @@ -1,5 +1,5 @@ .. zephyr:code-sample:: usb-audio-headphones-microphone - :name: USB Audio microphone & headphones + :name: Legacy USB Audio microphone & headphones :relevant-api: _usb_device_core_api Implement a USB Audio microphone + headphones device with audio IN/OUT loopback. @@ -12,6 +12,9 @@ project. This very simple sample that performs loopback over IN/OUT ISO endpoints. The device will show up as two audio devices. One Input (Microphone) and one Output (Headphones) device. +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + Building and Running ******************** @@ -36,4 +39,4 @@ Steps to test the sample: - Verify the recorded audio stream. This sample can be found under -:zephyr_file:`samples/subsys/usb/audio/headphones_microphone` in the Zephyr project tree. +:zephyr_file:`samples/subsys/usb/legacy/audio_headphones_microphone` in the Zephyr project tree. diff --git a/samples/subsys/usb/audio/headphones_microphone/app.overlay b/samples/subsys/usb/legacy/audio_headphones_microphone/app.overlay similarity index 100% rename from samples/subsys/usb/audio/headphones_microphone/app.overlay rename to samples/subsys/usb/legacy/audio_headphones_microphone/app.overlay diff --git a/samples/subsys/usb/audio/headphones_microphone/prj.conf b/samples/subsys/usb/legacy/audio_headphones_microphone/prj.conf similarity index 100% rename from samples/subsys/usb/audio/headphones_microphone/prj.conf rename to samples/subsys/usb/legacy/audio_headphones_microphone/prj.conf diff --git a/samples/subsys/usb/legacy/audio_headphones_microphone/sample.yaml b/samples/subsys/usb/legacy/audio_headphones_microphone/sample.yaml new file mode 100644 index 0000000000000..8252eca3c6bbb --- /dev/null +++ b/samples/subsys/usb/legacy/audio_headphones_microphone/sample.yaml @@ -0,0 +1,10 @@ +sample: + name: USB audio Headphones Microphone sample +tests: + sample.usb.legacy.audio.headphones_microphone: + depends_on: usb_device + tags: usb + build_only: true + integration_platforms: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp diff --git a/samples/subsys/usb/audio/headphones_microphone/src/main.c b/samples/subsys/usb/legacy/audio_headphones_microphone/src/main.c similarity index 100% rename from samples/subsys/usb/audio/headphones_microphone/src/main.c rename to samples/subsys/usb/legacy/audio_headphones_microphone/src/main.c diff --git a/samples/subsys/usb/audio/headset/CMakeLists.txt b/samples/subsys/usb/legacy/audio_headset/CMakeLists.txt similarity index 100% rename from samples/subsys/usb/audio/headset/CMakeLists.txt rename to samples/subsys/usb/legacy/audio_headset/CMakeLists.txt diff --git a/samples/subsys/usb/audio/headset/README.rst b/samples/subsys/usb/legacy/audio_headset/README.rst similarity index 85% rename from samples/subsys/usb/audio/headset/README.rst rename to samples/subsys/usb/legacy/audio_headset/README.rst index e8986cc176bbe..7602a7751d2e8 100644 --- a/samples/subsys/usb/audio/headset/README.rst +++ b/samples/subsys/usb/legacy/audio_headset/README.rst @@ -1,5 +1,5 @@ .. zephyr:code-sample:: usb-audio-headset - :name: USB Audio headset + :name: Legacy USB Audio headset :relevant-api: _usb_device_core_api Implement a USB Audio headset device with audio IN/OUT loopback. @@ -11,6 +11,9 @@ This sample app demonstrates use of a USB Audio driver by the Zephyr project. This very simple sample that performs loopback over IN/OUT ISO endpoints. The device will show up as single audio device. +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + Building and Running ******************** @@ -35,4 +38,4 @@ Steps to test the sample: - Verify the recorded audio stream. This sample can be found under -:zephyr_file:`samples/subsys/usb/audio/headset` in the Zephyr project tree. +:zephyr_file:`samples/subsys/usb/legacy/audio_headset` in the Zephyr project tree. diff --git a/samples/subsys/usb/audio/headset/app.overlay b/samples/subsys/usb/legacy/audio_headset/app.overlay similarity index 100% rename from samples/subsys/usb/audio/headset/app.overlay rename to samples/subsys/usb/legacy/audio_headset/app.overlay diff --git a/samples/subsys/usb/audio/headset/prj.conf b/samples/subsys/usb/legacy/audio_headset/prj.conf similarity index 100% rename from samples/subsys/usb/audio/headset/prj.conf rename to samples/subsys/usb/legacy/audio_headset/prj.conf diff --git a/samples/subsys/usb/legacy/audio_headset/sample.yaml b/samples/subsys/usb/legacy/audio_headset/sample.yaml new file mode 100644 index 0000000000000..066c30e2aee9c --- /dev/null +++ b/samples/subsys/usb/legacy/audio_headset/sample.yaml @@ -0,0 +1,11 @@ +sample: + name: USB audio headset sample +tests: + sample.usb.legacy.audio.headset: + depends_on: usb_device + tags: usb + build_only: true + arch_exclude: posix + integration_platforms: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp diff --git a/samples/subsys/usb/audio/headset/src/main.c b/samples/subsys/usb/legacy/audio_headset/src/main.c similarity index 100% rename from samples/subsys/usb/audio/headset/src/main.c rename to samples/subsys/usb/legacy/audio_headset/src/main.c diff --git a/samples/subsys/usb/dfu-next/CMakeLists.txt b/samples/subsys/usb/legacy/cdc_acm/CMakeLists.txt similarity index 94% rename from samples/subsys/usb/dfu-next/CMakeLists.txt rename to samples/subsys/usb/legacy/cdc_acm/CMakeLists.txt index defe46f998fb6..c97b499076633 100644 --- a/samples/subsys/usb/dfu-next/CMakeLists.txt +++ b/samples/subsys/usb/legacy/cdc_acm/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(usb-dfu) +project(cdc_acm) include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) diff --git a/samples/subsys/usb/legacy/cdc_acm/README.rst b/samples/subsys/usb/legacy/cdc_acm/README.rst new file mode 100644 index 0000000000000..1e7a4d1530062 --- /dev/null +++ b/samples/subsys/usb/legacy/cdc_acm/README.rst @@ -0,0 +1,102 @@ +.. zephyr:code-sample:: legacy-usb-cdc-acm + :name: Legacy USB CDC ACM UART sample + :relevant-api: _usb_device_core_api uart_interface + + Use USB CDC ACM UART driver to implement a serial port echo. + +Overview +******** + +This sample app demonstrates use of a USB Communication Device Class (CDC) +Abstract Control Model (ACM) driver provided by the Zephyr project. +Received data from the serial port is echoed back to the same port +provided by this driver. + +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + +This sample can be found under :zephyr_file:`samples/subsys/usb/legacy/cdc_acm` in the +Zephyr project tree. + +Requirements +************ + +This project requires an USB device driver, which is available for multiple +boards supported in Zephyr. + +Building and Running +******************** + +Reel Board +=========== + +To see the console output of the app, open a serial port emulator and +attach it to the USB to TTL Serial cable. Build and flash the project: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/legacy/cdc_acm + :board: reel_board + :goals: flash + :compact: + +Running +======= + +Plug the board into a host device, for example, a PC running Linux. +The board will be detected as shown by the Linux dmesg command: + +.. code-block:: console + + usb 9-1: new full-speed USB device number 112 using uhci_hcd + usb 9-1: New USB device found, idVendor=8086, idProduct=f8a1 + usb 9-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + usb 9-1: Product: CDC-ACM + usb 9-1: Manufacturer: Intel + usb 9-1: SerialNumber: 00.01 + cdc_acm 9-1:1.0: ttyACM1: USB ACM device + +The app prints on serial output (UART1), used for the console: + +.. code-block:: console + + Wait for DTR + +Open a serial port emulator, for example minicom +and attach it to detected CDC ACM device: + +.. code-block:: console + + minicom --device /dev/ttyACM1 + +The app should respond on serial output with: + +.. code-block:: console + + DTR set, start test + Baudrate detected: 115200 + +And on ttyACM device, provided by zephyr USB device stack: + +.. code-block:: console + + Send characters to the UART device + Characters read: + +The characters entered in serial port emulator will be echoed back. + +Troubleshooting +=============== + +If the ModemManager runs on your operating system, it will try +to access the CDC ACM device and maybe you can see several characters +including "AT" on the terminal attached to the CDC ACM device. +You can add or extend the udev rule for your board to inform +ModemManager to skip the CDC ACM device. +For this example, it would look like this: + +.. code-block:: none + + ATTRS{idVendor}=="8086" ATTRS{idProduct}=="f8a1", ENV{ID_MM_DEVICE_IGNORE}="1" + +You can use +``/lib/udev/rules.d/77-mm-usb-device-blacklist.rules`` as reference. diff --git a/samples/subsys/usb/legacy/cdc_acm/app.overlay b/samples/subsys/usb/legacy/cdc_acm/app.overlay new file mode 100644 index 0000000000000..c50d0fd9d69e7 --- /dev/null +++ b/samples/subsys/usb/legacy/cdc_acm/app.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&zephyr_udc0 { + cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; diff --git a/samples/subsys/usb/legacy/cdc_acm/prj.conf b/samples/subsys/usb/legacy/cdc_acm/prj.conf new file mode 100644 index 0000000000000..55e4fe9217fb5 --- /dev/null +++ b/samples/subsys/usb/legacy/cdc_acm/prj.conf @@ -0,0 +1,11 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC ACM sample" +CONFIG_USB_DEVICE_PID=0x0001 +CONFIG_LOG=y +CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y +CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n diff --git a/samples/subsys/usb/legacy/cdc_acm/sample.yaml b/samples/subsys/usb/legacy/cdc_acm/sample.yaml new file mode 100644 index 0000000000000..b61deab71ff2d --- /dev/null +++ b/samples/subsys/usb/legacy/cdc_acm/sample.yaml @@ -0,0 +1,7 @@ +sample: + name: CDC ACM USB +tests: + sample.usb.legacy.cdc-acm: + depends_on: usb_device + tags: usb + build_only: true diff --git a/samples/subsys/usb/legacy/cdc_acm/src/main.c b/samples/subsys/usb/legacy/cdc_acm/src/main.c new file mode 100644 index 0000000000000..d06161f0f5ca4 --- /dev/null +++ b/samples/subsys/usb/legacy/cdc_acm/src/main.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +LOG_MODULE_REGISTER(cdc_acm_echo, LOG_LEVEL_INF); + +const struct device *const uart_dev = DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart); + +#define RING_BUF_SIZE 1024 +uint8_t ring_buffer[RING_BUF_SIZE]; + +struct ring_buf ringbuf; + +static bool rx_throttled; + +static inline void print_baudrate(const struct device *dev) +{ + uint32_t baudrate; + int ret; + + ret = uart_line_ctrl_get(dev, UART_LINE_CTRL_BAUD_RATE, &baudrate); + if (ret) { + LOG_WRN("Failed to get baudrate, ret code %d", ret); + } else { + LOG_INF("Baudrate %u", baudrate); + } +} + +static void interrupt_handler(const struct device *dev, void *user_data) +{ + ARG_UNUSED(user_data); + + while (uart_irq_update(dev) && uart_irq_is_pending(dev)) { + if (!rx_throttled && uart_irq_rx_ready(dev)) { + int recv_len, rb_len; + uint8_t buffer[64]; + size_t len = MIN(ring_buf_space_get(&ringbuf), + sizeof(buffer)); + + if (len == 0) { + /* Throttle because ring buffer is full */ + uart_irq_rx_disable(dev); + rx_throttled = true; + continue; + } + + recv_len = uart_fifo_read(dev, buffer, len); + if (recv_len < 0) { + LOG_ERR("Failed to read UART FIFO"); + recv_len = 0; + }; + + rb_len = ring_buf_put(&ringbuf, buffer, recv_len); + if (rb_len < recv_len) { + LOG_ERR("Drop %u bytes", recv_len - rb_len); + } + + LOG_DBG("tty fifo -> ringbuf %d bytes", rb_len); + if (rb_len) { + uart_irq_tx_enable(dev); + } + } + + if (uart_irq_tx_ready(dev)) { + uint8_t buffer[64]; + int rb_len, send_len; + + rb_len = ring_buf_get(&ringbuf, buffer, sizeof(buffer)); + if (!rb_len) { + LOG_DBG("Ring buffer empty, disable TX IRQ"); + uart_irq_tx_disable(dev); + continue; + } + + if (rx_throttled) { + uart_irq_rx_enable(dev); + rx_throttled = false; + } + + send_len = uart_fifo_fill(dev, buffer, rb_len); + if (send_len < rb_len) { + LOG_ERR("Drop %d bytes", rb_len - send_len); + } + + LOG_DBG("ringbuf -> tty fifo %d bytes", send_len); + } + } +} + +int main(void) +{ + int ret; + + if (!device_is_ready(uart_dev)) { + LOG_ERR("CDC ACM device not ready"); + return 0; + } + + ret = usb_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable USB"); + return 0; + } + + ring_buf_init(&ringbuf, sizeof(ring_buffer), ring_buffer); + + LOG_INF("Wait for DTR"); + + while (true) { + uint32_t dtr = 0U; + + uart_line_ctrl_get(uart_dev, UART_LINE_CTRL_DTR, &dtr); + if (dtr) { + break; + } + + k_sleep(K_MSEC(100)); + } + + LOG_INF("DTR set"); + + /* They are optional, we use them to test the interrupt endpoint */ + ret = uart_line_ctrl_set(uart_dev, UART_LINE_CTRL_DCD, 1); + if (ret) { + LOG_WRN("Failed to set DCD, ret code %d", ret); + } + + ret = uart_line_ctrl_set(uart_dev, UART_LINE_CTRL_DSR, 1); + if (ret) { + LOG_WRN("Failed to set DSR, ret code %d", ret); + } + + /* Wait 100ms for the host to do all settings */ + k_msleep(100); + + print_baudrate(uart_dev); + + uart_irq_callback_set(uart_dev, interrupt_handler); + /* Enable rx interrupts */ + uart_irq_rx_enable(uart_dev); + + return 0; +} diff --git a/samples/subsys/usb/legacy/dfu/CMakeLists.txt b/samples/subsys/usb/legacy/dfu/CMakeLists.txt new file mode 100644 index 0000000000000..2da1508d6a1e1 --- /dev/null +++ b/samples/subsys/usb/legacy/dfu/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(dfu) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/legacy/dfu/README.rst b/samples/subsys/usb/legacy/dfu/README.rst new file mode 100644 index 0000000000000..2a06eeb5cdda7 --- /dev/null +++ b/samples/subsys/usb/legacy/dfu/README.rst @@ -0,0 +1,160 @@ +.. zephyr:code-sample:: legacy-usb-dfu + :name: Legacy USB DFU (Device Firmware Upgrade) + :relevant-api: _usb_device_core_api + + Implement device firmware upgrade using the USB DFU class driver. + +Overview +******** + +This sample app demonstrates use of a USB DFU Class driver provided +by the Zephyr project. + +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + +Requirements +************ + +This project requires an USB device driver. Currently, the USB DFU +class provided by the Zephyr project depends on DFU image manager and +partition layout. Refer to :ref:`flash_map_api` for details about +partition layout. You SoC must run MCUboot as the stage 1 bootloader. +This sample is built as an application for the MCUboot bootloader. + +.. note:: + This example explicitly turns :kconfig:option:`CONFIG_USB_DFU_ENABLE_UPLOAD` on. + +Building and Testing +******************** + +Building and signing the application +==================================== + +This sample can be built in the usual way (see :ref:`build_an_application` +for more details) and flashed with regular flash tools, but will need +to be loaded at the offset of SLOT-0. + +Application images (such as this sample) must be signed. +The build system can do this for you by setting the :kconfig:option:`CONFIG_MCUBOOT_SIGNATURE_KEY_FILE` symbol. + +For example: + +.. code-block:: console + + west build -b nrf52840dk/nrf52840 zephyr/samples/subsys/usb/legacy/dfu -d build-dfu -- \ + -DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE=\"bootloader/mcuboot/root-rsa-2048.pem\" + +Build and flash MCUboot bootloader for Zephyr project as it is described in +the `Using MCUboot with Zephyr`_ documentation. Then build, sign and flash +the USB DFU sample at the offset of SLOT-0. + +Build and sign a second application image e.g. :zephyr:code-sample:`hello_world`, +which will be used as an image for the update. +Do not forget to enable the required :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` option (as described +in :ref:`mcuboot`). For example: + +.. code-block:: console + + west build -b nrf52840dk/nrf52840 zephyr/samples/hello_world -d build-hello_world -- \ + -DCONFIG_BOOTLOADER_MCUBOOT=y '-DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE="bootloader/mcuboot/root-rsa-2048.pem"' + +Testing +======= + +The Linux ``dfu-util`` tool can be used to backup or update the application +image. + +Use the following command to backup the SLOT-0 image: + +.. code-block:: console + + dfu-util --alt 0 --upload slot0_backup.bin + +Use the following command to update the application: + +.. code-block:: console + + dfu-util --alt 1 --download build-hello_world/zephyr/zephyr.signed.bin + +Reset the SoC. MCUboot boot will swap the images and boot the new application, +showing this output to the console: + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.0.0-360-gc0dd594d4d3d *** + I: Starting bootloader + I: Primary image: magic=good, swap_type=0x3, copy_done=0x1, image_ok=0x1 + I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3 + I: Boot source: none + I: Swap type: test + I: Bootloader chainload address offset: 0xc000 + I: Jumping to the first image slot + *** Booting Zephyr OS build zephyr-v3.0.0-361-gb987e6daa2f9 *** + Hello World! nrf52840dk + + +Reset the SoC again and MCUboot should revert the images and boot +USB DFU sample, showing this output to the console: + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.0.0-360-gc0dd594d4d3d *** + I: Starting bootloader + I: Primary image: magic=good, swap_type=0x2, copy_done=0x1, image_ok=0x3 + I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 + I: Boot source: none + I: Swap type: revert + I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 + I: Bootloader chainload address offset: 0xc000 + I: Jumping to the first image slot + *** Booting Zephyr OS build zephyr-v3.0.0-361-gb987e6daa2f9 *** + [00:00:00.005,920] main: This device supports USB DFU class. + +Permanent download and automatic reboot +======================================= + +There are some symbols that can be used to enable a hands free download: + +To mark SLOT-1 as permanent after the download completes, +enable the :kconfig:option:`CONFIG_USB_DFU_PERMANENT_DOWNLOAD` symbol. + +To automatically reboot after the download completes, +enable the :kconfig:option:`CONFIG_USB_DFU_REBOOT` symbol. + +.. warning:: + Enabling :kconfig:option:`CONFIG_USB_DFU_PERMANENT_DOWNLOAD` can lead to a bricked device! + Make sure there is another way to download firmware. + For example via a debugger or Mcuboot's recovery mode. + +Both symbols can be enabled with the :file:`overlay-permanent-download.conf` overlay. For example: + +.. code-block:: console + + west build -b nrf52840dk/nrf52840 zephyr/samples/subsys/usb/legacy/dfu -d build-dfu -- \ + -DCONFIG_BOOTLOADER_MCUBOOT=y '-DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE="bootloader/mcuboot/root-rsa-2048.pem"' \ + -DEXTRA_CONF_FILE=overlay-permanent-download.conf + + +The listing below shows the output to the console when downloading via dfu-util. +Note the ``Swap type: perm``. + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.0.0-361-ge6900e2451d5 *** + [00:00:00.005,920] main: This device supports USB DFU class. + + *** Booting Zephyr OS build zephyr-v3.0.0-360-gc0dd594d4d3d *** + I: Starting bootloader + I: Primary image: magic=good, swap_type=0x4, copy_done=0x1, image_ok=0x1 + I: Secondary image: magic=good, swap_type=0x3, copy_done=0x3, image_ok=0x1 + I: Boot source: none + I: Swap type: perm + I: Bootloader chainload address offset: 0xc000 + I: Jumping to the first image slot + *** Booting Zephyr OS build zephyr-v3.0.0-361-gb987e6daa2f9 *** + Hello World! nrf52840dk + + +.. _MCUboot GitHub repo: https://github.com/zephyrproject-rtos/mcuboot +.. _Using MCUboot with Zephyr: https://docs.mcuboot.com/readme-zephyr diff --git a/samples/subsys/usb/dfu/overlay-permanent-download.conf b/samples/subsys/usb/legacy/dfu/overlay-permanent-download.conf similarity index 100% rename from samples/subsys/usb/dfu/overlay-permanent-download.conf rename to samples/subsys/usb/legacy/dfu/overlay-permanent-download.conf diff --git a/samples/subsys/usb/legacy/dfu/prj.conf b/samples/subsys/usb/legacy/dfu/prj.conf new file mode 100644 index 0000000000000..6bf6f1ee310b5 --- /dev/null +++ b/samples/subsys/usb/legacy/dfu/prj.conf @@ -0,0 +1,16 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_GPIO=y +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr DFU sample" +CONFIG_USB_DEVICE_PID=0x0005 +CONFIG_USB_DFU_CLASS=y +CONFIG_USB_DFU_ENABLE_UPLOAD=y +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_STREAM_FLASH=y +CONFIG_IMG_MANAGER=y +CONFIG_LOG=y +CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y +CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n diff --git a/samples/subsys/usb/legacy/dfu/sample.yaml b/samples/subsys/usb/legacy/dfu/sample.yaml new file mode 100644 index 0000000000000..f3ed333784247 --- /dev/null +++ b/samples/subsys/usb/legacy/dfu/sample.yaml @@ -0,0 +1,16 @@ +sample: + name: USB DFU sample + +common: + build_only: true + arch_exclude: posix + depends_on: usb_device + platform_allow: + - nrf52840dk/nrf52840 + - frdm_k64f +tests: + sample.usb.legacy.dfu: + tags: usb + sample.usb.legacy.dfu.permanent.download: + tags: usb + extra_args: EXTRA_CONF_FILE=overlay-permanent-download.conf diff --git a/samples/subsys/usb/legacy/dfu/src/main.c b/samples/subsys/usb/legacy/dfu/src/main.c new file mode 100644 index 0000000000000..2c10c2e65ff03 --- /dev/null +++ b/samples/subsys/usb/legacy/dfu/src/main.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2017 Phytec Messtechnik GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Sample app for USB DFU class driver. */ + +#include +#include +#include +LOG_MODULE_REGISTER(main); + +int main(void) +{ + int ret; + + ret = usb_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable USB"); + return 0; + } + + LOG_INF("This device supports USB DFU class.\n"); + return 0; +} diff --git a/samples/subsys/usb/legacy/hci_usb/CMakeLists.txt b/samples/subsys/usb/legacy/hci_usb/CMakeLists.txt new file mode 100644 index 0000000000000..714d9c369a57e --- /dev/null +++ b/samples/subsys/usb/legacy/hci_usb/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hci_usb) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/usb/legacy/hci_usb/README.rst b/samples/subsys/usb/legacy/hci_usb/README.rst new file mode 100644 index 0000000000000..77d43d7815f14 --- /dev/null +++ b/samples/subsys/usb/legacy/hci_usb/README.rst @@ -0,0 +1,22 @@ +.. zephyr:code-sample:: legacy_bluetooth_hci_usb + :name: Legacy HCI USB + :relevant-api: hci_raw bluetooth _usb_device_core_api + + Turn a Zephyr board into a USB Bluetooth dongle (compatible with all operating systems). + +Overview +******** + +Make a USB Bluetooth dongle out of Zephyr. Requires USB device support from the +board it runs on (e.g. :ref:`nrf52840dk_nrf52840` supports both Bluetooth LE and USB). + +Requirements +************ + +* Bluetooth stack running on the host (e.g. BlueZ) +* A board with Bluetooth and USB support in Zephyr + +Building and Running +******************** +This sample can be found under :zephyr_file:`samples/subsys/usb/legacy/hci_usb` in the +Zephyr tree. diff --git a/samples/subsys/usb/legacy/hci_usb/prj.conf b/samples/subsys/usb/legacy/hci_usb/prj.conf new file mode 100644 index 0000000000000..0f809e424d6dc --- /dev/null +++ b/samples/subsys/usb/legacy/hci_usb/prj.conf @@ -0,0 +1,17 @@ +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y + +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PID=0x000B +CONFIG_USB_DEVICE_BLUETOOTH=y +CONFIG_USB_DEVICE_BLUETOOTH_VS_H4=n +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +# We dont want any console or CDC ACM that may cause BlueZ to not detect hci_usb +CONFIG_SERIAL=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 diff --git a/samples/subsys/usb/legacy/hci_usb/sample.yaml b/samples/subsys/usb/legacy/hci_usb/sample.yaml new file mode 100644 index 0000000000000..3eccaaf62c961 --- /dev/null +++ b/samples/subsys/usb/legacy/hci_usb/sample.yaml @@ -0,0 +1,11 @@ +sample: + name: Bluetooth over USB sample +tests: + sample.bluetooth.hci_usb.legacy: + depends_on: + - usb_device + - ble + build_only: true + tags: + - usb + - bluetooth diff --git a/samples/subsys/usb/legacy/hci_usb/src/main.c b/samples/subsys/usb/legacy/hci_usb/src/main.c new file mode 100644 index 0000000000000..a002f2dd2d4b8 --- /dev/null +++ b/samples/subsys/usb/legacy/hci_usb/src/main.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +int main(void) +{ + int ret; + + ret = usb_enable(NULL); + if (ret != 0) { + printk("Failed to enable USB"); + return 0; + } + + printk("Bluetooth over USB sample\n"); + return 0; +} diff --git a/samples/subsys/usb/webusb-next/CMakeLists.txt b/samples/subsys/usb/legacy/hid-mouse/CMakeLists.txt similarity index 93% rename from samples/subsys/usb/webusb-next/CMakeLists.txt rename to samples/subsys/usb/legacy/hid-mouse/CMakeLists.txt index 97a240805ee9e..d2217c00a4727 100644 --- a/samples/subsys/usb/webusb-next/CMakeLists.txt +++ b/samples/subsys/usb/legacy/hid-mouse/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(webusb) +project(hid-mouse) include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) diff --git a/samples/subsys/usb/legacy/hid-mouse/README.rst b/samples/subsys/usb/legacy/hid-mouse/README.rst new file mode 100644 index 0000000000000..aa82e23804a1c --- /dev/null +++ b/samples/subsys/usb/legacy/hid-mouse/README.rst @@ -0,0 +1,114 @@ +.. zephyr:code-sample:: legacy-usb-hid-mouse + :name: Legacy USB HID mouse + :relevant-api: _usb_device_core_api usb_hid_device_api input_interface + + Implement a basic HID mouse device. + +Overview +******** + +This sample app demonstrates use of a USB Human Interface Device (HID) driver +by the Zephyr project. This very simple driver enumerates a board with a button +into a mouse that has a left mouse button and optionally (depending on +the number of buttons on the board) a right mouse button, X-axis movement, +and Y-axis movement. +If the USB peripheral driver supports remote wakeup feature, wakeup request +will be performed on every button click if the bus is in suspended state. +This sample can be found under :zephyr_file:`samples/subsys/usb/legacy/hid-mouse` in the +Zephyr project tree. + +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + +Requirements +************ + +This project requires an USB device driver and uses the :ref:`input` API. +There must be a :dtcompatible:`gpio-keys` group of buttons or keys defined at +the board level that can generate input events, otherwise the example will build +but not work as expected. + +The key mapping in the sample is as follows: + +- ``INPUT_KEY_0``: left button +- ``INPUT_KEY_1``: right button +- ``INPUT_KEY_2``: move the mouse along the x-axis +- ``INPUT_KEY_3``: move the mouse along the y-axis + +An LED must also be configured via the ``led0`` devicetree alias. You may also +see this error if you try to build this sample for an unsupported board: + +.. code-block:: none + + Unsupported board: led0 devicetree alias is not defined + +Building and Running +******************** + +This sample can be built for multiple boards, in this example we will build it +for the nucleo_f070rb board: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/legacy/hid-mouse + :board: nucleo_f070rb + :goals: build + :compact: + +After you have built and flashed the sample app image to your board, plug the +board into a host device, for example, a PC running Linux. +The board will be detected as shown by the Linux dmesg command: + +.. code-block:: console + + dmesg | tail -10 + usb 2-2: new full-speed USB device number 2 using at91_ohci + usb 2-2: New USB device found, idVendor=2fe3, idProduct=0007, bcdDevice= 2.03 + usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + usb 2-2: Product: Zephyr HID mouse sample + usb 2-2: Manufacturer: ZEPHYR + usb 2-2: SerialNumber: 86FE679A598AC47A + input: ZEPHYR Zephyr HID mouse sample as /devices/soc0/ahb/600000.ohci/usb2/2-2/2-2:1.0/0003:2FE3:0100.0001/input/input0 + hid-generic 0003:2FE3:0100.0001: input: USB HID v1.10 Mouse [ZEPHYR Zephyr HID mouse sample] on usb-at91-2/input0 + +You can also monitor mouse events by using the standard Linux ``evtest`` command +(see the `Ubuntu evtest man page`_ for more information about this tool): + +.. _Ubuntu evtest man page: + http://manpages.ubuntu.com/manpages/trusty/man1/evtest.1.html + +.. code-block:: console + + sudo evtest /dev/input/event0 + Input driver version is 1.0.1 + Input device ID: bus 0x3 vendor 0x2fe3 product 0x7 version 0x110 + Input device name: "ZEPHYR Zephyr HID mouse sample" + Supported events: + Event type 0 (EV_SYN) + Event type 1 (EV_KEY) + Event code 272 (BTN_LEFT) + Event code 273 (BTN_RIGHT) + Event code 274 (BTN_MIDDLE) + Event type 2 (EV_REL) + Event code 0 (REL_X) + Event code 1 (REL_Y) + Event code 8 (REL_WHEEL) + Event type 4 (EV_MSC) + Event code 4 (MSC_SCAN) + Properties: + Testing ... (interrupt to exit) + +When you press the button on your board, it will act as if the left +mouse button was pressed, and this information will be displayed +by ``evtest``: + +.. code-block:: console + + Event: time 1167609663.618515, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001 + Event: time 1167609663.618515, type 1 (EV_KEY), code 272 (BTN_LEFT), value 1 + Event: time 1167609663.618515, -------------- SYN_REPORT ------------ + Event: time 1167609663.730510, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001 + Event: time 1167609663.730510, type 1 (EV_KEY), code 272 (BTN_LEFT), value 0 + Event: time 1167609663.730510, -------------- SYN_REPORT ------------ + +If your board has more than one button, they will act as right mouse button, +X-axis movement, and Y-axis movement. diff --git a/samples/subsys/usb/legacy/hid-mouse/prj.conf b/samples/subsys/usb/legacy/hid-mouse/prj.conf new file mode 100644 index 0000000000000..b797a7382e814 --- /dev/null +++ b/samples/subsys/usb/legacy/hid-mouse/prj.conf @@ -0,0 +1,13 @@ +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_HID=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr HID mouse sample" +CONFIG_USB_DEVICE_PID=0x0007 +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +CONFIG_LOG=y +CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y +CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y + +CONFIG_GPIO=y +CONFIG_INPUT=y +CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/samples/subsys/usb/legacy/hid-mouse/sample.yaml b/samples/subsys/usb/legacy/hid-mouse/sample.yaml new file mode 100644 index 0000000000000..4dc2da9079883 --- /dev/null +++ b/samples/subsys/usb/legacy/hid-mouse/sample.yaml @@ -0,0 +1,15 @@ +sample: + name: USB HID mouse sample +common: + harness: button + filter: dt_alias_exists("sw0") and dt_alias_exists("led0") + depends_on: + - gpio +tests: + sample.usb.legacy.hid-mouse: + depends_on: + - usb_device + build_only: true + platform_exclude: + - frdm_mcxn947/mcxn947/cpu0 + tags: usb diff --git a/samples/subsys/usb/legacy/hid-mouse/src/main.c b/samples/subsys/usb/legacy/hid-mouse/src/main.c new file mode 100644 index 0000000000000..e3ddce5cbcc82 --- /dev/null +++ b/samples/subsys/usb/legacy/hid-mouse/src/main.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2018 qianfan Zhao + * Copyright (c) 2018, 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); + +static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); +static const uint8_t hid_report_desc[] = HID_MOUSE_REPORT_DESC(2); +static enum usb_dc_status_code usb_status; + +#define MOUSE_BTN_LEFT 0 +#define MOUSE_BTN_RIGHT 1 + +enum mouse_report_idx { + MOUSE_BTN_REPORT_IDX = 0, + MOUSE_X_REPORT_IDX = 1, + MOUSE_Y_REPORT_IDX = 2, + MOUSE_WHEEL_REPORT_IDX = 3, + MOUSE_REPORT_COUNT = 4, +}; + +K_MSGQ_DEFINE(mouse_msgq, MOUSE_REPORT_COUNT, 2, 1); +static K_SEM_DEFINE(ep_write_sem, 0, 1); + +static inline void status_cb(enum usb_dc_status_code status, const uint8_t *param) +{ + usb_status = status; +} + +static ALWAYS_INLINE void rwup_if_suspended(void) +{ + if (IS_ENABLED(CONFIG_USB_DEVICE_REMOTE_WAKEUP)) { + if (usb_status == USB_DC_SUSPEND) { + usb_wakeup_request(); + return; + } + } +} + +static void input_cb(struct input_event *evt, void *user_data) +{ + static uint8_t tmp[MOUSE_REPORT_COUNT]; + + ARG_UNUSED(user_data); + + switch (evt->code) { + case INPUT_KEY_0: + rwup_if_suspended(); + WRITE_BIT(tmp[MOUSE_BTN_REPORT_IDX], MOUSE_BTN_LEFT, evt->value); + break; + case INPUT_KEY_1: + rwup_if_suspended(); + WRITE_BIT(tmp[MOUSE_BTN_REPORT_IDX], MOUSE_BTN_RIGHT, evt->value); + break; + case INPUT_KEY_2: + if (evt->value) { + tmp[MOUSE_X_REPORT_IDX] += 10U; + } + + break; + case INPUT_KEY_3: + if (evt->value) { + tmp[MOUSE_Y_REPORT_IDX] += 10U; + } + + break; + default: + LOG_INF("Unrecognized input code %u value %d", + evt->code, evt->value); + return; + } + + if (k_msgq_put(&mouse_msgq, tmp, K_NO_WAIT) != 0) { + LOG_ERR("Failed to put new input event"); + } + + tmp[MOUSE_X_REPORT_IDX] = 0U; + tmp[MOUSE_Y_REPORT_IDX] = 0U; + +} + +INPUT_CALLBACK_DEFINE(NULL, input_cb, NULL); + +static void int_in_ready_cb(const struct device *dev) +{ + ARG_UNUSED(dev); + k_sem_give(&ep_write_sem); +} + +static const struct hid_ops ops = { + .int_in_ready = int_in_ready_cb, +}; + +int main(void) +{ + const struct device *hid_dev; + int ret; + + if (!gpio_is_ready_dt(&led0)) { + LOG_ERR("LED device %s is not ready", led0.port->name); + return 0; + } + + hid_dev = device_get_binding("HID_0"); + if (hid_dev == NULL) { + LOG_ERR("Cannot get USB HID Device"); + return 0; + } + + ret = gpio_pin_configure_dt(&led0, GPIO_OUTPUT); + if (ret < 0) { + LOG_ERR("Failed to configure the LED pin, error: %d", ret); + return 0; + } + + usb_hid_register_device(hid_dev, + hid_report_desc, sizeof(hid_report_desc), + &ops); + + usb_hid_init(hid_dev); + + ret = usb_enable(status_cb); + if (ret != 0) { + LOG_ERR("Failed to enable USB"); + return 0; + } + + while (true) { + UDC_STATIC_BUF_DEFINE(report, MOUSE_REPORT_COUNT); + + k_msgq_get(&mouse_msgq, &report, K_FOREVER); + + ret = hid_int_ep_write(hid_dev, report, MOUSE_REPORT_COUNT, NULL); + if (ret) { + LOG_ERR("HID write error, %d", ret); + } else { + k_sem_take(&ep_write_sem, K_FOREVER); + /* Toggle LED on sent report */ + (void)gpio_pin_toggle(led0.port, led0.pin); + } + } + return 0; +} diff --git a/samples/subsys/usb/legacy/legacy.rst b/samples/subsys/usb/legacy/legacy.rst new file mode 100644 index 0000000000000..1eeac67d58df6 --- /dev/null +++ b/samples/subsys/usb/legacy/legacy.rst @@ -0,0 +1,12 @@ +.. zephyr:code-sample-category:: usb_legacy + :name: Legacy USB device support + + These samples demonstrate the use of legacy USB device support in Zephyr RTOS. + +.. note:: + These samples use a legacy :ref:`usb_device_stack` that is in the + deprecation process. + +.. zephyr:code-sample-listing:: + :categories: usb_legacy + :live-search: diff --git a/samples/subsys/usb/legacy/mass/CMakeLists.txt b/samples/subsys/usb/legacy/mass/CMakeLists.txt new file mode 100644 index 0000000000000..bbeec829616ad --- /dev/null +++ b/samples/subsys/usb/legacy/mass/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(mass) + +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +endif() diff --git a/samples/subsys/usb/legacy/mass/README.rst b/samples/subsys/usb/legacy/mass/README.rst new file mode 100644 index 0000000000000..8e3ae5319df61 --- /dev/null +++ b/samples/subsys/usb/legacy/mass/README.rst @@ -0,0 +1,32 @@ +.. zephyr:code-sample:: legacy-usb-mass + :name: Legacy USB Mass Storage + :relevant-api: _usb_device_core_api + + Expose board's RAM as a USB disk using USB Mass Storage driver. + +Overview +******** + +This sample app demonstrates use of a USB Mass Storage driver by the Zephyr +project. This very simple driver enumerates a board with RAM disk into an USB +disk. This sample can be found under +:zephyr_file:`samples/subsys/usb/legacy/mass` in the Zephyr project tree. + +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + +Requirements +************ + +This project requires a USB device driver, and either 96KiB of RAM or a FLASH device. + +Building and Running +******************** + +The configurations selects RAM-based disk without any file system. + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/legacy/mass + :board: reel_board + :goals: build + :compact: diff --git a/samples/subsys/usb/legacy/mass/app.overlay b/samples/subsys/usb/legacy/mass/app.overlay new file mode 100644 index 0000000000000..ff09a0f8ca73e --- /dev/null +++ b/samples/subsys/usb/legacy/mass/app.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <192>; + }; +}; diff --git a/samples/subsys/usb/legacy/mass/prj.conf b/samples/subsys/usb/legacy/mass/prj.conf new file mode 100644 index 0000000000000..0954afcd0eec0 --- /dev/null +++ b/samples/subsys/usb/legacy/mass/prj.conf @@ -0,0 +1,14 @@ +CONFIG_STDOUT_CONSOLE=y + +#USB related configs +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr MSC sample" +CONFIG_USB_DEVICE_PID=0x0008 +CONFIG_LOG=y +CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y +CONFIG_USB_MASS_STORAGE=y +CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y +CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +CONFIG_MAIN_STACK_SIZE=1536 diff --git a/samples/subsys/usb/legacy/mass/sample.yaml b/samples/subsys/usb/legacy/mass/sample.yaml new file mode 100644 index 0000000000000..f4d1bb2f96d98 --- /dev/null +++ b/samples/subsys/usb/legacy/mass/sample.yaml @@ -0,0 +1,10 @@ +sample: + name: Mass Storage +tests: + sample.usb.legacy.mass_ram_none: + min_ram: 128 + depends_on: usb_device + build_only: true + arch_exclude: posix + tags: + - usb diff --git a/samples/subsys/usb/legacy/mass/src/main.c b/samples/subsys/usb/legacy/mass/src/main.c new file mode 100644 index 0000000000000..52dfa00294ef2 --- /dev/null +++ b/samples/subsys/usb/legacy/mass/src/main.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2019-2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); + +int main(void) +{ + int ret; + + ret = usb_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable USB"); + return 0; + } + + LOG_INF("The device is put in USB mass storage mode"); + + return 0; +} diff --git a/samples/subsys/usb/legacy/netusb/CMakeLists.txt b/samples/subsys/usb/legacy/netusb/CMakeLists.txt new file mode 100644 index 0000000000000..0fc0cebeb6027 --- /dev/null +++ b/samples/subsys/usb/legacy/netusb/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(zperf) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/usb/legacy/netusb/README.rst b/samples/subsys/usb/legacy/netusb/README.rst new file mode 100644 index 0000000000000..4c5143559019c --- /dev/null +++ b/samples/subsys/usb/legacy/netusb/README.rst @@ -0,0 +1,32 @@ +.. zephyr:code-sample:: legacy-netusb + :name: Legacy USB device netusb sample + :relevant-api: net_config _usb_device_core_api + + Use USB CDC EEM/ECM or RNDIS implementation + +Overview +******** + +Use the USB CDC EEM/ECM or RNDIS implementation to establish a network +connection to a device running the Zephyr RTOS. + +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + +This sample can be found under :zephyr_file:`samples/subsys/usb/legacy/netusb` in the +Zephyr project tree. + +Requirements +************ + +This project requires an USB device driver, which is available for multiple +boards supported in Zephyr. + +Building and Running +******************** + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/legacy/netusb + :board: reel_board + :goals: flash + :compact: diff --git a/samples/subsys/usb/legacy/netusb/prj.conf b/samples/subsys/usb/legacy/netusb/prj.conf new file mode 100644 index 0000000000000..14f069dc80327 --- /dev/null +++ b/samples/subsys/usb/legacy/netusb/prj.conf @@ -0,0 +1,33 @@ +CONFIG_NETWORKING=y +CONFIG_NET_LOG=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_UDP=y + +CONFIG_NET_PKT_RX_COUNT=40 +CONFIG_NET_PKT_TX_COUNT=40 +CONFIG_NET_BUF_RX_COUNT=160 +CONFIG_NET_BUF_TX_COUNT=160 +CONFIG_NET_BUF_DATA_SIZE=256 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5 +CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1 +CONFIG_NET_MAX_CONTEXTS=5 +CONFIG_NET_TC_TX_COUNT=1 +CONFIG_POSIX_API=y + +CONFIG_INIT_STACKS=y +CONFIG_TEST_RANDOM_GENERATOR=y + +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_CONFIG_SETTINGS=y +CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" + +CONFIG_LOG=y +CONFIG_SHELL_CMDS_RESIZE=n + +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_NETWORK_ECM=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n diff --git a/samples/subsys/usb/legacy/netusb/sample.yaml b/samples/subsys/usb/legacy/netusb/sample.yaml new file mode 100644 index 0000000000000..2ef97e764a83e --- /dev/null +++ b/samples/subsys/usb/legacy/netusb/sample.yaml @@ -0,0 +1,26 @@ +common: + tags: + - net + - usb + min_ram: 192 + depends_on: usb_device + build_only: true + platform_exclude: + - native_sim + - native_sim/native/64 +sample: + description: Samples for legacy CDC ECM, CDC EEM, RNDIS functions + name: Legacy ECM EEM RNDIS +tests: + sample.usb.legacy.cdc_ecm: + extra_configs: + - CONFIG_USB_DEVICE_NETWORK_ECM=y + - CONFIG_USB_DEVICE_NETWORK_EEM=n + sample.usb.legacy.cdc_eem: + extra_configs: + - CONFIG_USB_DEVICE_NETWORK_ECM=n + - CONFIG_USB_DEVICE_NETWORK_EEM=y + sample.usb.legacy.rndis: + extra_configs: + - CONFIG_USB_DEVICE_NETWORK_ECM=n + - CONFIG_USB_DEVICE_NETWORK_RNDIS=y diff --git a/samples/net/sockets/http_server/src/usb.c b/samples/subsys/usb/legacy/netusb/src/main.c similarity index 54% rename from samples/net/sockets/http_server/src/usb.c rename to samples/subsys/usb/legacy/netusb/src/main.c index 0f7c98f82db54..f4989dbbbde93 100644 --- a/samples/net/sockets/http_server/src/usb.c +++ b/samples/subsys/usb/legacy/netusb/src/main.c @@ -1,23 +1,19 @@ /* - * Copyright (c) 2024, Nordic Semiconductor + * Copyright (c) 2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -#include -LOG_MODULE_DECLARE(net_http_server_sample, LOG_LEVEL_DBG); - #include #include -int init_usb(void) +int main(void) { int ret; ret = usb_enable(NULL); if (ret != 0) { - LOG_ERR("Cannot enable USB (%d)", ret); - return ret; + printk("usb enable error %d\n", ret); } (void)net_config_init_app(NULL, "Initializing network"); diff --git a/samples/subsys/usb/legacy/webusb/CMakeLists.txt b/samples/subsys/usb/legacy/webusb/CMakeLists.txt new file mode 100644 index 0000000000000..fbac52a732ef8 --- /dev/null +++ b/samples/subsys/usb/legacy/webusb/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(webusb) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/usb) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/legacy/webusb/README.rst b/samples/subsys/usb/legacy/webusb/README.rst new file mode 100644 index 0000000000000..ab187b35bb03d --- /dev/null +++ b/samples/subsys/usb/legacy/webusb/README.rst @@ -0,0 +1,94 @@ +.. zephyr:code-sample:: legacy-webusb + :name: Legacy WebUSB + :relevant-api: _usb_device_core_api + + Receive and echo data from a web page using WebUSB API. + +For a deeper dive into the WebUSB, refer to +https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web + +WebUSB API Specification: +https://wicg.github.io/webusb/ + +Overview +******** + +This simple echo application demonstrates the WebUSB sample application. +This application receives the data and echoes back to the WebUSB +based web application (web page) running in the browser at host. +This application is intended for testing purposes only. For running +real usecase, implement applications based on the WebUSB API. +This sample can be found under :zephyr_file:`samples/subsys/usb/legacy/webusb` in the +Zephyr project tree. + +.. note:: + This samples demonstrate deprecated :ref:`usb_device_stack`. + +Requirements +************ + +This project requires an USB device driver, which is available for multiple +boards supported in Zephyr. + +Building and Running +******************** + +Build and flash webusb sample with: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/legacy/webusb + :board: + :goals: flash + :compact: + +Testing with the latest Google Chrome on host +********************************************* + +This sample application requires the latest Google Chrome, a web page +based on WebUSB API to connect to the USB device and optionally +http server running on localhost to serve the web page. + +WebUSB is a powerful new feature added to the Web and it is available +only to secure origins. This means the web page/site that is used to +connect to the device must be served over a secure connection (HTTPS). + +Follow these steps to run the demo on your host system: + +#. Run the latest Google Chrome on host. + +#. Implement a web app (web page) using WebUSB API and run + it on localhost. + + The sample can be found in the webusb sample directory: + :zephyr_file:`samples/subsys/usb/legacy/webusb/index.html`. + + This sample web page demonstrates how to create and use a WebUSB + interface, as well as demonstrate the communication between browser + and WebUSB enabled device. + + There are two ways to access this sample page: + + * Using Chrome browser go to :doc:`demo` + + * Host the demo page locally: Start a web server + in the webusb sample directory. + + .. code-block:: console + + $ python -m http.server + + Using Chrome browser open url http://localhost:8001/ + +#. Connect the board to your host. + +#. Once the device is booted, you should see a notification from + Chrome: "Go to localhost to connect.". Click on the notification + to open demo page. + Note that at the moment WebUSB landing page notification is disabled + in Chrome on Windows. See https://github.com/WICG/webusb#implementation-status + +#. Click on the :guilabel:`Connect` button to connect to the device. + +#. Send some text to the device by clicking on the :guilabel:`Send` button. + The demo app will receive the same text from the device and display it in + the text area. diff --git a/samples/subsys/usb/webusb-next/demo.rst b/samples/subsys/usb/legacy/webusb/demo.rst similarity index 100% rename from samples/subsys/usb/webusb-next/demo.rst rename to samples/subsys/usb/legacy/webusb/demo.rst diff --git a/samples/subsys/usb/webusb-next/index.html b/samples/subsys/usb/legacy/webusb/index.html similarity index 100% rename from samples/subsys/usb/webusb-next/index.html rename to samples/subsys/usb/legacy/webusb/index.html diff --git a/samples/subsys/usb/legacy/webusb/prj.conf b/samples/subsys/usb/legacy/webusb/prj.conf new file mode 100644 index 0000000000000..0f706e42ddea1 --- /dev/null +++ b/samples/subsys/usb/legacy/webusb/prj.conf @@ -0,0 +1,13 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_BOS=y +CONFIG_SERIAL=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr WebUSB sample" +CONFIG_USB_DEVICE_PID=0x000A +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +CONFIG_LOG=y +CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y +CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y diff --git a/samples/subsys/usb/legacy/webusb/sample.yaml b/samples/subsys/usb/legacy/webusb/sample.yaml new file mode 100644 index 0000000000000..4ad25f07262d0 --- /dev/null +++ b/samples/subsys/usb/legacy/webusb/sample.yaml @@ -0,0 +1,10 @@ +sample: + name: Web USB +tests: + sample.usb.legacy.webusb: + depends_on: usb_device + build_only: true + tags: usb + platform_exclude: + - native_posix + - native_posix/native/64 diff --git a/samples/subsys/usb/legacy/webusb/src/main.c b/samples/subsys/usb/legacy/webusb/src/main.c new file mode 100644 index 0000000000000..331319b2bec48 --- /dev/null +++ b/samples/subsys/usb/legacy/webusb/src/main.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2016-2019 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Sample app for WebUSB enabled custom class driver. + * + * Sample app for WebUSB enabled custom class driver. The received + * data is echoed back to the WebUSB based application running in + * the browser at host. + */ + +#define LOG_LEVEL CONFIG_USB_DEVICE_LOG_LEVEL +#include +LOG_MODULE_REGISTER(main); + +#include +#include +#include +#include + +#include "webusb.h" + +/* random GUID {FA611CC3-7057-42EE-9D82-4919639562B3} */ +#define WEBUSB_DEVICE_INTERFACE_GUID \ + '{', 0x00, 'F', 0x00, 'A', 0x00, '6', 0x00, '1', 0x00, '1', 0x00, \ + 'C', 0x00, 'C', 0x00, '3', 0x00, '-', 0x00, '7', 0x00, '0', 0x00, \ + '5', 0x00, '7', 0x00, '-', 0x00, '4', 0x00, '2', 0x00, 'E', 0x00, \ + 'E', 0x00, '-', 0x00, '9', 0x00, 'D', 0x00, '8', 0x00, '2', 0x00, \ + '-', 0x00, '4', 0x00, '9', 0x00, '1', 0x00, '9', 0x00, '6', 0x00, \ + '3', 0x00, '9', 0x00, '5', 0x00, '6', 0x00, '2', 0x00, 'B', 0x00, \ + '3', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 + +#define COMPATIBLE_ID_WINUSB \ + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00 + +static struct msosv2_descriptor_t { + struct msosv2_descriptor_set_header header; +#if defined(CONFIG_USB_CDC_ACM) + struct msosv2_function_subset_header subset_header; +#endif + struct msosv2_compatible_id webusb_compatible_id; + struct msosv2_guids_property webusb_guids_property; +} __packed msosv2_descriptor = { + /* Microsoft OS 2.0 descriptor set + * This tells Windows what kind of device this is and to install the WinUSB driver. + */ + .header = { + .wLength = sizeof(struct msosv2_descriptor_set_header), + .wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR, + .dwWindowsVersion = 0x06030000, + .wTotalLength = sizeof(struct msosv2_descriptor_t), + }, +#if defined(CONFIG_USB_CDC_ACM) + /* If CONFIG_USB_CDC_ACM is selected, extra interfaces will be added on build time, + * making the target a composite device, which requires an extra Function + * Subset Header. + */ + .subset_header = { + .wLength = sizeof(struct msosv2_function_subset_header), + .wDescriptorType = MS_OS_20_SUBSET_HEADER_FUNCTION, + /* The WebUSB interface number becomes the first when CDC_ACM is enabled by + * configuration. Beware that if this sample is used as an inspiration for + * applications, where the WebUSB interface is no longer the first, + * remember to adjust bFirstInterface. + */ + .bFirstInterface = 0, + .wSubsetLength = 160 + }, +#endif + .webusb_compatible_id = { + .wLength = sizeof(struct msosv2_compatible_id), + .wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID, + .CompatibleID = {COMPATIBLE_ID_WINUSB}, + }, + .webusb_guids_property = { + .wLength = sizeof(struct msosv2_guids_property), + .wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY, + .wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ, + .wPropertyNameLength = 42, + .PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME}, + .wPropertyDataLength = 80, + .bPropertyData = {WEBUSB_DEVICE_INTERFACE_GUID}, + }, +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_webusb cap; +} __packed bos_cap_webusb = { + /* WebUSB Platform Capability Descriptor: + * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor + */ + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_webusb), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + /* WebUSB Platform Capability UUID + * 3408b638-09a9-47a0-8bfd-a0768815b665 + */ + .PlatformCapabilityUUID = { + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, + 0xA0, 0x47, + 0x8B, 0xFD, + 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, + }, + }, + .cap = { + .bcdVersion = sys_cpu_to_le16(0x0100), + .bVendorCode = 0x01, + .iLandingPage = 0x01 + } +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_msos cap; +} __packed bos_cap_msosv2 = { + /* Microsoft OS 2.0 Platform Capability Descriptor + * See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/ + * microsoft-defined-usb-descriptors + * Adapted from the source: + * https://github.com/sowbug/weblight/blob/master/firmware/webusb.c + * (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c + */ + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_msos), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + .PlatformCapabilityUUID = { + /** + * MS OS 2.0 Platform Capability ID + * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F + */ + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, + 0xC7, 0x4C, + 0x9C, 0xD2, + 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, + }, + }, + .cap = { + /* Windows version (8.1) (0x06030000) */ + .dwWindowsVersion = sys_cpu_to_le32(0x06030000), + .wMSOSDescriptorSetTotalLength = + sys_cpu_to_le16(sizeof(msosv2_descriptor)), + /* Arbitrary code that is used as bRequest for vendor command */ + .bMS_VendorCode = 0x02, + .bAltEnumCode = 0x00 + }, +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_capability_lpm bos_cap_lpm = { + .bLength = sizeof(struct usb_bos_capability_lpm), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION, + /** + * Currently there is not a single device driver in Zephyr that supports + * LPM. Moreover, Zephyr USB stack does not have LPM support, so do not + * falsely claim to support LPM. + * BIT(1) - LPM support + * BIT(2) - BESL support + */ + .bmAttributes = 0, +}; + +/* WebUSB Device Requests */ +static const uint8_t webusb_allowed_origins[] = { + /* Allowed Origins Header: + * https://wicg.github.io/webusb/#get-allowed-origins + */ + 0x05, 0x00, 0x0D, 0x00, 0x01, + + /* Configuration Subset Header: + * https://wicg.github.io/webusb/#configuration-subset-header + */ + 0x04, 0x01, 0x01, 0x01, + + /* Function Subset Header: + * https://wicg.github.io/webusb/#function-subset-header + */ + 0x04, 0x02, 0x02, 0x01 +}; + +/* Number of allowed origins */ +#define NUMBER_OF_ALLOWED_ORIGINS 1 + +/* URL Descriptor: https://wicg.github.io/webusb/#url-descriptor */ +static const uint8_t webusb_origin_url[] = { + /* Length, DescriptorType, Scheme */ + 0x11, 0x03, 0x00, + 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', ':', '8', '0', '0', '0' +}; + +/* Predefined response to control commands related to MS OS 1.0 descriptors + * Please note that this code only defines "extended compat ID OS feature + * descriptors" and not "extended properties OS features descriptors" + */ +#define MSOS_STRING_LENGTH 18 +static struct string_desc { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bString[MSOS_STRING_LENGTH]; + +} __packed msos1_string_descriptor = { + .bLength = MSOS_STRING_LENGTH, + .bDescriptorType = USB_DESC_STRING, + /* Signature MSFT100 */ + .bString = { + 'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, + '1', 0x00, '0', 0x00, '0', 0x00, + 0x03, /* Vendor Code, used for a control request */ + 0x00, /* Padding byte for VendorCode looks like UTF16 */ + }, +}; + +static const uint8_t msos1_compatid_descriptor[] = { + /* See https://github.com/pbatard/libwdi/wiki/WCID-Devices */ + /* MS OS 1.0 header section */ + 0x28, 0x00, 0x00, 0x00, /* Descriptor size (40 bytes) */ + 0x00, 0x01, /* Version 1.00 */ + 0x04, 0x00, /* Type: Extended compat ID descriptor */ + 0x01, /* Number of function sections */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reserved */ + + /* MS OS 1.0 function section */ + 0x02, /* Index of interface this section applies to. */ + 0x01, /* reserved */ + /* 8-byte compatible ID string, then 8-byte sub-compatible ID string */ + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* reserved */ +}; + +/** + * @brief Custom handler for standard requests in + * order to catch the request and return the + * WebUSB Platform Capability Descriptor. + * + * @param pSetup Information about the request to execute. + * @param len Size of the buffer. + * @param data Buffer containing the request result. + * + * @return 0 on success, negative errno code on fail + */ +int custom_handle_req(struct usb_setup_packet *pSetup, + int32_t *len, uint8_t **data) +{ + if (usb_reqtype_is_to_device(pSetup)) { + return -ENOTSUP; + } + + if (USB_GET_DESCRIPTOR_TYPE(pSetup->wValue) == USB_DESC_STRING && + USB_GET_DESCRIPTOR_INDEX(pSetup->wValue) == 0xEE) { + *data = (uint8_t *)(&msos1_string_descriptor); + *len = sizeof(msos1_string_descriptor); + + LOG_DBG("Get MS OS Descriptor v1 string"); + + return 0; + } + + return -EINVAL; +} + +/** + * @brief Handler called for vendor specific commands. This includes + * WebUSB allowed origins and MS OS 1.0 and 2.0 descriptors. + * + * @param pSetup Information about the request to execute. + * @param len Size of the buffer. + * @param data Buffer containing the request result. + * + * @return 0 on success, negative errno code on fail. + */ +int vendor_handle_req(struct usb_setup_packet *pSetup, + int32_t *len, uint8_t **data) +{ + if (usb_reqtype_is_to_device(pSetup)) { + return -ENOTSUP; + } + + /* Get Allowed origins request */ + if (pSetup->bRequest == 0x01 && pSetup->wIndex == 0x01) { + *data = (uint8_t *)(&webusb_allowed_origins); + *len = sizeof(webusb_allowed_origins); + + LOG_DBG("Get webusb_allowed_origins"); + + return 0; + } else if (pSetup->bRequest == 0x01 && pSetup->wIndex == 0x02) { + /* Get URL request */ + uint8_t index = USB_GET_DESCRIPTOR_INDEX(pSetup->wValue); + + if (index == 0U || index > NUMBER_OF_ALLOWED_ORIGINS) { + return -ENOTSUP; + } + + *data = (uint8_t *)(&webusb_origin_url); + *len = sizeof(webusb_origin_url); + + LOG_DBG("Get webusb_origin_url"); + + return 0; + } else if (pSetup->bRequest == bos_cap_msosv2.cap.bMS_VendorCode && + pSetup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { + /* Get MS OS 2.0 Descriptors request */ + *data = (uint8_t *)(&msosv2_descriptor); + *len = sizeof(msosv2_descriptor); + + LOG_DBG("Get MS OS Descriptors v2"); + + return 0; + } else if (pSetup->bRequest == 0x03 && pSetup->wIndex == 0x04) { + /* Get MS OS 1.0 Descriptors request */ + /* 0x04 means "Extended compat ID". + * Use 0x05 instead for "Extended properties". + */ + *data = (uint8_t *)(&msos1_compatid_descriptor); + *len = sizeof(msos1_compatid_descriptor); + + LOG_DBG("Get MS OS Descriptors CompatibleID"); + + return 0; + } + + return -ENOTSUP; +} + +/* Custom and Vendor request handlers */ +static struct webusb_req_handlers req_handlers = { + .custom_handler = custom_handle_req, + .vendor_handler = vendor_handle_req, +}; + +int main(void) +{ + int ret; + + LOG_DBG(""); + + usb_bos_register_cap((void *)&bos_cap_webusb); + usb_bos_register_cap((void *)&bos_cap_msosv2); + usb_bos_register_cap((void *)&bos_cap_lpm); + + /* Set the custom and vendor request handlers */ + webusb_register_request_handlers(&req_handlers); + + ret = usb_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable USB"); + return 0; + } + return 0; +} diff --git a/samples/subsys/usb/webusb/src/webusb.c b/samples/subsys/usb/legacy/webusb/src/webusb.c similarity index 100% rename from samples/subsys/usb/webusb/src/webusb.c rename to samples/subsys/usb/legacy/webusb/src/webusb.c diff --git a/samples/subsys/usb/legacy/webusb/src/webusb.h b/samples/subsys/usb/legacy/webusb/src/webusb.h new file mode 100644 index 0000000000000..132cfb22b487b --- /dev/null +++ b/samples/subsys/usb/legacy/webusb/src/webusb.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015-2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief WebUSB enabled custom class driver header file + * + * Header file for WebUSB enabled custom class driver + */ + +#ifndef __WEBUSB_SERIAL_H__ +#define __WEBUSB_SERIAL_H__ + +/** + * WebUSB request handlers + */ +struct webusb_req_handlers { + /* Handler for WebUSB Vendor specific commands */ + usb_request_handler vendor_handler; + /** + * The custom request handler gets a first chance at handling + * the request before it is handed over to the 'chapter 9' request + * handler + */ + usb_request_handler custom_handler; +}; + +/** + * @brief Register Custom and Vendor request callbacks + * + * Function to register Custom and Vendor request callbacks + * for handling requests. + * + * @param [in] handlers Pointer to WebUSB request handlers structure + */ +void webusb_register_request_handlers(struct webusb_req_handlers *handlers); + +#endif /* __WEBUSB_SERIAL_H__ */ diff --git a/samples/subsys/usb/mass/README.rst b/samples/subsys/usb/mass/README.rst index b68f57497b206..910c34e7c1ecd 100644 --- a/samples/subsys/usb/mass/README.rst +++ b/samples/subsys/usb/mass/README.rst @@ -1,6 +1,6 @@ .. zephyr:code-sample:: usb-mass :name: USB Mass Storage - :relevant-api: usbd_api usbd_msc_device _usb_device_core_api file_system_api + :relevant-api: usbd_api usbd_msc_device file_system_api Expose board's RAM or FLASH as a USB disk using USB Mass Storage driver. diff --git a/samples/subsys/usb/mass/prj.conf b/samples/subsys/usb/mass/prj.conf index 0954afcd0eec0..dd9d784070de5 100644 --- a/samples/subsys/usb/mass/prj.conf +++ b/samples/subsys/usb/mass/prj.conf @@ -1,14 +1,15 @@ +CONFIG_USB_DEVICE_STACK_NEXT=y + CONFIG_STDOUT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y +CONFIG_USBD_MSC_CLASS=y +CONFIG_USBD_MSC_LUNS_PER_INSTANCE=3 -#USB related configs -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr MSC sample" -CONFIG_USB_DEVICE_PID=0x0008 CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_MASS_STORAGE=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y -CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y -CONFIG_MAIN_STACK_SIZE=1536 +CONFIG_SAMPLE_USBD_PID=0x0008 +CONFIG_SAMPLE_USBD_PRODUCT="USBD MSC sample" +CONFIG_MAIN_STACK_SIZE=2048 diff --git a/samples/subsys/usb/mass/sample.yaml b/samples/subsys/usb/mass/sample.yaml index 352ee21002275..e8e8f7df19c9f 100644 --- a/samples/subsys/usb/mass/sample.yaml +++ b/samples/subsys/usb/mass/sample.yaml @@ -1,25 +1,7 @@ sample: name: Mass Storage tests: - sample.usb.mass_ram_none: - min_ram: 128 - depends_on: usb_device - arch_exclude: posix - extra_args: - - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" - extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 - tags: - - msd - - usb - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "No file system selected" - - "The device is put in USB mass storage mode." - sample.usb_device_next.mass_ram_none: + sample.usbd.mass_ram_none: min_ram: 128 depends_on: usbd integration_platforms: @@ -31,12 +13,8 @@ tests: - mimxrt685_evk/mimxrt685s/cm33 - mimxrt1060_evk/mimxrt1062/qspi extra_args: - - CONF_FILE="usbd_next_prj.conf" - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" - extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 tags: - - msd - usb harness: console harness_config: @@ -44,43 +22,23 @@ tests: ordered: true regex: - "No file system selected" - - "The device is put in USB mass storage mode." - sample.usb.mass_ram_fat: + - "The device is put in USB mass storage mode" + sample.usbd.mass_ram_fat: min_ram: 128 - depends_on: usb_device - arch_exclude: posix + depends_on: usbd + integration_platforms: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - frdm_k64f + - stm32f723e_disco + - nucleo_f413zh + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk/mimxrt1062/qspi extra_args: - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 - CONFIG_APP_MSC_STORAGE_RAM=y tags: - - msd - - usb - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "End of files" - - "The device is put in USB mass storage mode." - sample.usb.mass_flash_fatfs: - min_ram: 32 - modules: - - fatfs - depends_on: usb_device - filter: dt_compat_enabled("nordic,qspi-nor") - platform_allow: - - nrf52840dk/nrf52840 - - nrf5340dk/nrf5340/cpuapp - - adafruit_feather_nrf52840/nrf52840/sense - integration_platforms: - - nrf52840dk/nrf52840 - extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 - - CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y - tags: - - msd - usb harness: console harness_config: @@ -88,8 +46,8 @@ tests: ordered: true regex: - "End of files" - - "The device is put in USB mass storage mode." - sample.usb_device_next.mass_flash_fatfs: + - "The device is put in USB mass storage mode" + sample.usbd.mass_flash_fatfs: min_ram: 32 modules: - fatfs @@ -101,43 +59,18 @@ tests: - adafruit_feather_nrf52840/nrf52840/sense integration_platforms: - nrf52840dk/nrf52840 - extra_args: CONF_FILE="usbd_next_prj.conf" extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 - CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y tags: - - msd - - usb - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "End of files" - - "The device is put in USB mass storage mode." - sample.usb.mass_sdhc_fatfs: - min_ram: 32 - filter: dt_compat_enabled("zephyr,sdmmc-disk") - modules: - - fatfs - depends_on: - - usb_device - - sdhc - extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 - - CONFIG_APP_MSC_STORAGE_SDCARD=y - tags: - - msd - usb harness: console harness_config: - fixture: fixture_sdcard type: multi_line ordered: true regex: - "End of files" - - "The device is put in USB mass storage mode." - sample.usb_device_next.mass_sdhc_fatfs: + - "The device is put in USB mass storage mode" + sample.usbd.mass_sdhc_fatfs: min_ram: 32 filter: dt_compat_enabled("zephyr,sdmmc-disk") modules: @@ -146,11 +79,8 @@ tests: - usbd - sdhc extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 - CONFIG_APP_MSC_STORAGE_SDCARD=y - extra_args: CONF_FILE="usbd_next_prj.conf" tags: - - msd - usb harness: console harness_config: @@ -159,12 +89,12 @@ tests: ordered: true regex: - "End of files" - - "The device is put in USB mass storage mode." - sample.usb.mass_flash_littlefs: + - "The device is put in USB mass storage mode" + sample.usbd.mass_flash_littlefs: modules: - littlefs min_ram: 32 - depends_on: usb_device + depends_on: usbd filter: dt_compat_enabled("nordic,qspi-nor") platform_allow: - nrf52840dk/nrf52840 @@ -173,10 +103,8 @@ tests: integration_platforms: - nrf52840dk/nrf52840 extra_configs: - - CONFIG_LOG_DEFAULT_LEVEL=3 - CONFIG_APP_MSC_STORAGE_FLASH_LITTLEFS=y tags: - - msd - usb harness: console harness_config: @@ -184,4 +112,4 @@ tests: ordered: true regex: - "End of files" - - "The device is put in USB mass storage mode." + - "The device is put in USB mass storage mode" diff --git a/samples/subsys/usb/mass/src/main.c b/samples/subsys/usb/mass/src/main.c index df90560d8353c..59a770a515450 100644 --- a/samples/subsys/usb/mass/src/main.c +++ b/samples/subsys/usb/mass/src/main.c @@ -9,13 +9,12 @@ #include #include -#include #include #include #include #include -LOG_MODULE_REGISTER(main); +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); #if CONFIG_DISK_DRIVER_FLASH #include @@ -41,7 +40,6 @@ FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage); static struct fs_mount_t fs_mnt; -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) static struct usbd_context *sample_usbd; #if CONFIG_DISK_DRIVER_RAM @@ -56,28 +54,6 @@ USBD_DEFINE_MSC_LUN(nand, "NAND", "Zephyr", "FlashDisk", "0.00"); USBD_DEFINE_MSC_LUN(sd, "SD", "Zephyr", "SD", "0.00"); #endif -static int enable_usb_device_next(void) -{ - int err; - - sample_usbd = sample_usbd_init_device(NULL); - if (sample_usbd == NULL) { - LOG_ERR("Failed to initialize USB device"); - return -ENODEV; - } - - err = usbd_enable(sample_usbd); - if (err) { - LOG_ERR("Failed to enable device support"); - return err; - } - - LOG_DBG("USB device support enabled"); - - return 0; -} -#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */ - static int setup_flash(struct fs_mount_t *mnt) { int rc = 0; @@ -215,16 +191,24 @@ int main(void) setup_disk(); -#if defined(CONFIG_USB_DEVICE_STACK_NEXT) - ret = enable_usb_device_next(); -#else - ret = usb_enable(NULL); -#endif + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); + return -ENODEV; + } + + ret = usbd_enable(sample_usbd); + if (ret) { + LOG_ERR("Failed to enable device support"); + return ret; + } + if (ret != 0) { LOG_ERR("Failed to enable USB"); return 0; } - LOG_INF("The device is put in USB mass storage mode.\n"); + LOG_INF("The device is put in USB mass storage mode"); + return 0; } diff --git a/samples/subsys/usb/mass/usbd_next_prj.conf b/samples/subsys/usb/mass/usbd_next_prj.conf deleted file mode 100644 index dd9d784070de5..0000000000000 --- a/samples/subsys/usb/mass/usbd_next_prj.conf +++ /dev/null @@ -1,15 +0,0 @@ -CONFIG_USB_DEVICE_STACK_NEXT=y - -CONFIG_STDOUT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_UART_LINE_CTRL=y -CONFIG_USBD_MSC_CLASS=y -CONFIG_USBD_MSC_LUNS_PER_INSTANCE=3 - -CONFIG_LOG=y -CONFIG_USBD_LOG_LEVEL_WRN=y -CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y - -CONFIG_SAMPLE_USBD_PID=0x0008 -CONFIG_SAMPLE_USBD_PRODUCT="USBD MSC sample" -CONFIG_MAIN_STACK_SIZE=2048 diff --git a/samples/subsys/usb/testusb/CMakeLists.txt b/samples/subsys/usb/testusb/CMakeLists.txt index 2351275f0368a..353c10f07384e 100644 --- a/samples/subsys/usb/testusb/CMakeLists.txt +++ b/samples/subsys/usb/testusb/CMakeLists.txt @@ -4,5 +4,6 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(testusb) +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/console/Kconfig b/samples/subsys/usb/testusb/Kconfig similarity index 100% rename from samples/subsys/usb/console/Kconfig rename to samples/subsys/usb/testusb/Kconfig diff --git a/samples/subsys/usb/testusb/README.rst b/samples/subsys/usb/testusb/README.rst index 03e6f6c104a83..52a124e05e6fc 100644 --- a/samples/subsys/usb/testusb/README.rst +++ b/samples/subsys/usb/testusb/README.rst @@ -1,6 +1,6 @@ .. zephyr:code-sample:: testusb-app - :name: USB testing application - :relevant-api: _usb_device_core_api + :name: USB device testing application + :relevant-api: usbd_api Test USB device drivers using a loopback function. diff --git a/samples/subsys/usb/testusb/prj.conf b/samples/subsys/usb/testusb/prj.conf index e310a67818d9c..fcbf19c62e8d8 100644 --- a/samples/subsys/usb/testusb/prj.conf +++ b/samples/subsys/usb/testusb/prj.conf @@ -1,11 +1,11 @@ -CONFIG_STDOUT_CONSOLE=y +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_LOOPBACK_CLASS=y +CONFIG_UDC_BUF_POOL_SIZE=4096 -#USB related configs -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr testusb sample" -CONFIG_USB_DEVICE_PID=0x0009 CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOOPBACK=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USBD_LOG_LEVEL_ERR=y +CONFIG_UDC_DRIVER_LOG_LEVEL_ERR=y +CONFIG_USBD_LOOPBACK_LOG_LEVEL_ERR=y + +CONFIG_SAMPLE_USBD_PID=0x0009 +CONFIG_SAMPLE_USBD_PRODUCT="Zephyr testusb sample" diff --git a/samples/subsys/usb/testusb/sample.yaml b/samples/subsys/usb/testusb/sample.yaml index c251eaded7392..a70589c49d940 100644 --- a/samples/subsys/usb/testusb/sample.yaml +++ b/samples/subsys/usb/testusb/sample.yaml @@ -1,10 +1,7 @@ sample: - name: USB loopback sample + name: USB device loopback sample tests: - sample.usb.loopback: - depends_on: usb_device + sample.usbd.loopback: + depends_on: usbd tags: usb - platform_exclude: - - native_posix - - native_posix/native/64 - harness: button + harness: TBD diff --git a/samples/subsys/usb/testusb/src/main.c b/samples/subsys/usb/testusb/src/main.c index 936608fc2e9da..04344e9754345 100644 --- a/samples/subsys/usb/testusb/src/main.c +++ b/samples/subsys/usb/testusb/src/main.c @@ -1,24 +1,37 @@ /* - * Copyright (c) 2018 Phytec Messtechnik GmbH + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include + #include -#include -LOG_MODULE_REGISTER(main); +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); int main(void) { + struct usbd_context *sample_usbd; int ret; - ret = usb_enable(NULL); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; + sample_usbd = sample_usbd_setup_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to setup USB device"); + return -ENODEV; + } + + ret = usbd_init(sample_usbd); + if (ret) { + LOG_ERR("Failed to initialize device support"); + return ret; + } + + ret = usbd_enable(sample_usbd); + if (ret) { + LOG_ERR("Failed to enable device support"); + return ret; } - LOG_INF("entered main."); return 0; } diff --git a/samples/subsys/usb/usb.rst b/samples/subsys/usb/usb.rst index a86c7cb3a1f71..aaae7fea11464 100644 --- a/samples/subsys/usb/usb.rst +++ b/samples/subsys/usb/usb.rst @@ -1,6 +1,17 @@ .. zephyr:code-sample-category:: usb - :name: USB device support - :show-listing: - :glob: **/* + :name: USB - Samples that demonstrate :ref:`usb_device_stack`. + These samples demonstrate the use of USB support in Zephyr RTOS. + +Most of the USB support samples can be found under :zephyr_file:`samples/subsys/usb` +in the Zephyr project tree. However, there are a few functions whose samples +are located in different directories. These are: + +* Bluetooth HCI USB transport layer implementation is covered by + :zephyr:code-sample:`bluetooth_hci_usb` +* USB CDC ECM and USB CDC NCM implementations are covered by the networking + samples :zephyr:code-sample:`zperf` or :zephyr:code-sample:`sockets-http-server` + +.. zephyr:code-sample-listing:: + :categories: usb + :live-search: diff --git a/samples/subsys/usb/webusb-next/README.rst b/samples/subsys/usb/webusb-next/README.rst deleted file mode 100644 index 262c6ee62722a..0000000000000 --- a/samples/subsys/usb/webusb-next/README.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. zephyr:code-sample:: webusb-next - :name: WebUSB-next - :relevant-api: usbd_api - - Receive and echo data from a web page using WebUSB API. - -Overview -******** - -This sample demonstrates how to use the Binary Device Object Store (BOS), -Microsoft OS 2.0 descriptors, and WebUSB descriptors to implement a WebUSB -sample application. The sample USB function receives the data and echoes back -to the WebUSB API based application running in the browser on your local host. -This sample can be found at :zephyr_file:`samples/subsys/usb/webusb-next` in the -Zephyr project tree. - -Requirements -************ - -This project requires a USB device controller driver using the UDC API. -On your host computer, this project requires a web browser that supports the -WebUSB API, such as Chromium or a Chromium-based browser. - -Building and Running -******************** - -Build and flash webusb sample with: - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/usb/webusb-next - :board: - :goals: flash - :compact: - -Demonstration -************* - -The sample includes a simple WebUSB API application and can be found in the -sample directory: :zephyr_file:`samples/subsys/usb/webusb-next/index.html`. - -There are two ways to access this sample page: - -* Using browser go to :doc:`demo` - -* Start a web server in the sample directory: - - .. code-block:: console - - $ python -m http.server - -Then follow these steps: - -#. Connect the board to your host. - -#. Once the device has booted, you may see a notification from the browser: "Go - to localhost to connect". Click on the notification to open the demo page. If - there is no notification from the browser, open the URL http://localhost:8001/ - in your browser. - -#. Click on the :guilabel:`Connect` button to connect to the device. - -#. Send some text to the device by clicking on the :guilabel:`Send` button. - The demo application will receive the same text from the device and display - it in the text area. - -References -*********** - -WebUSB API Specification: -https://wicg.github.io/webusb/ - -Chrome for Developers, "Access USB Devices on the Web": -https://developer.chrome.com/docs/capabilities/usb diff --git a/samples/subsys/usb/webusb-next/sample.yaml b/samples/subsys/usb/webusb-next/sample.yaml deleted file mode 100644 index e26352fe50e56..0000000000000 --- a/samples/subsys/usb/webusb-next/sample.yaml +++ /dev/null @@ -1,15 +0,0 @@ -sample: - name: WebUSB -tests: - sample.usb.webusb-next: - depends_on: usbd - tags: usb - integration_platforms: - - nrf52840dk/nrf52840 - - nrf54h20dk/nrf54h20/cpuapp - - frdm_k64f - - stm32f723e_disco - - nucleo_f413zh - - mimxrt685_evk/mimxrt685s/cm33 - - mimxrt1060_evk/mimxrt1062/qspi - harness: TBD diff --git a/samples/subsys/usb/webusb-next/src/main.c b/samples/subsys/usb/webusb-next/src/main.c deleted file mode 100644 index fe600e9d08d11..0000000000000 --- a/samples/subsys/usb/webusb-next/src/main.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2023-2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include -#include -#include - -#include -LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); - -/* - * There are three BOS descriptors used in the sample, a USB 2.0 EXTENSION from - * the USB samples common code, a Microsoft OS 2.0 platform capability - * descriptor, and a WebUSB platform capability descriptor. - */ -#include "webusb.h" -#include "msosv2.h" - -static void msg_cb(struct usbd_context *const usbd_ctx, - const struct usbd_msg *const msg) -{ - LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); - - if (usbd_can_detect_vbus(usbd_ctx)) { - if (msg->type == USBD_MSG_VBUS_READY) { - if (usbd_enable(usbd_ctx)) { - LOG_ERR("Failed to enable device support"); - } - } - - if (msg->type == USBD_MSG_VBUS_REMOVED) { - if (usbd_disable(usbd_ctx)) { - LOG_ERR("Failed to disable device support"); - } - } - } -} - -int main(void) -{ - struct usbd_context *sample_usbd; - int ret; - - sample_usbd = sample_usbd_setup_device(msg_cb); - if (sample_usbd == NULL) { - LOG_ERR("Failed to setup USB device"); - return -ENODEV; - } - - ret = usbd_add_descriptor(sample_usbd, &bos_vreq_msosv2); - if (ret) { - LOG_ERR("Failed to add MSOSv2 capability descriptor"); - return ret; - } - - ret = usbd_add_descriptor(sample_usbd, &bos_vreq_webusb); - if (ret) { - LOG_ERR("Failed to add WebUSB capability descriptor"); - return ret; - } - - ret = usbd_init(sample_usbd); - if (ret) { - LOG_ERR("Failed to initialize device support"); - return ret; - } - - if (!usbd_can_detect_vbus(sample_usbd)) { - ret = usbd_enable(sample_usbd); - if (ret) { - LOG_ERR("Failed to enable device support"); - return ret; - } - } - - return 0; -} diff --git a/samples/subsys/usb/webusb-next/src/webusb.h b/samples/subsys/usb/webusb-next/src/webusb.h deleted file mode 100644 index 329626d4587b6..0000000000000 --- a/samples/subsys/usb/webusb-next/src/webusb.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2016-2019 Intel Corporation - * Copyright (c) 2023-2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H -#define ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H - -/* - * WebUSB platform capability and WebUSB URL descriptor. - * See https://wicg.github.io/webusb for reference. - */ - -#define WEBUSB_REQ_GET_URL 0x02U -#define WEBUSB_DESC_TYPE_URL 0x03U -#define WEBUSB_URL_PREFIX_HTTP 0x00U -#define WEBUSB_URL_PREFIX_HTTPS 0x01U - -#define SAMPLE_WEBUSB_VENDOR_CODE 0x01U -#define SAMPLE_WEBUSB_LANDING_PAGE 0x01U - -struct usb_bos_webusb_desc { - struct usb_bos_platform_descriptor platform; - struct usb_bos_capability_webusb cap; -} __packed; - -static const struct usb_bos_webusb_desc bos_cap_webusb = { - /* WebUSB Platform Capability Descriptor: - * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor - */ - .platform = { - .bLength = sizeof(struct usb_bos_platform_descriptor) - + sizeof(struct usb_bos_capability_webusb), - .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, - .bReserved = 0, - /* WebUSB Platform Capability UUID - * 3408b638-09a9-47a0-8bfd-a0768815b665 - */ - .PlatformCapabilityUUID = { - 0x38, 0xB6, 0x08, 0x34, - 0xA9, 0x09, - 0xA0, 0x47, - 0x8B, 0xFD, - 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, - }, - }, - .cap = { - .bcdVersion = sys_cpu_to_le16(0x0100), - .bVendorCode = SAMPLE_WEBUSB_VENDOR_CODE, - .iLandingPage = SAMPLE_WEBUSB_LANDING_PAGE - } -}; - -/* WebUSB URL Descriptor, see https://wicg.github.io/webusb/#webusb-descriptors */ -static const uint8_t webusb_origin_url[] = { - /* bLength, bDescriptorType, bScheme, UTF-8 encoded URL */ - 0x11, WEBUSB_DESC_TYPE_URL, WEBUSB_URL_PREFIX_HTTP, - 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', ':', '8', '0', '0', '0' -}; - -static int webusb_to_host_cb(const struct usbd_context *const ctx, - const struct usb_setup_packet *const setup, - struct net_buf *const buf) -{ - LOG_INF("Vendor callback to host"); - - if (setup->wIndex == WEBUSB_REQ_GET_URL) { - uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); - - if (index != SAMPLE_WEBUSB_LANDING_PAGE) { - return -ENOTSUP; - } - - LOG_INF("Get URL request, index %u", index); - net_buf_add_mem(buf, &webusb_origin_url, - MIN(net_buf_tailroom(buf), sizeof(webusb_origin_url))); - - return 0; - } - - return -ENOTSUP; -} - -USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_webusb, sizeof(bos_cap_webusb), &bos_cap_webusb, - SAMPLE_WEBUSB_VENDOR_CODE, webusb_to_host_cb, NULL); - -#endif /* ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H */ diff --git a/samples/subsys/usb/webusb/CMakeLists.txt b/samples/subsys/usb/webusb/CMakeLists.txt index fbac52a732ef8..97a240805ee9e 100644 --- a/samples/subsys/usb/webusb/CMakeLists.txt +++ b/samples/subsys/usb/webusb/CMakeLists.txt @@ -4,7 +4,6 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(webusb) -target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/usb) - +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/webusb-next/Kconfig b/samples/subsys/usb/webusb/Kconfig similarity index 100% rename from samples/subsys/usb/webusb-next/Kconfig rename to samples/subsys/usb/webusb/Kconfig diff --git a/samples/subsys/usb/webusb/README.rst b/samples/subsys/usb/webusb/README.rst index d62d396768410..74c809d238350 100644 --- a/samples/subsys/usb/webusb/README.rst +++ b/samples/subsys/usb/webusb/README.rst @@ -1,31 +1,25 @@ .. zephyr:code-sample:: webusb :name: WebUSB - :relevant-api: _usb_device_core_api + :relevant-api: usbd_api Receive and echo data from a web page using WebUSB API. -For a deeper dive into the WebUSB, refer to -https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web - -WebUSB API Specification: -https://wicg.github.io/webusb/ - Overview ******** -This simple echo application demonstrates the WebUSB sample application. -This application receives the data and echoes back to the WebUSB -based web application (web page) running in the browser at host. -This application is intended for testing purposes only. For running -real usecase, implement applications based on the WebUSB API. -This sample can be found under :zephyr_file:`samples/subsys/usb/webusb` in the +This sample demonstrates how to use the Binary Device Object Store (BOS), +Microsoft OS 2.0 descriptors, and WebUSB descriptors to implement a WebUSB +sample application. The sample USB function receives the data and echoes back +to the WebUSB API based application running in the browser on your local host. +This sample can be found at :zephyr_file:`samples/subsys/usb/webusb` in the Zephyr project tree. Requirements ************ -This project requires an USB device driver, which is available for multiple -boards supported in Zephyr. +This project requires a USB device controller driver using the UDC API. +On your host computer, this project requires a web browser that supports the +WebUSB API, such as Chromium or a Chromium-based browser. Building and Running ******************** @@ -38,54 +32,42 @@ Build and flash webusb sample with: :goals: flash :compact: -Testing with the latest Google Chrome on host -********************************************* - -This sample application requires the latest Google Chrome, a web page -based on WebUSB API to connect to the USB device and optionally -http server running on localhost to serve the web page. - -WebUSB is a powerful new feature added to the Web and it is available -only to secure origins. This means the web page/site that is used to -connect to the device must be served over a secure connection (HTTPS). - -Follow these steps to run the demo on your host system: - -#. Run the latest Google Chrome on host. +Demonstration +************* -#. Implement a web app (web page) using WebUSB API and run - it on localhost. +The sample includes a simple WebUSB API application and can be found in the +sample directory: :zephyr_file:`samples/subsys/usb/webusb/index.html`. - The sample can be found in the webusb sample directory: - :zephyr_file:`samples/subsys/usb/webusb/index.html`. +There are two ways to access this sample page: - This sample web page demonstrates how to create and use a WebUSB - interface, as well as demonstrate the communication between browser - and WebUSB enabled device. +* Using browser go to :doc:`demo` - There are two ways to access this sample page: +* Start a web server in the sample directory: - * Using Chrome browser go to :doc:`demo` + .. code-block:: console - * Host the demo page locally: Start a web server - in the webusb sample directory. + $ python -m http.server - .. code-block:: console - - $ python -m http.server - - Using Chrome browser open url http://localhost:8001/ +Then follow these steps: #. Connect the board to your host. -#. Once the device is booted, you should see a notification from - Chrome: "Go to localhost to connect.". Click on the notification - to open demo page. - Note that at the moment WebUSB landing page notification is disabled - in Chrome on Windows. See https://github.com/WICG/webusb#implementation-status +#. Once the device has booted, you may see a notification from the browser: "Go + to localhost to connect". Click on the notification to open the demo page. If + there is no notification from the browser, open the URL http://localhost:8001/ + in your browser. #. Click on the :guilabel:`Connect` button to connect to the device. #. Send some text to the device by clicking on the :guilabel:`Send` button. - The demo app will receive the same text from the device and display it in - the text area. + The demo application will receive the same text from the device and display + it in the text area. + +References +*********** + +WebUSB API Specification: +https://wicg.github.io/webusb/ + +Chrome for Developers, "Access USB Devices on the Web": +https://developer.chrome.com/docs/capabilities/usb diff --git a/samples/subsys/usb/webusb/prj.conf b/samples/subsys/usb/webusb/prj.conf index 0f706e42ddea1..1c730a0ec56a3 100644 --- a/samples/subsys/usb/webusb/prj.conf +++ b/samples/subsys/usb/webusb/prj.conf @@ -1,13 +1,7 @@ -CONFIG_STDOUT_CONSOLE=y -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_BOS=y -CONFIG_SERIAL=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr WebUSB sample" -CONFIG_USB_DEVICE_PID=0x000A -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_UART_LINE_CTRL=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x000A +CONFIG_SAMPLE_USBD_20_EXTENSION_DESC=y diff --git a/samples/subsys/usb/webusb/sample.yaml b/samples/subsys/usb/webusb/sample.yaml index c68c0366eaa96..e26352fe50e56 100644 --- a/samples/subsys/usb/webusb/sample.yaml +++ b/samples/subsys/usb/webusb/sample.yaml @@ -1,10 +1,15 @@ sample: - name: Web USB + name: WebUSB tests: - sample.usb.webusb: - depends_on: usb_device + sample.usb.webusb-next: + depends_on: usbd tags: usb - platform_exclude: - - native_posix - - native_posix/native/64 + integration_platforms: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - frdm_k64f + - stm32f723e_disco + - nucleo_f413zh + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk/mimxrt1062/qspi harness: TBD diff --git a/samples/subsys/usb/webusb/src/main.c b/samples/subsys/usb/webusb/src/main.c index 331319b2bec48..fe600e9d08d11 100644 --- a/samples/subsys/usb/webusb/src/main.c +++ b/samples/subsys/usb/webusb/src/main.c @@ -1,364 +1,83 @@ /* - * Copyright (c) 2016-2019 Intel Corporation - * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2023-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -/** - * @file - * @brief Sample app for WebUSB enabled custom class driver. - * - * Sample app for WebUSB enabled custom class driver. The received - * data is echoed back to the WebUSB based application running in - * the browser at host. - */ - -#define LOG_LEVEL CONFIG_USB_DEVICE_LOG_LEVEL -#include -LOG_MODULE_REGISTER(main); +#include #include -#include -#include +#include +#include #include -#include "webusb.h" - -/* random GUID {FA611CC3-7057-42EE-9D82-4919639562B3} */ -#define WEBUSB_DEVICE_INTERFACE_GUID \ - '{', 0x00, 'F', 0x00, 'A', 0x00, '6', 0x00, '1', 0x00, '1', 0x00, \ - 'C', 0x00, 'C', 0x00, '3', 0x00, '-', 0x00, '7', 0x00, '0', 0x00, \ - '5', 0x00, '7', 0x00, '-', 0x00, '4', 0x00, '2', 0x00, 'E', 0x00, \ - 'E', 0x00, '-', 0x00, '9', 0x00, 'D', 0x00, '8', 0x00, '2', 0x00, \ - '-', 0x00, '4', 0x00, '9', 0x00, '1', 0x00, '9', 0x00, '6', 0x00, \ - '3', 0x00, '9', 0x00, '5', 0x00, '6', 0x00, '2', 0x00, 'B', 0x00, \ - '3', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 - -#define COMPATIBLE_ID_WINUSB \ - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00 - -static struct msosv2_descriptor_t { - struct msosv2_descriptor_set_header header; -#if defined(CONFIG_USB_CDC_ACM) - struct msosv2_function_subset_header subset_header; -#endif - struct msosv2_compatible_id webusb_compatible_id; - struct msosv2_guids_property webusb_guids_property; -} __packed msosv2_descriptor = { - /* Microsoft OS 2.0 descriptor set - * This tells Windows what kind of device this is and to install the WinUSB driver. - */ - .header = { - .wLength = sizeof(struct msosv2_descriptor_set_header), - .wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR, - .dwWindowsVersion = 0x06030000, - .wTotalLength = sizeof(struct msosv2_descriptor_t), - }, -#if defined(CONFIG_USB_CDC_ACM) - /* If CONFIG_USB_CDC_ACM is selected, extra interfaces will be added on build time, - * making the target a composite device, which requires an extra Function - * Subset Header. - */ - .subset_header = { - .wLength = sizeof(struct msosv2_function_subset_header), - .wDescriptorType = MS_OS_20_SUBSET_HEADER_FUNCTION, - /* The WebUSB interface number becomes the first when CDC_ACM is enabled by - * configuration. Beware that if this sample is used as an inspiration for - * applications, where the WebUSB interface is no longer the first, - * remember to adjust bFirstInterface. - */ - .bFirstInterface = 0, - .wSubsetLength = 160 - }, -#endif - .webusb_compatible_id = { - .wLength = sizeof(struct msosv2_compatible_id), - .wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID, - .CompatibleID = {COMPATIBLE_ID_WINUSB}, - }, - .webusb_guids_property = { - .wLength = sizeof(struct msosv2_guids_property), - .wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY, - .wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ, - .wPropertyNameLength = 42, - .PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME}, - .wPropertyDataLength = 80, - .bPropertyData = {WEBUSB_DEVICE_INTERFACE_GUID}, - }, -}; - -USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc { - struct usb_bos_platform_descriptor platform; - struct usb_bos_capability_webusb cap; -} __packed bos_cap_webusb = { - /* WebUSB Platform Capability Descriptor: - * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor - */ - .platform = { - .bLength = sizeof(struct usb_bos_platform_descriptor) - + sizeof(struct usb_bos_capability_webusb), - .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, - .bReserved = 0, - /* WebUSB Platform Capability UUID - * 3408b638-09a9-47a0-8bfd-a0768815b665 - */ - .PlatformCapabilityUUID = { - 0x38, 0xB6, 0x08, 0x34, - 0xA9, 0x09, - 0xA0, 0x47, - 0x8B, 0xFD, - 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, - }, - }, - .cap = { - .bcdVersion = sys_cpu_to_le16(0x0100), - .bVendorCode = 0x01, - .iLandingPage = 0x01 - } -}; - -USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc { - struct usb_bos_platform_descriptor platform; - struct usb_bos_capability_msos cap; -} __packed bos_cap_msosv2 = { - /* Microsoft OS 2.0 Platform Capability Descriptor - * See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/ - * microsoft-defined-usb-descriptors - * Adapted from the source: - * https://github.com/sowbug/weblight/blob/master/firmware/webusb.c - * (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c - */ - .platform = { - .bLength = sizeof(struct usb_bos_platform_descriptor) - + sizeof(struct usb_bos_capability_msos), - .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, - .bReserved = 0, - .PlatformCapabilityUUID = { - /** - * MS OS 2.0 Platform Capability ID - * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F - */ - 0xDF, 0x60, 0xDD, 0xD8, - 0x89, 0x45, - 0xC7, 0x4C, - 0x9C, 0xD2, - 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, - }, - }, - .cap = { - /* Windows version (8.1) (0x06030000) */ - .dwWindowsVersion = sys_cpu_to_le32(0x06030000), - .wMSOSDescriptorSetTotalLength = - sys_cpu_to_le16(sizeof(msosv2_descriptor)), - /* Arbitrary code that is used as bRequest for vendor command */ - .bMS_VendorCode = 0x02, - .bAltEnumCode = 0x00 - }, -}; - -USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_capability_lpm bos_cap_lpm = { - .bLength = sizeof(struct usb_bos_capability_lpm), - .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION, - /** - * Currently there is not a single device driver in Zephyr that supports - * LPM. Moreover, Zephyr USB stack does not have LPM support, so do not - * falsely claim to support LPM. - * BIT(1) - LPM support - * BIT(2) - BESL support - */ - .bmAttributes = 0, -}; - -/* WebUSB Device Requests */ -static const uint8_t webusb_allowed_origins[] = { - /* Allowed Origins Header: - * https://wicg.github.io/webusb/#get-allowed-origins - */ - 0x05, 0x00, 0x0D, 0x00, 0x01, - - /* Configuration Subset Header: - * https://wicg.github.io/webusb/#configuration-subset-header - */ - 0x04, 0x01, 0x01, 0x01, - - /* Function Subset Header: - * https://wicg.github.io/webusb/#function-subset-header - */ - 0x04, 0x02, 0x02, 0x01 -}; - -/* Number of allowed origins */ -#define NUMBER_OF_ALLOWED_ORIGINS 1 - -/* URL Descriptor: https://wicg.github.io/webusb/#url-descriptor */ -static const uint8_t webusb_origin_url[] = { - /* Length, DescriptorType, Scheme */ - 0x11, 0x03, 0x00, - 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', ':', '8', '0', '0', '0' -}; - -/* Predefined response to control commands related to MS OS 1.0 descriptors - * Please note that this code only defines "extended compat ID OS feature - * descriptors" and not "extended properties OS features descriptors" - */ -#define MSOS_STRING_LENGTH 18 -static struct string_desc { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bString[MSOS_STRING_LENGTH]; - -} __packed msos1_string_descriptor = { - .bLength = MSOS_STRING_LENGTH, - .bDescriptorType = USB_DESC_STRING, - /* Signature MSFT100 */ - .bString = { - 'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, - '1', 0x00, '0', 0x00, '0', 0x00, - 0x03, /* Vendor Code, used for a control request */ - 0x00, /* Padding byte for VendorCode looks like UTF16 */ - }, -}; - -static const uint8_t msos1_compatid_descriptor[] = { - /* See https://github.com/pbatard/libwdi/wiki/WCID-Devices */ - /* MS OS 1.0 header section */ - 0x28, 0x00, 0x00, 0x00, /* Descriptor size (40 bytes) */ - 0x00, 0x01, /* Version 1.00 */ - 0x04, 0x00, /* Type: Extended compat ID descriptor */ - 0x01, /* Number of function sections */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reserved */ - - /* MS OS 1.0 function section */ - 0x02, /* Index of interface this section applies to. */ - 0x01, /* reserved */ - /* 8-byte compatible ID string, then 8-byte sub-compatible ID string */ - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* reserved */ -}; +#include +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); -/** - * @brief Custom handler for standard requests in - * order to catch the request and return the - * WebUSB Platform Capability Descriptor. - * - * @param pSetup Information about the request to execute. - * @param len Size of the buffer. - * @param data Buffer containing the request result. - * - * @return 0 on success, negative errno code on fail +/* + * There are three BOS descriptors used in the sample, a USB 2.0 EXTENSION from + * the USB samples common code, a Microsoft OS 2.0 platform capability + * descriptor, and a WebUSB platform capability descriptor. */ -int custom_handle_req(struct usb_setup_packet *pSetup, - int32_t *len, uint8_t **data) -{ - if (usb_reqtype_is_to_device(pSetup)) { - return -ENOTSUP; - } - - if (USB_GET_DESCRIPTOR_TYPE(pSetup->wValue) == USB_DESC_STRING && - USB_GET_DESCRIPTOR_INDEX(pSetup->wValue) == 0xEE) { - *data = (uint8_t *)(&msos1_string_descriptor); - *len = sizeof(msos1_string_descriptor); - - LOG_DBG("Get MS OS Descriptor v1 string"); - - return 0; - } - - return -EINVAL; -} +#include "webusb.h" +#include "msosv2.h" -/** - * @brief Handler called for vendor specific commands. This includes - * WebUSB allowed origins and MS OS 1.0 and 2.0 descriptors. - * - * @param pSetup Information about the request to execute. - * @param len Size of the buffer. - * @param data Buffer containing the request result. - * - * @return 0 on success, negative errno code on fail. - */ -int vendor_handle_req(struct usb_setup_packet *pSetup, - int32_t *len, uint8_t **data) +static void msg_cb(struct usbd_context *const usbd_ctx, + const struct usbd_msg *const msg) { - if (usb_reqtype_is_to_device(pSetup)) { - return -ENOTSUP; - } - - /* Get Allowed origins request */ - if (pSetup->bRequest == 0x01 && pSetup->wIndex == 0x01) { - *data = (uint8_t *)(&webusb_allowed_origins); - *len = sizeof(webusb_allowed_origins); - - LOG_DBG("Get webusb_allowed_origins"); + LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); - return 0; - } else if (pSetup->bRequest == 0x01 && pSetup->wIndex == 0x02) { - /* Get URL request */ - uint8_t index = USB_GET_DESCRIPTOR_INDEX(pSetup->wValue); - - if (index == 0U || index > NUMBER_OF_ALLOWED_ORIGINS) { - return -ENOTSUP; + if (usbd_can_detect_vbus(usbd_ctx)) { + if (msg->type == USBD_MSG_VBUS_READY) { + if (usbd_enable(usbd_ctx)) { + LOG_ERR("Failed to enable device support"); + } } - *data = (uint8_t *)(&webusb_origin_url); - *len = sizeof(webusb_origin_url); - - LOG_DBG("Get webusb_origin_url"); - - return 0; - } else if (pSetup->bRequest == bos_cap_msosv2.cap.bMS_VendorCode && - pSetup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { - /* Get MS OS 2.0 Descriptors request */ - *data = (uint8_t *)(&msosv2_descriptor); - *len = sizeof(msosv2_descriptor); - - LOG_DBG("Get MS OS Descriptors v2"); - - return 0; - } else if (pSetup->bRequest == 0x03 && pSetup->wIndex == 0x04) { - /* Get MS OS 1.0 Descriptors request */ - /* 0x04 means "Extended compat ID". - * Use 0x05 instead for "Extended properties". - */ - *data = (uint8_t *)(&msos1_compatid_descriptor); - *len = sizeof(msos1_compatid_descriptor); - - LOG_DBG("Get MS OS Descriptors CompatibleID"); - - return 0; + if (msg->type == USBD_MSG_VBUS_REMOVED) { + if (usbd_disable(usbd_ctx)) { + LOG_ERR("Failed to disable device support"); + } + } } - - return -ENOTSUP; } -/* Custom and Vendor request handlers */ -static struct webusb_req_handlers req_handlers = { - .custom_handler = custom_handle_req, - .vendor_handler = vendor_handle_req, -}; - int main(void) { + struct usbd_context *sample_usbd; int ret; - LOG_DBG(""); + sample_usbd = sample_usbd_setup_device(msg_cb); + if (sample_usbd == NULL) { + LOG_ERR("Failed to setup USB device"); + return -ENODEV; + } - usb_bos_register_cap((void *)&bos_cap_webusb); - usb_bos_register_cap((void *)&bos_cap_msosv2); - usb_bos_register_cap((void *)&bos_cap_lpm); + ret = usbd_add_descriptor(sample_usbd, &bos_vreq_msosv2); + if (ret) { + LOG_ERR("Failed to add MSOSv2 capability descriptor"); + return ret; + } - /* Set the custom and vendor request handlers */ - webusb_register_request_handlers(&req_handlers); + ret = usbd_add_descriptor(sample_usbd, &bos_vreq_webusb); + if (ret) { + LOG_ERR("Failed to add WebUSB capability descriptor"); + return ret; + } - ret = usb_enable(NULL); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; + ret = usbd_init(sample_usbd); + if (ret) { + LOG_ERR("Failed to initialize device support"); + return ret; } + + if (!usbd_can_detect_vbus(sample_usbd)) { + ret = usbd_enable(sample_usbd); + if (ret) { + LOG_ERR("Failed to enable device support"); + return ret; + } + } + return 0; } diff --git a/samples/subsys/usb/webusb-next/src/msosv2.h b/samples/subsys/usb/webusb/src/msosv2.h similarity index 100% rename from samples/subsys/usb/webusb-next/src/msosv2.h rename to samples/subsys/usb/webusb/src/msosv2.h diff --git a/samples/subsys/usb/webusb-next/src/sfunc.c b/samples/subsys/usb/webusb/src/sfunc.c similarity index 100% rename from samples/subsys/usb/webusb-next/src/sfunc.c rename to samples/subsys/usb/webusb/src/sfunc.c diff --git a/samples/subsys/usb/webusb/src/webusb.h b/samples/subsys/usb/webusb/src/webusb.h index 132cfb22b487b..329626d4587b6 100644 --- a/samples/subsys/usb/webusb/src/webusb.h +++ b/samples/subsys/usb/webusb/src/webusb.h @@ -1,41 +1,90 @@ /* - * Copyright (c) 2015-2019 Intel Corporation + * Copyright (c) 2016-2019 Intel Corporation + * Copyright (c) 2023-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -/** - * @file - * @brief WebUSB enabled custom class driver header file - * - * Header file for WebUSB enabled custom class driver +#ifndef ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H +#define ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H + +/* + * WebUSB platform capability and WebUSB URL descriptor. + * See https://wicg.github.io/webusb for reference. */ -#ifndef __WEBUSB_SERIAL_H__ -#define __WEBUSB_SERIAL_H__ +#define WEBUSB_REQ_GET_URL 0x02U +#define WEBUSB_DESC_TYPE_URL 0x03U +#define WEBUSB_URL_PREFIX_HTTP 0x00U +#define WEBUSB_URL_PREFIX_HTTPS 0x01U -/** - * WebUSB request handlers - */ -struct webusb_req_handlers { - /* Handler for WebUSB Vendor specific commands */ - usb_request_handler vendor_handler; - /** - * The custom request handler gets a first chance at handling - * the request before it is handed over to the 'chapter 9' request - * handler +#define SAMPLE_WEBUSB_VENDOR_CODE 0x01U +#define SAMPLE_WEBUSB_LANDING_PAGE 0x01U + +struct usb_bos_webusb_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_webusb cap; +} __packed; + +static const struct usb_bos_webusb_desc bos_cap_webusb = { + /* WebUSB Platform Capability Descriptor: + * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor */ - usb_request_handler custom_handler; + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_webusb), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + /* WebUSB Platform Capability UUID + * 3408b638-09a9-47a0-8bfd-a0768815b665 + */ + .PlatformCapabilityUUID = { + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, + 0xA0, 0x47, + 0x8B, 0xFD, + 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, + }, + }, + .cap = { + .bcdVersion = sys_cpu_to_le16(0x0100), + .bVendorCode = SAMPLE_WEBUSB_VENDOR_CODE, + .iLandingPage = SAMPLE_WEBUSB_LANDING_PAGE + } }; -/** - * @brief Register Custom and Vendor request callbacks - * - * Function to register Custom and Vendor request callbacks - * for handling requests. - * - * @param [in] handlers Pointer to WebUSB request handlers structure - */ -void webusb_register_request_handlers(struct webusb_req_handlers *handlers); +/* WebUSB URL Descriptor, see https://wicg.github.io/webusb/#webusb-descriptors */ +static const uint8_t webusb_origin_url[] = { + /* bLength, bDescriptorType, bScheme, UTF-8 encoded URL */ + 0x11, WEBUSB_DESC_TYPE_URL, WEBUSB_URL_PREFIX_HTTP, + 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', ':', '8', '0', '0', '0' +}; + +static int webusb_to_host_cb(const struct usbd_context *const ctx, + const struct usb_setup_packet *const setup, + struct net_buf *const buf) +{ + LOG_INF("Vendor callback to host"); + + if (setup->wIndex == WEBUSB_REQ_GET_URL) { + uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); + + if (index != SAMPLE_WEBUSB_LANDING_PAGE) { + return -ENOTSUP; + } + + LOG_INF("Get URL request, index %u", index); + net_buf_add_mem(buf, &webusb_origin_url, + MIN(net_buf_tailroom(buf), sizeof(webusb_origin_url))); + + return 0; + } + + return -ENOTSUP; +} + +USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_webusb, sizeof(bos_cap_webusb), &bos_cap_webusb, + SAMPLE_WEBUSB_VENDOR_CODE, webusb_to_host_cb, NULL); -#endif /* __WEBUSB_SERIAL_H__ */ +#endif /* ZEPHYR_INCLUDE_WEBUSB_DESCRIPTOR_H */ diff --git a/snippets/cdc-acm-console/cdc-acm-console.conf b/snippets/cdc-acm-console/cdc-acm-console.conf index 28103411fc3e9..99da93e536ac4 100644 --- a/snippets/cdc-acm-console/cdc-acm-console.conf +++ b/snippets/cdc-acm-console/cdc-acm-console.conf @@ -1,6 +1,5 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr USB console sample" -CONFIG_USB_DEVICE_PID=0x0004 +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y CONFIG_SERIAL=y CONFIG_CONSOLE=y diff --git a/subsys/usb/device/Kconfig b/subsys/usb/device/Kconfig index 80c71fb163563..cc5d50676a1f2 100644 --- a/subsys/usb/device/Kconfig +++ b/subsys/usb/device/Kconfig @@ -95,7 +95,6 @@ config USB_REQUEST_BUFFER_SIZE range 8 65536 default 256 if USB_DEVICE_NETWORK_RNDIS default 266 if (USB_DEVICE_BLUETOOTH && USB_DEVICE_BLUETOOTH_BIG_BUF) - default 1024 if USB_DEVICE_LOOPBACK default 128 config USB_MAX_ALT_SETTING diff --git a/subsys/usb/device/class/CMakeLists.txt b/subsys/usb/device/class/CMakeLists.txt index f4d2b39ae70e1..9911d3fb31837 100644 --- a/subsys/usb/device/class/CMakeLists.txt +++ b/subsys/usb/device/class/CMakeLists.txt @@ -3,7 +3,6 @@ zephyr_sources_ifdef(CONFIG_USB_CDC_ACM cdc_acm.c) zephyr_sources_ifdef(CONFIG_USB_MASS_STORAGE msc.c) zephyr_sources_ifdef(CONFIG_USB_DEVICE_BLUETOOTH bluetooth.c) -zephyr_sources_ifdef(CONFIG_USB_DEVICE_LOOPBACK loopback.c) add_subdirectory_ifdef(CONFIG_USB_DEVICE_AUDIO audio) add_subdirectory_ifdef(CONFIG_USB_DEVICE_NETWORK netusb) diff --git a/subsys/usb/device/class/Kconfig b/subsys/usb/device/class/Kconfig index 9761e969a56a8..96cb6abe8ba9c 100644 --- a/subsys/usb/device/class/Kconfig +++ b/subsys/usb/device/class/Kconfig @@ -9,8 +9,6 @@ source "subsys/usb/device/class/Kconfig.msc" source "subsys/usb/device/class/Kconfig.bt" -source "subsys/usb/device/class/Kconfig.test" - source "subsys/usb/device/class/netusb/Kconfig" source "subsys/usb/device/class/hid/Kconfig" diff --git a/subsys/usb/device/class/Kconfig.test b/subsys/usb/device/class/Kconfig.test deleted file mode 100644 index eac1214f0a936..0000000000000 --- a/subsys/usb/device/class/Kconfig.test +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2016 Wind River Systems, Inc. -# SPDX-License-Identifier: Apache-2.0 - -config USB_DEVICE_LOOPBACK - bool "USB Loopback Function Driver" - help - USB Loopback Function Driver - -config LOOPBACK_BULK_EP_MPS - int - depends on USB_DEVICE_LOOPBACK - default 512 if USB_DC_HAS_HS_SUPPORT - default 64 - help - Loopback Function bulk endpoint size diff --git a/subsys/usb/device/class/loopback.c b/subsys/usb/device/class/loopback.c deleted file mode 100644 index 77c5dde4bdad1..0000000000000 --- a/subsys/usb/device/class/loopback.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * USB loopback function - * - * Copyright (c) 2018 Phytec Messtechnik GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include -#include - -#include -LOG_MODULE_REGISTER(usb_loopback, CONFIG_USB_DEVICE_LOG_LEVEL); - -#define LOOPBACK_OUT_EP_ADDR 0x01 -#define LOOPBACK_IN_EP_ADDR 0x81 - -#define LOOPBACK_OUT_EP_IDX 0 -#define LOOPBACK_IN_EP_IDX 1 - -static uint8_t loopback_buf[1024]; -BUILD_ASSERT(sizeof(loopback_buf) == CONFIG_USB_REQUEST_BUFFER_SIZE); - -/* usb.rst config structure start */ -struct usb_loopback_config { - struct usb_if_descriptor if0; - struct usb_ep_descriptor if0_out_ep; - struct usb_ep_descriptor if0_in_ep; -} __packed; - -USBD_CLASS_DESCR_DEFINE(primary, 0) struct usb_loopback_config loopback_cfg = { - /* Interface descriptor 0 */ - .if0 = { - .bLength = sizeof(struct usb_if_descriptor), - .bDescriptorType = USB_DESC_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_BCC_VENDOR, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - }, - - /* Data Endpoint OUT */ - .if0_out_ep = { - .bLength = sizeof(struct usb_ep_descriptor), - .bDescriptorType = USB_DESC_ENDPOINT, - .bEndpointAddress = LOOPBACK_OUT_EP_ADDR, - .bmAttributes = USB_DC_EP_BULK, - .wMaxPacketSize = sys_cpu_to_le16(CONFIG_LOOPBACK_BULK_EP_MPS), - .bInterval = 0x00, - }, - - /* Data Endpoint IN */ - .if0_in_ep = { - .bLength = sizeof(struct usb_ep_descriptor), - .bDescriptorType = USB_DESC_ENDPOINT, - .bEndpointAddress = LOOPBACK_IN_EP_ADDR, - .bmAttributes = USB_DC_EP_BULK, - .wMaxPacketSize = sys_cpu_to_le16(CONFIG_LOOPBACK_BULK_EP_MPS), - .bInterval = 0x00, - }, -}; -/* usb.rst config structure end */ - -static void loopback_out_cb(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) -{ - uint32_t bytes_to_read; - - usb_read(ep, NULL, 0, &bytes_to_read); - LOG_DBG("ep 0x%x, bytes to read %d ", ep, bytes_to_read); - usb_read(ep, loopback_buf, bytes_to_read, NULL); -} - -static void loopback_in_cb(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) -{ - if (usb_write(ep, loopback_buf, CONFIG_LOOPBACK_BULK_EP_MPS, NULL)) { - LOG_DBG("ep 0x%x", ep); - } -} - -/* usb.rst endpoint configuration start */ -static struct usb_ep_cfg_data ep_cfg[] = { - { - .ep_cb = loopback_out_cb, - .ep_addr = LOOPBACK_OUT_EP_ADDR, - }, - { - .ep_cb = loopback_in_cb, - .ep_addr = LOOPBACK_IN_EP_ADDR, - }, -}; -/* usb.rst endpoint configuration end */ - -static void loopback_status_cb(struct usb_cfg_data *cfg, - enum usb_dc_status_code status, - const uint8_t *param) -{ - ARG_UNUSED(cfg); - - switch (status) { - case USB_DC_INTERFACE: - loopback_in_cb(ep_cfg[LOOPBACK_IN_EP_IDX].ep_addr, 0); - LOG_DBG("USB interface configured"); - break; - case USB_DC_SET_HALT: - LOG_DBG("Set Feature ENDPOINT_HALT"); - break; - case USB_DC_CLEAR_HALT: - LOG_DBG("Clear Feature ENDPOINT_HALT"); - if (*param == ep_cfg[LOOPBACK_IN_EP_IDX].ep_addr) { - loopback_in_cb(ep_cfg[LOOPBACK_IN_EP_IDX].ep_addr, 0); - } - break; - default: - break; - } -} - -/* usb.rst vendor handler start */ -static int loopback_vendor_handler(struct usb_setup_packet *setup, - int32_t *len, uint8_t **data) -{ - LOG_DBG("Class request: bRequest 0x%x bmRequestType 0x%x len %d", - setup->bRequest, setup->bmRequestType, *len); - - if (setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_DEVICE) { - return -ENOTSUP; - } - - if (usb_reqtype_is_to_device(setup) && - setup->bRequest == 0x5b) { - LOG_DBG("Host-to-Device, data %p", *data); - /* - * Copy request data in loopback_buf buffer and reuse - * it later in control device-to-host transfer. - */ - memcpy(loopback_buf, *data, - MIN(sizeof(loopback_buf), setup->wLength)); - return 0; - } - - if ((usb_reqtype_is_to_host(setup)) && - (setup->bRequest == 0x5c)) { - LOG_DBG("Device-to-Host, wLength %d, data %p", - setup->wLength, *data); - *data = loopback_buf; - *len = MIN(sizeof(loopback_buf), setup->wLength); - return 0; - } - - return -ENOTSUP; -} -/* usb.rst vendor handler end */ - -static void loopback_interface_config(struct usb_desc_header *head, - uint8_t bInterfaceNumber) -{ - ARG_UNUSED(head); - - loopback_cfg.if0.bInterfaceNumber = bInterfaceNumber; -} - -/* usb.rst device config data start */ -USBD_DEFINE_CFG_DATA(loopback_config) = { - .usb_device_description = NULL, - .interface_config = loopback_interface_config, - .interface_descriptor = &loopback_cfg.if0, - .cb_usb_status = loopback_status_cb, - .interface = { - .class_handler = NULL, - .custom_handler = NULL, - .vendor_handler = loopback_vendor_handler, - }, - .num_endpoints = ARRAY_SIZE(ep_cfg), - .endpoint = ep_cfg, -}; -/* usb.rst device config data end */ diff --git a/subsys/usb/device_next/CMakeLists.txt b/subsys/usb/device_next/CMakeLists.txt index a93d32cd10bc5..e0120dc89a82c 100644 --- a/subsys/usb/device_next/CMakeLists.txt +++ b/subsys/usb/device_next/CMakeLists.txt @@ -17,6 +17,8 @@ zephyr_library_sources( usbd_msg.c ) +add_subdirectory(app) + zephyr_library_sources_ifdef( CONFIG_USBD_SHELL usbd_shell.c diff --git a/subsys/usb/device_next/Kconfig b/subsys/usb/device_next/Kconfig index a38823db71add..52ce9d990858e 100644 --- a/subsys/usb/device_next/Kconfig +++ b/subsys/usb/device_next/Kconfig @@ -56,5 +56,6 @@ config USBD_MSG_WORK_DELAY yet ready to publish the message. The delay unit is milliseconds. rsource "class/Kconfig" +rsource "app/Kconfig.cdc_acm_serial" endif # USB_DEVICE_STACK_NEXT diff --git a/subsys/usb/device_next/app/CMakeLists.txt b/subsys/usb/device_next/app/CMakeLists.txt new file mode 100644 index 0000000000000..116d422def3e4 --- /dev/null +++ b/subsys/usb/device_next/app/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources_ifdef(CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT cdc_acm_serial.c) diff --git a/subsys/usb/device_next/app/Kconfig.cdc_acm_serial b/subsys/usb/device_next/app/Kconfig.cdc_acm_serial new file mode 100644 index 0000000000000..dba212ba9bafd --- /dev/null +++ b/subsys/usb/device_next/app/Kconfig.cdc_acm_serial @@ -0,0 +1,57 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# This file contains Kconfig options and defaults for configuring the USB +# device stack and CDC ACM instance to be used as the default serial backend +# for logging or shell. + + +menuconfig CDC_ACM_SERIAL_INITIALIZE_AT_BOOT + bool "Initialize USB device and CDC ACM UART at boot" + depends on USBD_CDC_ACM_CLASS + help + This is intended for use with cdc-acm-snippet or as a default serial + backend only in applications where no other USB features are + required, configured, and enabled. + +if CDC_ACM_SERIAL_INITIALIZE_AT_BOOT + +config CDC_ACM_SERIAL_MANUFACTURER_STRING + string "USB device manufacturer string descriptor" + default "Zephyr Project" + help + USB device manufacturer string descriptor. + +config CDC_ACM_SERIAL_PRODUCT_STRING + string "USB device product string descriptor" + default "CDC ACM serial backend" + help + USB device product string descriptor. + +config CDC_ACM_SERIAL_VID + hex "USB device Vendor ID" + default 0x2fe3 + help + You must use your own VID for samples and applications outside of + Zephyr Project. + +config CDC_ACM_SERIAL_PID + hex "USB device Product ID" + default 0x0004 + help + You must use your own PID for samples and applications outside of + Zephyr Project. + +config CDC_ACM_SERIAL_SELF_POWERED + bool "USB device Self-powered attribute" + help + Set the Self-powered attribute in the configuration. + +config CDC_ACM_SERIAL_MAX_POWER + int "USB device bMaxPower value" + default 125 + range 0 250 + help + bMaxPower value in the configuration in 2 mA units. + +endif #CDC_ACM_SERIAL_INITIALIZE_AT_BOOT diff --git a/subsys/usb/device_next/app/cdc_acm_serial.c b/subsys/usb/device_next/app/cdc_acm_serial.c new file mode 100644 index 0000000000000..5a63a58814cc0 --- /dev/null +++ b/subsys/usb/device_next/app/cdc_acm_serial.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(cdc_acm_serial, LOG_LEVEL_DBG); + +/* + * This is intended for use with cdc-acm-snippet or as a default serial backend + * only in applications where no other USB features are required, configured, + * and enabled. This code only registers the first CDC-ACM instance. + */ + +USBD_DEVICE_DEFINE(cdc_acm_serial, + DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), + CONFIG_CDC_ACM_SERIAL_VID, CONFIG_CDC_ACM_SERIAL_PID); + +USBD_DESC_LANG_DEFINE(cdc_acm_serial_lang); +USBD_DESC_MANUFACTURER_DEFINE(cdc_acm_serial_mfr, CONFIG_CDC_ACM_SERIAL_MANUFACTURER_STRING); +USBD_DESC_PRODUCT_DEFINE(cdc_acm_serial_product, CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING); +USBD_DESC_SERIAL_NUMBER_DEFINE(cdc_acm_serial_sn); + +USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "FS Configuration"); +USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "HS Configuration"); + +static const uint8_t attributes = IS_ENABLED(CONFIG_CDC_ACM_SERIAL_SELF_POWERED) ? + USB_SCD_SELF_POWERED : 0; + +USBD_CONFIGURATION_DEFINE(cdc_acm_serial_fs_config, + attributes, + CONFIG_CDC_ACM_SERIAL_MAX_POWER, &fs_cfg_desc); + +USBD_CONFIGURATION_DEFINE(cdc_acm_serial_hs_config, + attributes, + CONFIG_CDC_ACM_SERIAL_MAX_POWER, &hs_cfg_desc); + +static int cdc_acm_serial_init_device(void) +{ + int err; + + err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_lang); + if (err) { + LOG_ERR("Failed to initialize language descriptor (%d)", err); + return err; + } + + err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_mfr); + if (err) { + LOG_ERR("Failed to initialize manufacturer descriptor (%d)", err); + return err; + } + + err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_product); + if (err) { + LOG_ERR("Failed to initialize product descriptor (%d)", err); + return err; + } + + err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_sn); + if (err) { + LOG_ERR("Failed to initialize SN descriptor (%d)", err); + return err; + } + + if (usbd_caps_speed(&cdc_acm_serial) == USBD_SPEED_HS) { + err = usbd_add_configuration(&cdc_acm_serial, USBD_SPEED_HS, + &cdc_acm_serial_hs_config); + if (err) { + LOG_ERR("Failed to add High-Speed configuration"); + return err; + } + + err = usbd_register_class(&cdc_acm_serial, "cdc_acm_0", USBD_SPEED_HS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return err; + } + } + + err = usbd_add_configuration(&cdc_acm_serial, USBD_SPEED_FS, + &cdc_acm_serial_fs_config); + if (err) { + LOG_ERR("Failed to add Full-Speed configuration"); + return err; + } + + err = usbd_register_class(&cdc_acm_serial, "cdc_acm_0", USBD_SPEED_FS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return err; + } + + err = usbd_init(&cdc_acm_serial); + if (err) { + LOG_ERR("Failed to initialize device support"); + return err; + } + + err = usbd_enable(&cdc_acm_serial); + if (err) { + LOG_ERR("Failed to enable device support"); + return err; + } + + return 0; +} + +SYS_INIT(cdc_acm_serial_init_device, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/subsys/usb/device_next/class/Kconfig.cdc_acm b/subsys/usb/device_next/class/Kconfig.cdc_acm index 997ded105f4eb..3d282560b1daa 100644 --- a/subsys/usb/device_next/class/Kconfig.cdc_acm +++ b/subsys/usb/device_next/class/Kconfig.cdc_acm @@ -10,6 +10,7 @@ config USBD_CDC_ACM_CLASS select SERIAL_SUPPORT_INTERRUPT select RING_BUFFER select UART_INTERRUPT_DRIVEN + default y help USB device CDC ACM class implementation. diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index c67f995006e6d..dff1af8e7a265 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -114,6 +114,8 @@ struct cdc_acm_uart_data { * the TX FIFO during the user callback execution. */ bool zlp_needed; + /* Trace whether uart_irq_update() was called or not */ + bool irq_updated; /* UART API IRQ callback */ uart_irq_callback_user_data_t cb; /* UART API user callback data */ @@ -513,8 +515,8 @@ static int usbd_cdc_acm_init(struct usbd_class_data *const c_data) return 0; } -static int cdc_acm_send_notification(const struct device *dev, - const uint16_t serial_state) +static inline int cdc_acm_send_notification(const struct device *dev, + const uint16_t serial_state) { struct cdc_acm_notification notification = { .bmRequestType = 0xA1, @@ -549,7 +551,11 @@ static int cdc_acm_send_notification(const struct device *dev, net_buf_add_mem(buf, ¬ification, sizeof(struct cdc_acm_notification)); ret = usbd_ep_enqueue(c_data, buf); - /* FIXME: support for sync transfers */ + if (ret) { + net_buf_unref(buf); + return ret; + } + k_sem_take(&data->notif_sem, K_FOREVER); return ret; @@ -828,6 +834,8 @@ static int cdc_acm_irq_update(const struct device *dev) data->tx_fifo.irq = false; } + data->irq_updated = true; + return 1; } @@ -862,12 +870,18 @@ static void cdc_acm_irq_cb_handler(struct k_work *work) data->rx_fifo.altered = false; data->rx_fifo.irq = false; data->tx_fifo.irq = false; + data->irq_updated = false; if (atomic_test_bit(&data->state, CDC_ACM_IRQ_RX_ENABLED) || atomic_test_bit(&data->state, CDC_ACM_IRQ_TX_ENABLED)) { data->cb(usbd_class_get_private(c_data), data->cb_data); } + if (!data->irq_updated) { + LOG_ERR("User callback did not call uart_irq_update()"); + return; + } + if (data->rx_fifo.altered) { LOG_DBG("rx fifo altered, submit work"); cdc_acm_work_submit(&data->rx_fifo_work); diff --git a/tests/bluetooth/shell/cdc_acm.conf b/tests/bluetooth/shell/cdc_acm.conf index c69afa40dd860..62a206917967b 100644 --- a/tests/bluetooth/shell/cdc_acm.conf +++ b/tests/bluetooth/shell/cdc_acm.conf @@ -1,6 +1,6 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr BT Shell" -CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y +CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="Zephyr BT Shell" CONFIG_UART_LINE_CTRL=y CONFIG_SHELL_BACKEND_SERIAL_CHECK_DTR=y diff --git a/tests/bluetooth/shell/src/main.c b/tests/bluetooth/shell/src/main.c index 87114ad381af3..d019d5716fb50 100644 --- a/tests/bluetooth/shell/src/main.c +++ b/tests/bluetooth/shell/src/main.c @@ -128,7 +128,7 @@ int main(void) uint32_t dtr = 0; dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart)); - if (!device_is_ready(dev) || usb_enable(NULL)) { + if (!device_is_ready(dev)) { return 0; } diff --git a/tests/bluetooth/shell/testcase.yaml b/tests/bluetooth/shell/testcase.yaml index 2d45c4a18a875..18d133e24f7fb 100644 --- a/tests/bluetooth/shell/testcase.yaml +++ b/tests/bluetooth/shell/testcase.yaml @@ -44,7 +44,7 @@ tests: extra_args: - EXTRA_CONF_FILE=cdc_acm.conf - DTC_OVERLAY_FILE="usb.overlay" - depends_on: usb_device + depends_on: usbd platform_allow: - native_sim - native_sim/native/64 diff --git a/tests/drivers/uart/uart_basic_api/overlay-usb.conf b/tests/drivers/uart/uart_basic_api/overlay-usb.conf index 3af32b0ea5317..208a828f8c842 100644 --- a/tests/drivers/uart/uart_basic_api/overlay-usb.conf +++ b/tests/drivers/uart/uart_basic_api/overlay-usb.conf @@ -1,4 +1,5 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC ACM UART" +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y +CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="Zephyr CDC ACM UART" CONFIG_UART_LINE_CTRL=y CONFIG_TEST_LOGGING_DEFAULTS=n diff --git a/tests/drivers/uart/uart_basic_api/src/main.c b/tests/drivers/uart/uart_basic_api/src/main.c index 42ccc5530f3cb..bd2b52f25fcea 100644 --- a/tests/drivers/uart/uart_basic_api/src/main.c +++ b/tests/drivers/uart/uart_basic_api/src/main.c @@ -11,7 +11,6 @@ * @} */ -#include #include "test_uart.h" #ifdef CONFIG_SHELL @@ -52,7 +51,7 @@ void *uart_basic_setup(void) uint32_t dtr = 0; dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); - if (!device_is_ready(dev) || usb_enable(NULL)) { + if (!device_is_ready(dev)) { return NULL; } diff --git a/tests/drivers/uart/uart_basic_api/testcase.yaml b/tests/drivers/uart/uart_basic_api/testcase.yaml index bbda79b810ac4..22900388d69c9 100644 --- a/tests/drivers/uart/uart_basic_api/testcase.yaml +++ b/tests/drivers/uart/uart_basic_api/testcase.yaml @@ -47,7 +47,7 @@ tests: - drivers - usb filter: CONFIG_UART_CONSOLE - depends_on: usb_device + depends_on: usbd harness: keyboard drivers.uart.basic_api.shell_ke17z9_uart: tags: