Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for restart to bootloader via USB command #14212

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions quantum/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ static void print_version(void) {
#ifdef LTO_ENABLE
" LTO"
#endif
#ifdef USB_FEATURE_ENABLE
" USB_FEATURE_ENABLE"
#endif

" " STR(BOOTLOADER_SIZE) "\n");

Expand Down
1 change: 1 addition & 0 deletions show_options.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ BUILD_OPTION_NAMES = \
BOOTMAGIC_ENABLE \
MOUSEKEY_ENABLE \
EXTRAKEY_ENABLE \
USB_FEATURE_ENABLE \
CONSOLE_ENABLE \
COMMAND_ENABLE \
NKRO_ENABLE \
Expand Down
5 changes: 5 additions & 0 deletions tmk_core/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
SHARED_EP_ENABLE = yes
endif

ifeq ($(strip $(USB_FEATURE_ENABLE)), yes)
TMK_COMMON_DEFS += -DUSB_FEATURE_ENABLE
SHARED_EP_ENABLE = yes
endif

ifeq ($(strip $(RAW_ENABLE)), yes)
TMK_COMMON_DEFS += -DRAW_ENABLE
endif
Expand Down
76 changes: 70 additions & 6 deletions tmk_core/protocol/chibios/usb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "wait.h"
#include "usb_descriptor.h"
#include "usb_driver.h"
#include "bootloader.h"

#ifdef NKRO_ENABLE
# include "keycode_config.h"
Expand Down Expand Up @@ -93,6 +94,11 @@ uint8_t extra_report_blank[3] = {0};
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B

/* HID Report Types */
#define HID_SET_REPORT_INPUT 0x01
#define HID_SET_REPORT_OUTPUT 0x02
#define HID_SET_REPORT_FEATURE 0x03

/*
* Handles the GET_DESCRIPTOR callback
*
Expand Down Expand Up @@ -505,6 +511,16 @@ static uint16_t get_hword(uint8_t *p) {
return hw;
}

static uint32_t get_dword(uint8_t *p) {
uint32_t dw;

dw = (uint32_t)*p++;
dw |= (uint32_t)*p++ << 8U;
dw |= (uint32_t)*p++ << 16U;
dw |= (uint32_t)*p++ << 24U;
return dw;
}

/*
* Appendix G: HID Request Support Requirements
*
Expand All @@ -518,7 +534,7 @@ static uint16_t get_hword(uint8_t *p) {
* Other Device Required Optional Optional Optional Optional Optional
*/

static uint8_t set_report_buf[2] __attribute__((aligned(2)));
static uint8_t set_report_buf[9] __attribute__((aligned(4)));
static void set_led_transfer_cb(USBDriver *usbp) {
if (usbp->setup[6] == 2) { /* LSB(wLength) */
uint8_t report_id = set_report_buf[0];
Expand All @@ -530,6 +546,32 @@ static void set_led_transfer_cb(USBDriver *usbp) {
}
}

#ifndef MAGIC0
#define MAGIC0 0x5AA555AA
#endif
#ifndef MAGIC1
#define MAGIC1 0xCC3300FF
#endif

static void set_feature_cb(USBDriver *usbp) {
uint8_t offset = 0;
bool bootloader_restart_check = true;
if (usbp->setup[6] == 9) { /* LSB(wLength) */
uint8_t report_id = set_report_buf[0];
if (report_id == REPORT_ID_CONSUMER){
offset = 1;
}
else {
bootloader_restart_check = false;
}
}
if (bootloader_restart_check){
if( (get_dword(set_report_buf + offset) == MAGIC0) && (get_dword(set_report_buf + offset + 4) == MAGIC1)){
bootloader_jump();
}
}
}

/* Callback for SETUP request on the endpoint 0 (control) */
static bool usb_request_hook_cb(USBDriver *usbp) {
const USBDescriptor *dp;
Expand Down Expand Up @@ -584,13 +626,35 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
case USB_RTYPE_DIR_HOST2DEV:
switch (usbp->setup[1]) { /* bRequest */
case HID_SET_REPORT:
switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
case KEYBOARD_INTERFACE:
switch (usbp->setup[3]) { /* report type: input/output/feature */
#if defined(SHARED_EP_ENABLE)
case HID_SET_REPORT_FEATURE:
switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
case SHARED_INTERFACE:
usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_feature_cb);
return TRUE;
break;
}
break;
#endif


/* control leds if report arrived for keyboard interface */
case HID_SET_REPORT_OUTPUT:
switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
case KEYBOARD_INTERFACE:
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
case SHARED_INTERFACE:
case SHARED_INTERFACE:
#endif
usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
return TRUE;
usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
return TRUE;
break;
}
break;


/* input report is not handled */
default:
break;
}
break;
Expand Down
8 changes: 7 additions & 1 deletion tmk_core/protocol/usb_descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
#endif

#ifdef EXTRAKEY_ENABLE
#if defined(EXTRAKEY_ENABLE) || defined(USB_FEATURE_ENABLE)
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
HID_RI_USAGE(8, 0x80), // System Control
HID_RI_COLLECTION(8, 0x01), // Application
Expand All @@ -187,6 +187,12 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
HID_RI_REPORT_COUNT(8, 1),
HID_RI_REPORT_SIZE(8, 16),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
HID_RI_USAGE(8, 0x0), // undefined
HID_RI_LOGICAL_MINIMUM(8, 0x80),
HID_RI_LOGICAL_MAXIMUM(8, 0x7f),
HID_RI_REPORT_SIZE(8, 8),
HID_RI_REPORT_COUNT(8, 8),
HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0),
#endif

Expand Down