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

[Feature] Add support for HID Bootloader generation #6

Merged
merged 5 commits into from
Jul 18, 2021
Merged
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@
Documentation/
node_modules/
Bootloaders/DFU/Keyboard.h
.vscode/ipch/
Bootloaders/HID/Keyboard.h
.vscode/ipch/
.DS_Store
42 changes: 40 additions & 2 deletions Bootloaders/HID/BootloaderHID.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,31 @@ int main(void)
/* Setup hardware required for the bootloader */
SetupHardware();

/* Turn on first LED on the board to indicate that the bootloader has started */
LEDs_SetAllLEDs(LEDS_LED1 | LEDS_LED2);

/* Enable global interrupts so that the USB stack can function */
GlobalInterruptEnable();

while (RunBootloader)
#if (BOARD == BOARD_QMK)
USB_USBTask();
uint16_t keypress = 0;
#endif

while (RunBootloader) {
USB_USBTask();
#if (BOARD == BOARD_QMK)
bool pressed = (PIN(QMK_ESC_INPUT) & NUM(QMK_ESC_INPUT));
if ((keypress > 5000) && pressed) {
break;
}
if (pressed) {
keypress++;
} else {
keypress = 0;
}
#endif
}

/* Wait a short time to end all USB transactions and then disconnect */
_delay_us(1000);
Expand Down Expand Up @@ -113,8 +133,27 @@ static void SetupHardware(void)
MCUCR = (1 << IVCE);
MCUCR = (1 << IVSEL);

#if (BOARD == BOARD_QMK)
// output setup
DDR(QMK_ESC_OUTPUT) |= NUM(QMK_ESC_OUTPUT);
PORT(QMK_ESC_OUTPUT) |= NUM(QMK_ESC_OUTPUT);

// input setup
DDR(QMK_ESC_INPUT) |= NUM(QMK_ESC_INPUT);
#endif

/* Initialize USB subsystem */
USB_Init();
LEDs_Init();

/* Bootloader active LED toggle timer initialization */
TIMSK1 = (1 << TOIE1);
TCCR1B = ((1 << CS11) | (1 << CS10));
}

/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
ISR(TIMER1_OVF_vect, ISR_BLOCK) {
LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
}

/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
Expand Down Expand Up @@ -208,4 +247,3 @@ void EVENT_USB_Device_ControlRequest(void)
break;
}
}
drashna marked this conversation as resolved.
Show resolved Hide resolved

2 changes: 2 additions & 0 deletions Bootloaders/HID/BootloaderHID.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
#include "Descriptors.h"

#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Platform/Platform.h>
#include <LUFA/Common/Common.h>

/* Preprocessor Checks: */
#if !defined(__OPTIMIZE_SIZE__)
Expand Down
49 changes: 46 additions & 3 deletions Bootloaders/HID/Descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
*/

#include "Descriptors.h"
#include "Keyboard.h"

#ifndef MANUFACTURER
#define MANUFACTURER QMK
#endif
#ifndef PRODUCT
#define PRODUCT Keyboard
#endif

/** HID class report descriptor. This is a special descriptor constructed with values from the
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
Expand Down Expand Up @@ -77,8 +85,8 @@ const USB_Descriptor_Device_t DeviceDescriptor =
.ProductID = 0x2067,
.ReleaseNumber = VERSION_BCD(0,0,1),

.ManufacturerStrIndex = NO_DESCRIPTOR,
.ProductStrIndex = NO_DESCRIPTOR,
.ManufacturerStrIndex = STRING_ID_Manufacturer,
.ProductStrIndex = STRING_ID_Product,
.SerialNumStrIndex = NO_DESCRIPTOR,

.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
Expand Down Expand Up @@ -144,6 +152,24 @@ const USB_Descriptor_Configuration_t ConfigurationDescriptor =
},
};

/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host requests
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
*/
const USB_Descriptor_String_t LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);

/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
const USB_Descriptor_String_t ManufacturerString = USB_STRING_DESCRIPTOR(LSTR(MANUFACTURER));

/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
const USB_Descriptor_String_t ProductString = USB_STRING_DESCRIPTOR(LSTR(PRODUCT));

/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
Expand All @@ -155,6 +181,7 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);

const void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
Expand All @@ -180,8 +207,24 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
Address = &HIDReport;
Size = sizeof(HIDReport);
}
else if (DescriptorType == DTYPE_String) {
if (DescriptorNumber == STRING_ID_Language)
{
Address = &LanguageString;
Size = LanguageString.Header.Size;
}
else if (DescriptorNumber == STRING_ID_Manufacturer)
{
Address = &ManufacturerString;
Size = ManufacturerString.Header.Size;
}
else if (DescriptorNumber == STRING_ID_Product)
{
Address = &ProductString;
Size = ProductString.Header.Size;
}
}

*DescriptorAddress = Address;
return Size;
}
drashna marked this conversation as resolved.
Show resolved Hide resolved

19 changes: 17 additions & 2 deletions Bootloaders/HID/Descriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,16 @@
{
INTERFACE_ID_GenericHID = 0, /**< GenericHID interface descriptor ID */
};

/** Enum for the device string descriptor IDs within the device. Each string descriptor should
* have a unique ID index associated with it, which can be used to refer to the string from
* other descriptors.
*/
enum StringDescriptors_t
{
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
STRING_ID_Product = 2, /**< Product string ID */
};
/* Macros: */
/** Endpoint address of the HID data IN endpoint. */
#define HID_IN_EPADDR (ENDPOINT_DIR_IN | 1)
Expand All @@ -76,5 +85,11 @@
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);

#endif
// convert to L string
#define LSTR(s) XLSTR(s)
#define XLSTR(s) L ## #s
// convert to string
#define STR(s) XSTR(s)
#define XSTR(s) #s

#endif
14 changes: 7 additions & 7 deletions Bootloaders/HID/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@

# Run "make help" for target help.

MCU = at90usb1287
ARCH = AVR8
BOARD = USBKEY
F_CPU = 8000000
F_USB = $(F_CPU)
MCU ?= atmega32u4
ARCH ?= AVR8
BOARD = QMK
F_CPU ?= 16000000
F_USB ?= $(F_CPU)
OPTIMIZATION = s
TARGET = BootloaderHID
SRC = $(TARGET).c Descriptors.c $(LUFA_SRC_USB)
Expand All @@ -27,8 +27,8 @@ LTO = Y
# Flash size and bootloader section sizes of the target, in KB. These must
# match the target's total FLASH size and the bootloader size set in the
# device's fuses.
FLASH_SIZE_KB := 128
BOOT_SECTION_SIZE_KB := 8
FLASH_SIZE_KB ?= 32
BOOT_SECTION_SIZE_KB ?= 4

# Bootloader address calculation formulas
# Do not modify these macros, but rather modify the dependent values above.
Expand Down
Loading