diff --git a/.gitignore b/.gitignore index 0730578d3c..125f413c22 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ Documentation/ node_modules/ Bootloaders/DFU/Keyboard.h -.vscode/ipch/ \ No newline at end of file +Bootloaders/HID/Keyboard.h +.vscode/ipch/ +.DS_Store diff --git a/Bootloaders/HID/BootloaderHID.c b/Bootloaders/HID/BootloaderHID.c index 8973bd8128..50154b47c5 100644 --- a/Bootloaders/HID/BootloaderHID.c +++ b/Bootloaders/HID/BootloaderHID.c @@ -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); @@ -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 @@ -208,4 +247,3 @@ void EVENT_USB_Device_ControlRequest(void) break; } } - diff --git a/Bootloaders/HID/BootloaderHID.h b/Bootloaders/HID/BootloaderHID.h index 3ed03d8889..d15636c437 100644 --- a/Bootloaders/HID/BootloaderHID.h +++ b/Bootloaders/HID/BootloaderHID.h @@ -49,7 +49,9 @@ #include "Descriptors.h" #include + #include #include + #include /* Preprocessor Checks: */ #if !defined(__OPTIMIZE_SIZE__) diff --git a/Bootloaders/HID/Descriptors.c b/Bootloaders/HID/Descriptors.c index 6a82c230d3..b9d64eb1f2 100644 --- a/Bootloaders/HID/Descriptors.c +++ b/Bootloaders/HID/Descriptors.c @@ -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 @@ -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 @@ -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 @@ -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; @@ -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; } - diff --git a/Bootloaders/HID/Descriptors.h b/Bootloaders/HID/Descriptors.h index d3290ec8a3..e7c95cb22b 100644 --- a/Bootloaders/HID/Descriptors.h +++ b/Bootloaders/HID/Descriptors.h @@ -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) @@ -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 diff --git a/Bootloaders/HID/makefile b/Bootloaders/HID/makefile index 8e46b49252..0be231426f 100644 --- a/Bootloaders/HID/makefile +++ b/Bootloaders/HID/makefile @@ -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) @@ -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. diff --git a/LUFA/Drivers/Board/AVR8/QMK/LEDs.h b/LUFA/Drivers/Board/AVR8/QMK/LEDs.h index bcfe07cdde..07dc5b6482 100644 --- a/LUFA/Drivers/Board/AVR8/QMK/LEDs.h +++ b/LUFA/Drivers/Board/AVR8/QMK/LEDs.h @@ -54,54 +54,110 @@ along with this program. If not, see . #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. #endif - #define B0 0x30 - #define B1 0x31 - #define B2 0x32 - #define B3 0x33 - #define B4 0x34 - #define B5 0x35 - #define B6 0x36 - #define B7 0x37 - #define C0 0x60 - #define C1 0x61 - #define C2 0x62 - #define C3 0x63 - #define C4 0x64 - #define C5 0x65 - #define C6 0x66 - #define C7 0x67 - #define D0 0x90 - #define D1 0x91 - #define D2 0x92 - #define D3 0x93 - #define D4 0x94 - #define D5 0x95 - #define D6 0x96 - #define D7 0x97 - #define E0 0xC0 - #define E1 0xC1 - #define E2 0xC2 - #define E3 0xC3 - #define E4 0xC4 - #define E5 0xC5 - #define E6 0xC6 - #define E7 0xC7 - #define F0 0xF0 - #define F1 0xF1 - #define F2 0xF2 - #define F3 0xF3 - #define F4 0xF4 - #define F5 0xF5 - #define F6 0xF6 - #define F7 0xF7 - #define A0 0x00 - #define A1 0x01 - #define A2 0x02 - #define A3 0x03 - #define A4 0x04 - #define A5 0x05 - #define A6 0x06 - #define A7 0x07 +# define PORT_SHIFTER 4 // this may be 4 for all AVR chips +# define NO_PIN (~0) + +// If you want to add more to this list, reference the PINx definitions in these header +// files: https://github.com/vancegroup-mirrors/avr-libc/tree/master/avr-libc/include/avr + +# if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) +# define ADDRESS_BASE 0x00 +# define PINB_ADDRESS 0x3 +# define PINC_ADDRESS 0x6 +# define PIND_ADDRESS 0x9 +# define PINE_ADDRESS 0xC +# define PINF_ADDRESS 0xF +# elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) +# define ADDRESS_BASE 0x00 +# define PINB_ADDRESS 0x3 +# define PINC_ADDRESS 0x6 +# define PIND_ADDRESS 0x9 +# elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) +# define ADDRESS_BASE 0x00 +# define PINA_ADDRESS 0x0 +# define PINB_ADDRESS 0x3 +# define PINC_ADDRESS 0x6 +# define PIND_ADDRESS 0x9 +# define PINE_ADDRESS 0xC +# define PINF_ADDRESS 0xF +# else +# error "Pins are not defined" +# endif + +/* I/O pins */ +# define PINDEF(port, pin) ((PIN##port##_ADDRESS << PORT_SHIFTER) | pin) + +# ifdef PORTA +# define A0 PINDEF(A, 0) +# define A1 PINDEF(A, 1) +# define A2 PINDEF(A, 2) +# define A3 PINDEF(A, 3) +# define A4 PINDEF(A, 4) +# define A5 PINDEF(A, 5) +# define A6 PINDEF(A, 6) +# define A7 PINDEF(A, 7) +# endif +# ifdef PORTB +# define B0 PINDEF(B, 0) +# define B1 PINDEF(B, 1) +# define B2 PINDEF(B, 2) +# define B3 PINDEF(B, 3) +# define B4 PINDEF(B, 4) +# define B5 PINDEF(B, 5) +# define B6 PINDEF(B, 6) +# define B7 PINDEF(B, 7) +# endif +# ifdef PORTC +# define C0 PINDEF(C, 0) +# define C1 PINDEF(C, 1) +# define C2 PINDEF(C, 2) +# define C3 PINDEF(C, 3) +# define C4 PINDEF(C, 4) +# define C5 PINDEF(C, 5) +# define C6 PINDEF(C, 6) +# define C7 PINDEF(C, 7) +# endif +# ifdef PORTD +# define D0 PINDEF(D, 0) +# define D1 PINDEF(D, 1) +# define D2 PINDEF(D, 2) +# define D3 PINDEF(D, 3) +# define D4 PINDEF(D, 4) +# define D5 PINDEF(D, 5) +# define D6 PINDEF(D, 6) +# define D7 PINDEF(D, 7) +# endif +# ifdef PORTE +# define E0 PINDEF(E, 0) +# define E1 PINDEF(E, 1) +# define E2 PINDEF(E, 2) +# define E3 PINDEF(E, 3) +# define E4 PINDEF(E, 4) +# define E5 PINDEF(E, 5) +# define E6 PINDEF(E, 6) +# define E7 PINDEF(E, 7) +# endif +# ifdef PORTF +# define F0 PINDEF(F, 0) +# define F1 PINDEF(F, 1) +# define F2 PINDEF(F, 2) +# define F3 PINDEF(F, 3) +# define F4 PINDEF(F, 4) +# define F5 PINDEF(F, 5) +# define F6 PINDEF(F, 6) +# define F7 PINDEF(F, 7) +# endif + +# ifndef __ASSEMBLER__ +# define _PIN_ADDRESS(p, offset) _SFR_IO8(ADDRESS_BASE + (p >> PORT_SHIFTER) + offset) +// Port X Input Pins Address +# define PINx_ADDRESS(p) _PIN_ADDRESS(p, 0) +// Port X Data Direction Register, 0:input 1:output +# define DDRx_ADDRESS(p) _PIN_ADDRESS(p, 1) +// Port X Data Register +# define PORTx_ADDRESS(p) _PIN_ADDRESS(p, 2) +# endif + #include "Keyboard.h" @@ -112,10 +168,10 @@ along with this program. If not, see . #define QMK_ESC_OUTPUT D5 #endif #ifndef QMK_LED - #define QMK_LED E6 + #define QMK_LED NO_PIN #endif #ifndef QMK_SPEAKER - #define QMK_SPEAKER C6 + #define QMK_SPEAKER NO_PIN #endif #define DDR(pin) _SFR_IO8(((pin) >> 4) + 1)