Skip to content

Commit 5b72932

Browse files
committed
Add rp2040 reset interface
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 <dhs@frame.work>
1 parent 9388622 commit 5b72932

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

tmk_core/protocol/chibios/usb_main.c

+16
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "usb_device_state.h"
4444
#include "usb_descriptor.h"
4545
#include "usb_driver.h"
46+
#include "platforms/bootloader.h"
4647

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

655+
if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
656+
dprint(" TYPE_CLASS, RECIPIENT_INTERFACE\n");
657+
if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_HOST2DEV) {
658+
if (usbp->setup[4] == RP2040_RESET_INTERFACE) {
659+
switch (usbp->setup[1]) { /* bRequest */
660+
case 0x01: // RESET_REQUEST_BOOTSEL
661+
case 0x02: // RESET_REQUEST_FLASH
662+
dprint(" Reset interface\n");
663+
bootloader_jump();
664+
break;
665+
}
666+
}
667+
}
668+
}
669+
654670
/* Handle HID class specific requests */
655671
if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
656672
switch (usbp->setup[0] & USB_RTYPE_DIR_MASK) {

tmk_core/protocol/usb_descriptor.c

+13
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,19 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
738738
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
739739
},
740740
#endif
741+
.Rp2040_Reset_Interface = {
742+
.Header = {
743+
.Size = sizeof(USB_Descriptor_Interface_t),
744+
.Type = DTYPE_Interface
745+
},
746+
.InterfaceNumber = RP2040_RESET_INTERFACE,
747+
.AlternateSetting = 0x00,
748+
.TotalEndpoints = 2,
749+
.Class = 0xFF,
750+
.SubClass = 0x00, // RESET_INTERFACE_SUBCLASS
751+
.Protocol = 0x01, // RESET_INTERFACE_PROTOCOL
752+
.InterfaceStrIndex = NO_DESCRIPTOR
753+
},
741754

742755
#ifdef CONSOLE_ENABLE
743756
/*

tmk_core/protocol/usb_descriptor.h

+4
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ typedef struct {
9292
USB_Descriptor_Endpoint_t Shared_INEndpoint;
9393
#endif
9494

95+
USB_Descriptor_Interface_t Rp2040_Reset_Interface;
96+
9597
#ifdef CONSOLE_ENABLE
9698
// Console HID Interface
9799
USB_Descriptor_Interface_t Console_Interface;
@@ -173,6 +175,8 @@ enum usb_interfaces {
173175
SHARED_INTERFACE,
174176
#endif
175177

178+
RP2040_RESET_INTERFACE,
179+
176180
#ifdef CONSOLE_ENABLE
177181
CONSOLE_INTERFACE,
178182
#endif

0 commit comments

Comments
 (0)