Skip to content

Commit

Permalink
Add support for restart to bootloader via USB command
Browse files Browse the repository at this point in the history
  • Loading branch information
stdvar committed Aug 29, 2021
1 parent aed8bac commit e2230d7
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 7 deletions.
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

0 comments on commit e2230d7

Please sign in to comment.