Skip to content

Commit

Permalink
Add rp2040 reset interface
Browse files Browse the repository at this point in the history
This is the same one implemented in the rp-pico SDK.

See [definition](https://github.com/raspberrypi/pico-sdk/blob/2.0.0/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c#L109)
and [usage](https://github.com/raspberrypi/pico-sdk/blob/2.0.0/src/rp2_common/pico_stdio_usb/reset_interface.c).

Since QMK does not use the USB descriptors from the SDK, we can't just
use `#define FOO PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE` and
have to implement it ourselves.

Picotool writes a control transfer that arrives in `usb_request_hook_cb`
in `usbp->setup` as bytes `21 01 00 00 03 00 00 00`.

FWUPD also implements this same reset protocol
https://github.com/fwupd/fwupd/tree/main/plugins/rp-pico
Using this reset mechanism allows a standard reset into bootloader mode
from where UF2 update is easy.

The qmk commandline could also implement it to make debugging more
seamless.

Signed-off-by: Daniel Schaefer <[email protected]>
  • Loading branch information
JohnAZoidberg committed Nov 19, 2024
1 parent 9388622 commit 5b72932
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
16 changes: 16 additions & 0 deletions tmk_core/protocol/chibios/usb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "usb_device_state.h"
#include "usb_descriptor.h"
#include "usb_driver.h"
#include "platforms/bootloader.h"

#ifdef NKRO_ENABLE
# include "keycode_config.h"
Expand Down Expand Up @@ -651,6 +652,21 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
* 4,5: (LSB,MSB) wIndex
* 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */

if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
dprint(" TYPE_CLASS, RECIPIENT_INTERFACE\n");
if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_HOST2DEV) {
if (usbp->setup[4] == RP2040_RESET_INTERFACE) {
switch (usbp->setup[1]) { /* bRequest */
case 0x01: // RESET_REQUEST_BOOTSEL
case 0x02: // RESET_REQUEST_FLASH
dprint(" Reset interface\n");
bootloader_jump();
break;
}
}
}
}

/* Handle HID class specific requests */
if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
switch (usbp->setup[0] & USB_RTYPE_DIR_MASK) {
Expand Down
13 changes: 13 additions & 0 deletions tmk_core/protocol/usb_descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,19 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
},
#endif
.Rp2040_Reset_Interface = {
.Header = {
.Size = sizeof(USB_Descriptor_Interface_t),
.Type = DTYPE_Interface
},
.InterfaceNumber = RP2040_RESET_INTERFACE,
.AlternateSetting = 0x00,
.TotalEndpoints = 2,
.Class = 0xFF,
.SubClass = 0x00, // RESET_INTERFACE_SUBCLASS
.Protocol = 0x01, // RESET_INTERFACE_PROTOCOL
.InterfaceStrIndex = NO_DESCRIPTOR
},

#ifdef CONSOLE_ENABLE
/*
Expand Down
4 changes: 4 additions & 0 deletions tmk_core/protocol/usb_descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ typedef struct {
USB_Descriptor_Endpoint_t Shared_INEndpoint;
#endif

USB_Descriptor_Interface_t Rp2040_Reset_Interface;

#ifdef CONSOLE_ENABLE
// Console HID Interface
USB_Descriptor_Interface_t Console_Interface;
Expand Down Expand Up @@ -173,6 +175,8 @@ enum usb_interfaces {
SHARED_INTERFACE,
#endif

RP2040_RESET_INTERFACE,

#ifdef CONSOLE_ENABLE
CONSOLE_INTERFACE,
#endif
Expand Down

0 comments on commit 5b72932

Please sign in to comment.