diff --git a/src/cmake/rp2_common.cmake b/src/cmake/rp2_common.cmake index 273839f70..c51f4f0b0 100644 --- a/src/cmake/rp2_common.cmake +++ b/src/cmake/rp2_common.cmake @@ -121,6 +121,7 @@ if (NOT PICO_BARE_METAL) endif() pico_add_subdirectory(rp2_common/tinyusb) pico_add_subdirectory(rp2_common/pico_stdio_usb) + pico_add_subdirectory(rp2_common/pico_usb_reset_interface) pico_add_subdirectory(rp2_common/pico_i2c_slave) # networking libraries - note dependency order is important diff --git a/src/common/pico_usb_reset_interface_headers/BUILD.bazel b/src/common/pico_usb_reset_interface_headers/BUILD.bazel index 880792dd3..20efac5dd 100644 --- a/src/common/pico_usb_reset_interface_headers/BUILD.bazel +++ b/src/common/pico_usb_reset_interface_headers/BUILD.bazel @@ -2,6 +2,6 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "pico_usb_reset_interface_headers", - hdrs = ["include/pico/usb_reset_interface.h"], + hdrs = ["include/pico/usb_reset_interface.h", "include/pico/usb_reset_interface_config.h", "include/pico/usb_reset_interface_device.h", "include/pico/usb_reset_interface_tusb.h"], includes = ["include"], ) diff --git a/src/common/pico_usb_reset_interface_headers/CMakeLists.txt b/src/common/pico_usb_reset_interface_headers/CMakeLists.txt index 6be755edc..f1927a890 100644 --- a/src/common/pico_usb_reset_interface_headers/CMakeLists.txt +++ b/src/common/pico_usb_reset_interface_headers/CMakeLists.txt @@ -1,6 +1,4 @@ # don't use pico_add_library here as picotool includes it directly add_library(pico_usb_reset_interface_headers INTERFACE) -add_library(pico_usb_reset_interface INTERFACE) -target_link_libraries(pico_usb_reset_interface INTERFACE pico_usb_reset_interface_headers) target_include_directories(pico_usb_reset_interface_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) diff --git a/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_config.h b/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_config.h new file mode 100644 index 000000000..e2bbbcde7 --- /dev/null +++ b/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_config.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PICO_USB_RESET_INTERFACE_CONFIG_H +#define _PICO_USB_RESET_INTERFACE_CONFIG_H + +// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_usb_reset_interface + +// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW, Whether pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE) is active low, type=bool, default=0, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW +#define PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW 0 +#endif + +// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED, Whether the pin specified by PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED is fixed or can be modified by picotool over the VENDOR USB interface, type=bool, default=0, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED +#define PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED 0 +#endif + +// Any modes disabled here can't be re-enabled by picotool via VENDOR_INTERFACE. +// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK, Optionally disable either the mass storage interface (bit 0) or the PICOBOOT interface (bit 1) when entering BOOTSEL mode via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=3, default=0, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK +#define PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK 0u +#endif + +// PICO_CONFIG: PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE, Enable/disable resetting into BOOTSEL mode via an additional VENDOR USB interface - enables picotool based reset, type=bool, default=1 if application is not using TinyUSB directly, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE +#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE +#define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE 1 +#else +#define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE 0 +#endif +#endif + +// PICO_CONFIG: PICO_STDIO_USB_RESET_INCLUDE_APP_DRIVER_CB, Set to 0 if your application defines usbd_app_driver_get_cb, type=bool, default=1 when using pico_usb_reset_interface, 0 otherwise, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_INCLUDE_APP_DRIVER_CB +#define PICO_STDIO_USB_RESET_INCLUDE_APP_DRIVER_CB LIB_PICO_STDIO_USB +#endif + +// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL, If vendor reset interface is included allow rebooting to BOOTSEL mode, type=bool, default=1, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL +#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL 1 +#endif + +// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT, If vendor reset interface is included allow rebooting with regular flash boot, type=bool, default=1, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT +#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT 1 +#endif + +// PICO_CONFIG: PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS, Delay in ms before rebooting via regular flash boot, default=100, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS +#define PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS 100 +#endif + +// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR, If vendor reset interface is included add support for Microsoft OS 2.0 Descriptor, type=bool, default=1 if application is not using TinyUSB directly, 0 otherwise, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR +#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE +#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR 1 +#else +#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR 0 +#endif +#endif + +// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF, If vendor reset interface is included the USB interface number for the reset interface, type=int, default=2 if application is not using TinyUSB directly, undefined otherwise, group=pico_usb_reset_interface +#ifndef PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF +#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE +#define PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF 2 +#elif PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR +#error Must set PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF to the reset interface number when using PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR with custom USB descriptors +#endif +#endif + +#endif \ No newline at end of file diff --git a/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_device.h b/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_device.h new file mode 100644 index 000000000..4346fe76d --- /dev/null +++ b/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_device.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PICO_USB_RESET_INTERFACE_DEVICE_H +#define _PICO_USB_RESET_INTERFACE_DEVICE_H + +/** \file usb_reset_interface_device.h + * \defgroup pico_usb_reset_interface pico_usb_reset_interface + * + * \brief Functionality to enable the RP-series microcontroller to be reset over the USB interface. + * + * This library can be used to enable the RP-series microcontroller to be reset over the USB interface. + * + * This functionality is included by default when using the `pico_stdio_usb` library and not using TinyUSB directly. + * + * To add this functionality to a project using TinyUSB directly, you need to: + * 1. Link the pico_usb_reset_interface library, and include the `pico/usb_reset_interface_device.h` header file where needed. + * 2. Define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE=1 + * 3. Add `TUD_RPI_RESET_DESCRIPTOR(, )` to your USB descriptors (length is `TUD_RPI_RESET_DESC_LEN`) + * 4. Check if your project has an existing `usbd_app_driver_get_cb` function: + * - If it does, you need to add the `pico_usb_reset_interface_driver` to the drivers returned + * - If it does not, and you aren't using the `pico_stdio_usb` library, you need to define `PICO_STDIO_USB_RESET_INCLUDE_APP_DRIVER_CB=1` + * 5. Check if your project has an existing Microsoft OS 2.0 Descriptor: + * - If it does, you need to add the Function Subset header `RPI_RESET_MS_OS_20_DESCRIPTOR()` to your Microsoft OS 2.0 Descriptor (length is `RPI_RESET_MS_OS_20_DESC_LEN`) + * - If it does not, you need to define `PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR=1` and `PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF=` + */ + +#include "pico/usb_reset_interface.h" +#include "pico/usb_reset_interface_config.h" +#include "pico/usb_reset_interface_tusb.h" + +#endif \ No newline at end of file diff --git a/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_tusb.h b/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_tusb.h new file mode 100644 index 000000000..bcafdc126 --- /dev/null +++ b/src/common/pico_usb_reset_interface_headers/include/pico/usb_reset_interface_tusb.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PICO_USB_RESET_INTERFACE_TUSB_H +#define _PICO_USB_RESET_INTERFACE_TUSB_H + +// Interface descriptor +#define TUD_RPI_RESET_DESC_LEN 9 +#define TUD_RPI_RESET_DESCRIPTOR(_itfnum, _stridx) \ + /* Interface */\ + TUD_RPI_RESET_DESC_LEN, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_VENDOR_SPECIFIC, RESET_INTERFACE_SUBCLASS, RESET_INTERFACE_PROTOCOL, _stridx + + +// Microsoft OS 2.0 Descriptor +#define RPI_RESET_MS_OS_20_DESC_LEN (0x08 + 0x14 + 0x80) +#define RPI_RESET_MS_OS_20_DESCRIPTOR(itf_num) \ + /* Function Subset header: length, type, first interface, reserved, subset length */ \ + U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), itf_num, 0, U16_TO_U8S_LE(RPI_RESET_MS_OS_20_DESC_LEN), \ + \ + /* MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID */ \ + U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* sub-compatible */ \ + \ + /* MS OS 2.0 Registry property descriptor: length, type */ \ + U16_TO_U8S_LE(0x0080), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), \ + U16_TO_U8S_LE(0x0001), U16_TO_U8S_LE(0x0028), /* wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUID" in UTF-16 */ \ + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, \ + 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, \ + U16_TO_U8S_LE(0x004E), /* wPropertyDataLength */ \ + /* Vendor-defined Property Data: {bc7398c1-73cd-4cb7-98b8-913a8fca7bf6} */ \ + '{', 0, 'b', 0, 'c', 0, '7', 0, '3', 0, '9', 0, \ + '8', 0, 'c', 0, '1', 0, '-', 0, '7', 0, '3', 0, \ + 'c', 0, 'd', 0, '-', 0, '4', 0, 'c', 0, 'b', 0, \ + '7', 0, '-', 0, '9', 0, '8', 0, 'b', 0, '8', 0, \ + '-', 0, '9', 0, '1', 0, '3', 0, 'a', 0, '8', 0, \ + 'f', 0, 'c', 0, 'a', 0, '7', 0, 'b', 0, 'f', 0, \ + '6', 0, '}', 0, 0, 0 + +#include "stdint.h" +#include "device/usbd_pvt.h" + +void pico_usb_reset_interface_init(void); +void pico_usb_reset_interface_reset(uint8_t __unused rhport); +uint16_t pico_usb_reset_interface_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool pico_usb_reset_interface_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const * request); +bool pico_usb_reset_interface_xfer_cb(uint8_t __unused rhport, uint8_t __unused ep_addr, xfer_result_t __unused result, uint32_t __unused xferred_bytes); + +static usbd_class_driver_t const pico_usb_reset_interface_driver = +{ +#if CFG_TUSB_DEBUG >= 2 + .name = "RESET", +#endif + .init = pico_usb_reset_interface_init, + .reset = pico_usb_reset_interface_reset, + .open = pico_usb_reset_interface_open, + .control_xfer_cb = pico_usb_reset_interface_control_xfer_cb, + .xfer_cb = pico_usb_reset_interface_xfer_cb, + .sof = NULL +}; + +#endif \ No newline at end of file diff --git a/src/rp2_common/pico_stdio_usb/BUILD.bazel b/src/rp2_common/pico_stdio_usb/BUILD.bazel index 1e8817142..9a48e3684 100644 --- a/src/rp2_common/pico_stdio_usb/BUILD.bazel +++ b/src/rp2_common/pico_stdio_usb/BUILD.bazel @@ -55,7 +55,6 @@ cc_library( cc_library( name = "pico_stdio_usb_enabled", srcs = [ - "reset_interface.c", "stdio_usb.c", "stdio_usb_descriptors.c", ], @@ -71,10 +70,9 @@ cc_library( "//src/common/pico_binary_info", "//src/common/pico_sync", "//src/rp2_common/hardware_irq", - "//src/rp2_common/hardware_watchdog", - "//src/rp2_common/pico_bootrom", "//src/rp2_common/pico_stdio:pico_stdio_headers", "//src/rp2_common/pico_unique_id", + "//src/rp2_common/pico_usb_reset_interface", ], # Ensure `stdio_usb_descriptors.c` isn't affected by link order. alwayslink = True, diff --git a/src/rp2_common/pico_stdio_usb/CMakeLists.txt b/src/rp2_common/pico_stdio_usb/CMakeLists.txt index 8dc672182..cad6a1453 100644 --- a/src/rp2_common/pico_stdio_usb/CMakeLists.txt +++ b/src/rp2_common/pico_stdio_usb/CMakeLists.txt @@ -4,7 +4,6 @@ if (TARGET tinyusb_device_unmarked) target_include_directories(pico_stdio_usb_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) target_sources(pico_stdio_usb INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/reset_interface.c ${CMAKE_CURRENT_LIST_DIR}/stdio_usb.c ${CMAKE_CURRENT_LIST_DIR}/stdio_usb_descriptors.c ) diff --git a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h index 5cf2e1f66..5015d7efa 100644 --- a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h +++ b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h @@ -91,53 +91,6 @@ #define PICO_STDIO_USB_DEINIT_DELAY_MS 110 #endif -// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_stdio_usb - -// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW, Whether pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE) is active low, type=bool, default=0, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW -#define PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW 0 -#endif - -// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED, Whether the pin specified by PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED is fixed or can be modified by picotool over the VENDOR USB interface, type=bool, default=0, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED -#define PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED 0 -#endif - -// Any modes disabled here can't be re-enabled by picotool via VENDOR_INTERFACE. -// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK, Optionally disable either the mass storage interface (bit 0) or the PICOBOOT interface (bit 1) when entering BOOTSEL mode via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=3, default=0, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK -#define PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK 0u -#endif - -// PICO_CONFIG: PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE, Enable/disable resetting into BOOTSEL mode via an additional VENDOR USB interface - enables picotool based reset, type=bool, default=1 if application is not using TinyUSB directly, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE -#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE -#define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE 1 -#else -#define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE 0 -#endif -#endif - -// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL, If vendor reset interface is included allow rebooting to BOOTSEL mode, type=bool, default=1, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL -#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL 1 -#endif - -// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT, If vendor reset interface is included allow rebooting with regular flash boot, type=bool, default=1, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT -#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT 1 -#endif - -// PICO_CONFIG: PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR, If vendor reset interface is included add support for Microsoft OS 2.0 Descriptor, type=bool, default=1, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR -#define PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR 1 -#endif - -// PICO_CONFIG: PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS, Delay in ms before rebooting via regular flash boot, default=100, group=pico_stdio_usb -#ifndef PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS -#define PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS 100 -#endif - // PICO_CONFIG: PICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS, Whether `pico_stdio_usb` provides the USB descriptors needed for USB communication, type=bool, default=1 if the application is not using tinyUSB directly, group=pico_stdio_usb #ifndef PICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS #if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE diff --git a/src/rp2_common/pico_stdio_usb/include/tusb_config.h b/src/rp2_common/pico_stdio_usb/include/tusb_config.h index 0b9e4306b..302ff0ad8 100644 --- a/src/rp2_common/pico_stdio_usb/include/tusb_config.h +++ b/src/rp2_common/pico_stdio_usb/include/tusb_config.h @@ -48,14 +48,7 @@ #endif // We use a vendor specific interface but with our own driver -// Vendor driver only used for Microsoft OS 2.0 descriptor -#if !PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR #define CFG_TUD_VENDOR (0) -#else -#define CFG_TUD_VENDOR (1) -#define CFG_TUD_VENDOR_RX_BUFSIZE (256) -#define CFG_TUD_VENDOR_TX_BUFSIZE (256) -#endif #endif #endif diff --git a/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c b/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c index b805e8fb2..95796f6ac 100644 --- a/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c +++ b/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c @@ -27,7 +27,7 @@ */ #include "pico/stdio_usb.h" -#include "pico/stdio_usb/reset_interface.h" +#include "pico/usb_reset_interface_device.h" #include "pico/unique_id.h" #include "tusb.h" @@ -53,7 +53,6 @@ #define USBD_PRODUCT "Pico" #endif -#define TUD_RPI_RESET_DESC_LEN 9 #if !PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE #define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) #else @@ -72,6 +71,7 @@ #define USBD_ITF_MAX (2) #else #define USBD_ITF_RPI_RESET (2) +static_assert(USBD_ITF_RPI_RESET == PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF, "USBD_ITF_RPI_RESET must be equal to PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF"); #define USBD_ITF_MAX (3) #endif @@ -115,10 +115,6 @@ static const tusb_desc_device_t usbd_desc_device = { .bNumConfigurations = 1, }; -#define TUD_RPI_RESET_DESCRIPTOR(_itfnum, _stridx) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_VENDOR_SPECIFIC, RESET_INTERFACE_SUBCLASS, RESET_INTERFACE_PROTOCOL, _stridx, - static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, USBD_CONFIGURATION_DESCRIPTOR_ATTRIBUTE, USBD_MAX_POWER_MA), @@ -127,7 +123,7 @@ static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), #if PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE - TUD_RPI_RESET_DESCRIPTOR(USBD_ITF_RPI_RESET, USBD_STR_RPI_RESET) + TUD_RPI_RESET_DESCRIPTOR(USBD_ITF_RPI_RESET, USBD_STR_RPI_RESET), #endif }; diff --git a/src/rp2_common/pico_usb_reset_interface/BUILD.bazel b/src/rp2_common/pico_usb_reset_interface/BUILD.bazel new file mode 100644 index 000000000..3ec1fcd82 --- /dev/null +++ b/src/rp2_common/pico_usb_reset_interface/BUILD.bazel @@ -0,0 +1,21 @@ +load("//bazel:defs.bzl", "compatible_with_config", "compatible_with_rp2", "incompatible_with_config") +load("//bazel/util:sdk_define.bzl", "pico_sdk_define") + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "pico_usb_reset_interface", + srcs = [ + "usb_reset_interface.c", + ], + defines = [ + "LIB_PICO_USB_RESET_INTERFACE=1", + ], + target_compatible_with = compatible_with_rp2(), + deps = [ + "//src/common/pico_usb_reset_interface_headers", + "//bazel/config:PICO_TINYUSB_LIB", + "//src/rp2_common/hardware_watchdog", + "//src/rp2_common/pico_bootrom", + ], +) diff --git a/src/rp2_common/pico_usb_reset_interface/CMakeLists.txt b/src/rp2_common/pico_usb_reset_interface/CMakeLists.txt new file mode 100644 index 000000000..f2f7d307a --- /dev/null +++ b/src/rp2_common/pico_usb_reset_interface/CMakeLists.txt @@ -0,0 +1,11 @@ +if (TARGET tinyusb_device_unmarked) + pico_add_impl_library(pico_usb_reset_interface) + + target_sources(pico_usb_reset_interface INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/usb_reset_interface.c + ) + + target_link_libraries(pico_usb_reset_interface INTERFACE + tinyusb_device_unmarked + ) +endif() diff --git a/src/rp2_common/pico_stdio_usb/reset_interface.c b/src/rp2_common/pico_usb_reset_interface/usb_reset_interface.c similarity index 64% rename from src/rp2_common/pico_stdio_usb/reset_interface.c rename to src/rp2_common/pico_usb_reset_interface/usb_reset_interface.c index 26afa3de1..2e144312e 100644 --- a/src/rp2_common/pico_stdio_usb/reset_interface.c +++ b/src/rp2_common/pico_usb_reset_interface/usb_reset_interface.c @@ -6,6 +6,7 @@ #include "tusb.h" #include "pico/bootrom.h" +#include "pico/usb_reset_interface_device.h" #if !defined(LIB_TINYUSB_HOST) @@ -14,9 +15,7 @@ #endif #if PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE -#include "pico/stdio_usb/reset_interface.h" #include "hardware/watchdog.h" -#include "device/usbd_pvt.h" static uint8_t itf_num; @@ -24,8 +23,7 @@ static uint8_t itf_num; // Support for Microsoft OS 2.0 descriptor #define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) -#define MS_OS_20_DESC_LEN 166 -#define USBD_ITF_RPI_RESET 2 +#define MS_OS_20_DESC_LEN (RPI_RESET_MS_OS_20_DESC_LEN + 0x0A) uint8_t const desc_bos[] = { @@ -48,27 +46,7 @@ static const uint8_t desc_ms_os_20[] = // Set header: length, type, windows version, total length U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN), - // Function Subset header: length, type, first interface, reserved, subset length - U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), USBD_ITF_RPI_RESET, 0, U16_TO_U8S_LE(0x009C), - - // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID - U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible - - // MS OS 2.0 Registry property descriptor: length, type - U16_TO_U8S_LE(0x0080), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), - U16_TO_U8S_LE(0x0001), U16_TO_U8S_LE(0x0028), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUID" in UTF-16 - 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, - 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, - U16_TO_U8S_LE(0x004E), // wPropertyDataLength - // Vendor-defined Property Data: {bc7398c1-73cd-4cb7-98b8-913a8fca7bf6} - '{', 0, 'b', 0, 'c', 0, '7', 0, '3', 0, '9', 0, - '8', 0, 'c', 0, '1', 0, '-', 0, '7', 0, '3', 0, - 'c', 0, 'd', 0, '-', 0, '4', 0, 'c', 0, 'b', 0, - '7', 0, '-', 0, '9', 0, '8', 0, 'b', 0, '8', 0, - '-', 0, '9', 0, '1', 0, '3', 0, 'a', 0, '8', 0, - 'f', 0, 'c', 0, 'a', 0, '7', 0, 'b', 0, 'f', 0, - '6', 0, '}', 0, 0, 0 + RPI_RESET_MS_OS_20_DESCRIPTOR(PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF) }; TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size"); @@ -90,14 +68,14 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ } #endif -static void resetd_init(void) { +void pico_usb_reset_interface_init(void) { } -static void resetd_reset(uint8_t __unused rhport) { +void pico_usb_reset_interface_reset(uint8_t __unused rhport) { itf_num = 0; } -static uint16_t resetd_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +uint16_t pico_usb_reset_interface_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass && RESET_INTERFACE_SUBCLASS == itf_desc->bInterfaceSubClass && RESET_INTERFACE_PROTOCOL == itf_desc->bInterfaceProtocol, 0); @@ -110,7 +88,7 @@ static uint16_t resetd_open(uint8_t __unused rhport, tusb_desc_interface_t const } // Support for parameterized reset via vendor interface control request -static bool resetd_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const * request) { +bool pico_usb_reset_interface_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const * request) { // nothing to do with DATA & ACK stage if (stage != CONTROL_STAGE_SETUP) return true; @@ -147,29 +125,18 @@ static bool resetd_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_ return false; } -static bool resetd_xfer_cb(uint8_t __unused rhport, uint8_t __unused ep_addr, xfer_result_t __unused result, uint32_t __unused xferred_bytes) { +bool pico_usb_reset_interface_xfer_cb(uint8_t __unused rhport, uint8_t __unused ep_addr, xfer_result_t __unused result, uint32_t __unused xferred_bytes) { return true; } -static usbd_class_driver_t const _resetd_driver = -{ -#if CFG_TUSB_DEBUG >= 2 - .name = "RESET", -#endif - .init = resetd_init, - .reset = resetd_reset, - .open = resetd_open, - .control_xfer_cb = resetd_control_xfer_cb, - .xfer_cb = resetd_xfer_cb, - .sof = NULL -}; - +#if PICO_STDIO_USB_RESET_INCLUDE_APP_DRIVER_CB // Implement callback to add our custom driver usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) { *driver_count = 1; - return &_resetd_driver; + return &pico_usb_reset_interface_driver; } #endif +#endif #if PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE // Support for default BOOTSEL reset by changing baud rate