* Add some extra defines to customise behaviour of STDIO_USB_RESET modes * Tweaks to STDIO_USB_RESET defines
115 lines
3.8 KiB
C
115 lines
3.8 KiB
C
/**
|
|
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
#include "tusb.h"
|
|
|
|
#include "pico/bootrom.h"
|
|
|
|
#if PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE && !(PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL || PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT)
|
|
#warning PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE has been selected but neither PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL nor PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT have been selected.
|
|
#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;
|
|
|
|
static void resetd_init(void) {
|
|
}
|
|
|
|
static void resetd_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) {
|
|
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass &&
|
|
RESET_INTERFACE_SUBCLASS == itf_desc->bInterfaceSubClass &&
|
|
RESET_INTERFACE_PROTOCOL == itf_desc->bInterfaceProtocol, 0);
|
|
|
|
uint16_t const drv_len = sizeof(tusb_desc_interface_t);
|
|
TU_VERIFY(max_len >= drv_len, 0);
|
|
|
|
itf_num = itf_desc->bInterfaceNumber;
|
|
return drv_len;
|
|
}
|
|
|
|
// Support for parameterized reset via vendor interface control request
|
|
static bool resetd_control_request_cb(uint8_t __unused rhport, tusb_control_request_t const *request) {
|
|
if (request->wIndex == itf_num) {
|
|
|
|
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL
|
|
if (request->bRequest == RESET_REQUEST_BOOTSEL) {
|
|
#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
|
|
uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
|
|
#else
|
|
uint gpio_mask = 0u;
|
|
#endif
|
|
#if !PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED
|
|
if (request->wValue & 0x100) {
|
|
gpio_mask = 1u << (request->wValue >> 9u);
|
|
}
|
|
#endif
|
|
reset_usb_boot(gpio_mask, (request->wValue & 0x7f) | PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
|
|
// does not return, otherwise we'd return true
|
|
}
|
|
#endif
|
|
|
|
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT
|
|
if (request->bRequest == RESET_REQUEST_FLASH) {
|
|
watchdog_reboot(0, SRAM_END, PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS);
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool resetd_control_complete_cb(uint8_t __unused rhport, tusb_control_request_t __unused const *request) {
|
|
return true;
|
|
}
|
|
|
|
static bool resetd_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_request = resetd_control_request_cb,
|
|
.control_complete = resetd_control_complete_cb,
|
|
.xfer_cb = resetd_xfer_cb,
|
|
.sof = NULL
|
|
};
|
|
|
|
// 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;
|
|
}
|
|
#endif
|
|
|
|
#if PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE
|
|
// Support for default BOOTSEL reset by changing baud rate
|
|
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) {
|
|
if (p_line_coding->bit_rate == PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE) {
|
|
#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
|
|
const uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
|
|
#else
|
|
const uint gpio_mask = 0u;
|
|
#endif
|
|
reset_usb_boot(gpio_mask, PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
|
|
}
|
|
}
|
|
#endif
|
|
|