diff --git a/firmware/TODO b/firmware/TODO new file mode 100644 index 00000000..7905bbae --- /dev/null +++ b/firmware/TODO @@ -0,0 +1,2 @@ +* toggle nkro function +* nkro send keys / add/remove keys by bits if nkro enabled diff --git a/firmware/keyboard/ergodox/layout/common/definitions.h b/firmware/keyboard/ergodox/layout/common/definitions.h index 7f50b2e3..3ba05e24 100644 --- a/firmware/keyboard/ergodox/layout/common/definitions.h +++ b/firmware/keyboard/ergodox/layout/common/definitions.h @@ -24,6 +24,7 @@ #include "../../../../../firmware/lib/usb.h" #include "../../../../../firmware/lib/usb/usage-page/keyboard.h" #include "../../../../../firmware/lib/layout/key-functions.h" +#include "../../../../../firmware/lib/layout/mouse.h" #include "../../../../../firmware/lib/layout/layer-stack.h" #include "../../../../../firmware/keyboard.h" diff --git a/firmware/keyboard/ergodox/layout/common/keys.c.h b/firmware/keyboard/ergodox/layout/common/keys.c.h index e1afc073..40a822c4 100644 --- a/firmware/keyboard/ergodox/layout/common/keys.c.h +++ b/firmware/keyboard/ergodox/layout/common/keys.c.h @@ -209,6 +209,19 @@ void R(shR2kcap) (void) { KF(2_keys_capslock)(false, KEYBOARD__RightShift); } void P(btldr) (void) { KF(jump_to_bootloader)(); } void R(btldr) (void) {} +/** + * mouse left click + */ + +void P(MclkL) (void) { KF(mouse_buttons)(1, 0, 0); } +void R(MclkL) (void) { KF(mouse_buttons)(0, 0, 0); } + +/** + * nkro toggle + */ + +void P(tnkro) (void) { KF(toggle_nkro)(); } +void R(tnkro) (void) {} // ---------------------------------------------------------------------------- // --- layer ------------------------------------------------------------------ diff --git a/firmware/keyboard/ergodox/layout/repa.c b/firmware/keyboard/ergodox/layout/repa.c new file mode 100644 index 00000000..e5a783b8 --- /dev/null +++ b/firmware/keyboard/ergodox/layout/repa.c @@ -0,0 +1,167 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) 2013 Ben Blazak + * Released under The MIT License (see "doc/licenses/MIT.md") + * Project located at + * ------------------------------------------------------------------------- */ + +/** description + * A Dvorak layout adapted from the default Kinesis layout. The position of + * the symbol keys on the function layer was (roughly) taken from the Arensito + * layout. + * + * Implements the "layout" section of '.../firmware/keyboard.h' + */ + + +#include "./common/definitions.h" + +// ---------------------------------------------------------------------------- +// matrix control +// ---------------------------------------------------------------------------- + +#include "./common/exec_key.c.h" + + +// ---------------------------------------------------------------------------- +// LED control +// ---------------------------------------------------------------------------- + +void kb__led__logical_on(char led) { + switch(led) { + case 'N': kb__led__on(1); break; // numlock + case 'C': kb__led__on(2); break; // capslock + case 'S': kb__led__on(3); break; // scroll lock + case 'O': break; // compose + case 'K': break; // kana + }; +} + +void kb__led__logical_off(char led) { + switch(led) { + case 'N': kb__led__off(1); break; // numlock + case 'C': kb__led__off(2); break; // capslock + case 'S': kb__led__off(3); break; // scroll lock + case 'O': break; // compose + case 'K': break; // kana + }; +} + + +// ---------------------------------------------------------------------------- +// keys +// ---------------------------------------------------------------------------- + +#include "./common/keys.c.h" + +KEYS__LAYER__NUM_PUSH(10, 3); +KEYS__LAYER__NUM_POP(10); + + +// ---------------------------------------------------------------------------- +// layout +// ---------------------------------------------------------------------------- + +#include "./common/matrix.h" + + +static _layout_t _layout = { + +// ............................................................................ + + MATRIX_LAYER( // layer 0 : default +// macro, unused, + K, nop, +// left hand ...... ......... ......... ......... ......... ......... ......... + equal, 1, 2, 3, 4, 5, esc, + tab, quote, comma, period, p, y, lpu1l1, + bkslash, a, o, e, u, i, +shL2kcap, semicol, q, j, k, x, lpupo1l1, + guiL, grave, bkslash, arrowL, arrowR, + ctrlL, altL, + nop, nop, home, + bs, del, end, +// right hand ..... ......... ......... ......... ......... ......... ......... + btldr, 6, 7, 8, 9, 0, dash, + MclkL, f, g, c, r, l, brktR, + d, h, t, n, s, slash, + tnkro, b, m, w, v, z, shR2kcap, + arrowL, arrowD, arrowU, arrowR, guiR, + altR, ctrlR, + pageU, nop, nop, + pageD, enter, space ), + +// ............................................................................ + + MATRIX_LAYER( // layer 1 : function and symbol keys +// macro, unused, + K, nop, +// left hand ...... ......... ......... ......... ......... ......... ......... + nop, F1, F2, F3, F4, F5, F11, + transp, braceL, braceR, brktL, brktR, nop, lpo1l1, + transp, semicol, slash, dash, kp0, colon, + transp, kp6, kp7, kp8, kp9, plus, lpupo2l2, + transp, transp, transp, transp, transp, + transp, transp, + transp, transp, transp, + transp, transp, transp, +// right hand ..... ......... ......... ......... ......... ......... ......... + F12, F6, F7, F8, F9, F10, power, + transp, nop, undersc, lessThan, grtrThan, dollar, volumeU, + bkslash, kp1, parenL, parenR, equal, volumeD, + lpupo2l2, asterisk, kp2, kp3, kp4, kp5, mute, + transp, transp, transp, transp, transp, + transp, transp, + transp, transp, transp, + transp, transp, transp ), + +// ............................................................................ + + MATRIX_LAYER( // layer 2 : keyboard functions +// macro, unused, + K, nop, +// left hand ...... ......... ......... ......... ......... ......... ......... + btldr, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, + nop, nop, + nop, nop, nop, + nop, nop, nop, +// right hand ..... ......... ......... ......... ......... ......... ......... + nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, + nop, nop, + nop, nop, nop, + nop, nop, nop ), + +// ............................................................................ + + MATRIX_LAYER( // layer 3 : numpad +// macro, unused, + K, nop, +// left hand ...... ......... ......... ......... ......... ......... ......... + transp, transp, transp, transp, transp, transp, transp, + transp, transp, transp, transp, transp, transp, transp, + transp, transp, transp, transp, transp, transp, + transp, transp, transp, transp, transp, transp, transp, + transp, ins, transp, transp, transp, + transp, transp, + transp, transp, transp, + transp, transp, transp, +// right hand ..... ......... ......... ......... ......... ......... ......... + numPop, transp, numPop, equal, kpDiv, kpMul, transp, + transp, transp, kp7, kp8, kp9, kpSub, transp, + transp, kp4, kp5, kp6, kpAdd, transp, + transp, transp, kp1, kp2, kp3, kpEnter, transp, + transp, transp, period, kpEnter, transp, + transp, transp, + transp, transp, transp, + transp, transp, kp0 ), + +// ............................................................................ +}; + diff --git a/firmware/keyboard/ergodox/led.c b/firmware/keyboard/ergodox/led.c index 1a68830e..705f9f11 100644 --- a/firmware/keyboard/ergodox/led.c +++ b/firmware/keyboard/ergodox/led.c @@ -35,16 +35,18 @@ void kb__led__on(uint8_t led) { case 3: (DDRB |= (1<<7)); break; // bottommost case 4: break; case 5: break; + case 6: (PORTD |= (1<<6)); break; // teensy }; } void kb__led__off(uint8_t led) { switch(led) { - case 1: (DDRB &= ~(1<<5)); break; // topmost - case 2: (DDRB &= ~(1<<6)); break; // middle - case 3: (DDRB &= ~(1<<7)); break; // bottommost - case 4: break; - case 5: break; + case 1: (DDRB &= ~(1<<5)); break; // topmost + case 2: (DDRB &= ~(1<<6)); break; // middle + case 3: (DDRB &= ~(1<<7)); break; // bottommost + case 4: break; + case 5: break; + case 6: (PORTD &= ~(1<<6)); break; // teensy }; } @@ -55,6 +57,7 @@ void kb__led__set(uint8_t led, float n) { case 3: (OCR1C = (uint8_t)((n) * 0xFF)); break; // bottommost case 4: break; case 5: break; + case 6: break; }; } diff --git a/firmware/keyboard/ergodox/options.mk b/firmware/keyboard/ergodox/options.mk index a965c14f..08627db5 100644 --- a/firmware/keyboard/ergodox/options.mk +++ b/firmware/keyboard/ergodox/options.mk @@ -21,21 +21,26 @@ F_CPU := 16000000 # processor speed, in Hz; max value is 16000000 (16MHz); must match # initialization in source -KEYBOARD_LAYOUT := qwerty--kinesis-mod +KEYBOARD_LAYOUT := repa # default layout for this keyboard KEYBOARD_LAYOUTS := \ colemak--kinesis-mod \ dvorak--kinesis-mod \ - qwerty--kinesis-mod + qwerty--kinesis-mod \ + repa # a list of all available layouts for this keyboard +MOUSE_ENABLE := true +NKRO_ENABLE := true + # ----------------------------------------------------------------------------- $(call include_options_once,lib/eeprom) $(call include_options_once,lib/twi) $(call include_options_once,lib/layout/eeprom-macro) $(call include_options_once,lib/layout/key-functions) +$(call include_options_once,lib/layout/mouse) $(call include_options_once,lib/layout/layer-stack) # ----------------------------------------------------------------------------- diff --git a/firmware/lib/layout/key-functions.h b/firmware/lib/layout/key-functions.h index 32821e6d..f63aa86a 100644 --- a/firmware/lib/layout/key-functions.h +++ b/firmware/lib/layout/key-functions.h @@ -33,6 +33,8 @@ void key_functions__toggle_capslock (void); void key_functions__type_byte_hex (uint8_t byte); void key_functions__type_string (const char * string); +// nkro +void key_functions__toggle_nkro (void); // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- diff --git a/firmware/lib/layout/key-functions/device/atmega32u4.c b/firmware/lib/layout/key-functions/device/atmega32u4.c index 53dbc72c..bf6f51a8 100644 --- a/firmware/lib/layout/key-functions/device/atmega32u4.c +++ b/firmware/lib/layout/key-functions/device/atmega32u4.c @@ -39,4 +39,3 @@ void key_functions__jump_to_bootloader(void) { PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; asm volatile("jmp 0x7E00"); } - diff --git a/firmware/lib/layout/key-functions/special.c b/firmware/lib/layout/key-functions/special.c index 9d945b4a..593e30df 100644 --- a/firmware/lib/layout/key-functions/special.c +++ b/firmware/lib/layout/key-functions/special.c @@ -43,6 +43,12 @@ void key_functions__toggle_capslock(void) { usb__kb__send_report(); } +// nkro toggle + +void key_functions__toggle_nkro(void) { + usb__kb__toggle_nkro(); +} + /* * TODO: try using number pad numbers; see how it works */ diff --git a/firmware/lib/layout/mouse.h b/firmware/lib/layout/mouse.h new file mode 100644 index 00000000..dec38d5d --- /dev/null +++ b/firmware/lib/layout/mouse.h @@ -0,0 +1,24 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) 2013 Gyuri Horak + * Released under The MIT License (see "doc/licenses/MIT.md") + * Project located at + * ------------------------------------------------------------------------- */ + +/** + * Mouse related key functions + * + * Prefix: `key_functions__` + */ + + +#ifndef ERGODOX_FIRMWARE__FIRMWARE__LIB__LAYOUT__MOUSE__H +#define ERGODOX_FIRMWARE__FIRMWARE__LIB__LAYOUT__MOUSE__H +// ---------------------------------------------------------------------------- + +#include + +void key_functions__mouse_left_click (void); +void key_functions__mouse_buttons(uint8_t left, uint8_t middle, uint8_t right); + +// ---------------------------------------------------------------------------- +#endif // ERGODOX_FIRMWARE__FIRMWARE__LIB__LAYOUT__MOUSE__H diff --git a/firmware/lib/layout/mouse/mouse.c b/firmware/lib/layout/mouse/mouse.c new file mode 100644 index 00000000..a2577703 --- /dev/null +++ b/firmware/lib/layout/mouse/mouse.c @@ -0,0 +1,28 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) 2013 Gyuri Horak + * Released under The MIT License (see "doc/licenses/MIT.md") + * Project located at + * ------------------------------------------------------------------------- */ + +#include +#include "../../../../firmware/lib/usb.h" +#include "../../../../firmware/keyboard.h" + +// +void key_functions__mouse_buttons(uint8_t left, uint8_t middle, uint8_t right) +{ + uint8_t mask=0; + + if (left) mask |= 1; + if (middle) mask |= 4; + if (right) mask |= 2; + + usb__m__buttons(mask); +} + +// single left click (?) +void key_functions__mouse_left_click(void) { + usb__m__send(0, 0, 0, 0, MOUSE_BTN1); + usb__m__send(0, 0, 0, 0, 0); +} + diff --git a/firmware/lib/layout/mouse/options.mk b/firmware/lib/layout/mouse/options.mk new file mode 100644 index 00000000..5ea174f9 --- /dev/null +++ b/firmware/lib/layout/mouse/options.mk @@ -0,0 +1,16 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2013 Gyuri Horak +# Released under The MIT License (see "doc/licenses/MIT.md") +# Project located at +# ----------------------------------------------------------------------------- + +## +# mouse options +# +# This file is meant to be included by the using '.../options.mk' +# + +ifdef MOUSE_ENABLE + SRC += $(wildcard $(CURDIR)/*.c) +endif + diff --git a/firmware/lib/usb.h b/firmware/lib/usb.h index 95c76e90..408137a0 100644 --- a/firmware/lib/usb.h +++ b/firmware/lib/usb.h @@ -34,6 +34,17 @@ bool usb__kb__read_key (uint8_t keycode); bool usb__kb__read_led (char led); uint8_t usb__kb__send_report (void); +void usb__kb__toggle_nkro (void); + +// --- mouse --- +#define MOUSE_BTN1 (1<<0) +#define MOUSE_BTN2 (1<<1) +#define MOUSE_BTN3 (1<<2) +#define MOUSE_BTN4 (1<<3) +#define MOUSE_BTN5 (1<<4) + +void usb__m__send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons); +void usb__m__buttons(uint8_t buttons); // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- diff --git a/firmware/lib/usb/atmega32u4/general.c b/firmware/lib/usb/atmega32u4/general.c index e0c15a21..ef4f2387 100644 --- a/firmware/lib/usb/atmega32u4/general.c +++ b/firmware/lib/usb/atmega32u4/general.c @@ -11,7 +11,7 @@ */ #include -#include "./keyboard/from-pjrc/usb_keyboard.h" +#include "./keyboard/from-pjrc/usb.h" #include "../../usb.h" // ---------------------------------------------------------------------------- diff --git a/firmware/lib/usb/atmega32u4/keyboard.c b/firmware/lib/usb/atmega32u4/keyboard.c index 11b88b30..9111021c 100644 --- a/firmware/lib/usb/atmega32u4/keyboard.c +++ b/firmware/lib/usb/atmega32u4/keyboard.c @@ -11,7 +11,8 @@ #include #include #include "../usage-page/keyboard.h" -#include "./keyboard/from-pjrc/usb_keyboard.h" +#include "../../../../firmware/keyboard.h" +#include "./keyboard/from-pjrc/usb.h" #include "../../usb.h" // ---------------------------------------------------------------------------- @@ -58,15 +59,29 @@ uint8_t usb__kb__set_key(bool pressed, uint8_t keycode) { } // all others - for (uint8_t i=0; i<6; i++) { + if (!keyboard_nkro_enabled) { + for (uint8_t i=0; i>3) < REPORT_KEYS) { + keyboard_keys[keycode>>3] |= 1<<(keycode&7); return 0; } } else { - if (keyboard_keys[i] == keycode) { - keyboard_keys[i] = 0; + if ((keycode>>3) < REPORT_KEYS) { + keyboard_keys[keycode>>3] &= ~(1<<(keycode&7)); return 0; } } @@ -93,9 +108,16 @@ bool usb__kb__read_key(uint8_t keycode) { } // all others - for (uint8_t i=0; i<6; i++) - if (keyboard_keys[i] == keycode) - return true; + if (!keyboard_nkro_enabled) { + for (uint8_t i=0; i>3) < REPORT_KEYS) { + return (keyboard_keys[keycode>>3] & (1<<(keycode&7))); + } + } return false; } @@ -115,3 +137,12 @@ uint8_t usb__kb__send_report(void) { return usb_keyboard_send(); } +void usb__kb__toggle_nkro(void) { + if (!keyboard_nkro_enabled) { + usb_keyboard_nkro_enable(true); + kb__led__on(6); + } else { + usb_keyboard_nkro_enable(false); + kb__led__off(6); + } +} diff --git a/firmware/lib/usb/atmega32u4/keyboard/from-pjrc/usb_keyboard.c b/firmware/lib/usb/atmega32u4/keyboard/from-pjrc/usb.c similarity index 56% rename from firmware/lib/usb/atmega32u4/keyboard/from-pjrc/usb_keyboard.c rename to firmware/lib/usb/atmega32u4/keyboard/from-pjrc/usb.c index 2dd3a9cd..9cd159d0 100644 --- a/firmware/lib/usb/atmega32u4/keyboard/from-pjrc/usb_keyboard.c +++ b/firmware/lib/usb/atmega32u4/keyboard/from-pjrc/usb.c @@ -68,7 +68,7 @@ // ---------------------------------------------------------------------------- #define USB_SERIAL_PRIVATE_INCLUDE -#include "usb_keyboard.h" +#include "usb.h" /************************************************************************** * @@ -106,16 +106,19 @@ #define ENDPOINT0_SIZE 32 -#define KEYBOARD_INTERFACE 0 -#define KEYBOARD_ENDPOINT 3 -#define KEYBOARD_SIZE 8 -#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER - static const uint8_t PROGMEM endpoint_config_table[] = { - 0, - 0, - 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, - 0 + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD_SIZE) | KBD_BUFFER, // 1 +#ifdef MOUSE_ENABLE + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2 +#else + 0, // 2 +#endif +#ifdef NKRO_ENABLE + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 3 +#else + 0, // 3 +#endif + 0, // 4 }; @@ -174,56 +177,232 @@ static const uint8_t PROGMEM keyboard_hid_report_desc[] = { 0x95, 0x01, // Report Count (1), 0x75, 0x03, // Report Size (3), 0x91, 0x03, // Output (Constant), ;LED report padding - 0x95, 0x06, // Report Count (6), + 0x95, KBD_REPORT_KEYS, // Report Count (?), 0x75, 0x08, // Report Size (8), 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x68, // Logical Maximum(104), + 0x25, 0xFF, // Logical Maximum(104), 0x05, 0x07, // Usage Page (Key Codes), 0x19, 0x00, // Usage Minimum (0), - 0x29, 0x68, // Usage Maximum (104), + 0x29, 0xFF, // Usage Maximum (104), 0x81, 0x00, // Input (Data, Array), 0xc0 // End Collection }; -#define CONFIG1_DESC_SIZE (9+9+9+7) -#define KEYBOARD_HID_DESC_OFFSET (9+9) +#ifdef MOUSE_ENABLE +// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension +// http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521 +// http://www.keil.com/forum/15671/ +// http://www.microsoft.com/whdc/device/input/wheel.mspx +static const uint8_t PROGMEM mouse_hid_report_desc[] = { + /* mouse */ + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x02, // USAGE (Mouse) + 0xa1, 0x01, // COLLECTION (Application) + //0x85, REPORT_ID_MOUSE, // REPORT_ID (1) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + // ---------------------------- Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x05, // USAGE_MAXIMUM (Button 5) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x05, // REPORT_COUNT (5) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x03, // REPORT_SIZE (3) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // ---------------------------- X,Y position + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x06, // INPUT (Data,Var,Rel) + // ---------------------------- Vertical wheel + 0x09, 0x38, // USAGE (Wheel) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical + 0x45, 0x00, // PHYSICAL_MAXIMUM (0) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x06, // INPUT (Data,Var,Rel) + // ---------------------------- Horizontal wheel + 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) + 0x0a, 0x38, 0x02, // USAGE (AC Pan) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x06, // INPUT (Data,Var,Rel) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +}; +#endif + +#ifdef NKRO_ENABLE +// http://geekhack.org/index.php?topic=13162.msg259955#msg259955 +static const uint8_t PROGMEM keyboard2_hid_report_desc[] = { + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application), + // bitmap of modifiers + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte + // LED output report + 0x95, 0x05, // Report Count (5), + 0x75, 0x01, // Report Size (1), + 0x05, 0x08, // Usage Page (LEDs), + 0x19, 0x01, // Usage Minimum (1), + 0x29, 0x05, // Usage Maximum (5), + 0x91, 0x02, // Output (Data, Variable, Absolute), + 0x95, 0x01, // Report Count (1), + 0x75, 0x03, // Report Size (3), + 0x91, 0x03, // Output (Constant), + // bitmap of keys + 0x95, KBD2_REPORT_KEYS*8, // Report Count (), + 0x75, 0x01, // Report Size (1), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum(1), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, KBD2_REPORT_KEYS*8-1, // Usage Maximum (), + 0x81, 0x02, // Input (Data, Variable, Absolute), + 0xc0 // End Collection +}; +#endif + +#define KBD_HID_DESC_NUM 0 +#define KBD_HID_DESC_OFFSET (9+(9+9+7)*KBD_HID_DESC_NUM+9) + +#ifdef MOUSE_ENABLE +# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1) +# define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*MOUSE_HID_DESC_NUM+9) +#else +# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 0) +#endif + +#ifdef NKRO_ENABLE +# define KBD2_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1) +# define KBD2_HID_DESC_OFFSET (9+(9+9+7)*KBD2_HID_DESC_NUM+9) +#else +# define KBD2_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 0) +#endif + +#define NUM_INTERFACES (KBD2_HID_DESC_NUM + 1) +#define CONFIG1_DESC_SIZE (9+(9+9+7)*NUM_INTERFACES) + static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 9, // bLength; 2, // bDescriptorType; LSB(CONFIG1_DESC_SIZE), // wTotalLength MSB(CONFIG1_DESC_SIZE), - 1, // bNumInterfaces + NUM_INTERFACES, // bNumInterfaces 1, // bConfigurationValue 0, // iConfiguration - 0xC0, // bmAttributes + 0xA0, // bmAttributes 50, // bMaxPower + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType - KEYBOARD_INTERFACE, // bInterfaceNumber + KBD_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) 0x01, // bInterfaceSubClass (0x01 = Boot) 0x01, // bInterfaceProtocol (0x01 = Keyboard) 0, // iInterface - // HID interface descriptor, HID 1.11 spec, section 6.2.1 + // HID descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType - sizeof(keyboard_hid_report_desc), // wDescriptorLength + sizeof(keyboard_hid_report_desc), // wDescriptorLength 0, // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType - KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress + KBD_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) - KEYBOARD_SIZE, 0, // wMaxPacketSize - 1 // bInterval + KBD_SIZE, 0, // wMaxPacketSize + 10, // bInterval + +#ifdef MOUSE_ENABLE + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + MOUSE_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + // ThinkPad T23 BIOS doesn't work with boot mouse. + 0x00, // bInterfaceSubClass (0x01 = Boot) + 0x02, // bInterfaceProtocol (0x02 = Mouse) +/* + 0x01, // bInterfaceSubClass (0x01 = Boot) + 0x02, // bInterfaceProtocol (0x02 = Mouse) +*/ + 0, // iInterface + // HID descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0, // bCountryCode + 1, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(mouse_hid_report_desc), // wDescriptorLength + 0, + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + MOUSE_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + MOUSE_SIZE, 0, // wMaxPacketSize + 1, // bInterval +#endif + +#ifdef NKRO_ENABLE + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + KBD2_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x00, // bInterfaceSubClass (0x01 = Boot) + 0x00, // bInterfaceProtocol (0x01 = Keyboard) + 0, // iInterface + // HID descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0, // bCountryCode + 1, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(keyboard2_hid_report_desc), // wDescriptorLength + 0, + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + KBD2_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + KBD2_SIZE, 0, // wMaxPacketSize + 1, // bInterval +#endif }; // If you're desperate for a little extra code memory, these strings @@ -253,15 +432,27 @@ static const struct usb_string_descriptor_struct PROGMEM string2 = { // This table defines which descriptor data is sent for each specific // request from the host (in wValue and wIndex). static const struct descriptor_list_struct { - uint16_t wValue; + uint16_t wValue; // descriptor type uint16_t wIndex; const uint8_t *addr; uint8_t length; } PROGMEM descriptor_list[] = { + // DEVICE descriptor {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, + // CONFIGURATION descriptor {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, - {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, - {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, + // HID/REPORT descriptors + {0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9}, + {0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, +#ifdef MOUSE_ENABLE + {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, + {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)}, +#endif +#ifdef NKRO_ENABLE + {0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9}, + {0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)}, +#endif + // STRING descriptors {0x0300, 0x0000, (const uint8_t *)&string0, 4}, {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)} @@ -284,7 +475,7 @@ static volatile uint8_t usb_configuration=0; uint8_t keyboard_modifier_keys=0; // which keys are currently pressed, up to 6 keys may be down at once -uint8_t keyboard_keys[6]={0,0,0,0,0,0}; +uint8_t keyboard_keys[REPORT_KEYS]; // ={0,0,0,0,0,0}; // protocol setting from the host. We use exactly the same report // either way, so this variable only stores the setting since we @@ -301,6 +492,12 @@ static uint8_t keyboard_idle_count=0; // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana volatile uint8_t keyboard_leds=0; +// nkro, disabled by default +bool keyboard_nkro_enabled=false; + +// mouse +uint8_t usb_mouse_protocol=1; +uint8_t mouse_buttons = 0; /************************************************************************** * @@ -312,15 +509,22 @@ volatile uint8_t keyboard_leds=0; // initialize USB void usb_init(void) { + uint8_t i; + HW_CONFIG(); USB_FREEZE(); // enable USB PLL_CONFIG(); // config PLL - while (!(PLLCSR & (1< +#include +/*------------------------------------------------------------------* + * Keyboard descriptor setting + *------------------------------------------------------------------*/ +#define KBD_INTERFACE 0 +#define KBD_ENDPOINT 1 +#define KBD_SIZE 8 +#define KBD_BUFFER EP_DOUBLE_BUFFER +#define KBD_REPORT_KEYS (KBD_SIZE - 2) + +// secondary keyboard +#ifdef NKRO_ENABLE +#define KBD2_INTERFACE 2 +#define KBD2_ENDPOINT 3 +#define KBD2_SIZE 24 +#define KBD2_BUFFER EP_DOUBLE_BUFFER +#define KBD2_REPORT_KEYS (KBD2_SIZE - 1) +#endif + +#if defined(NKRO_ENABLE) +# define REPORT_KEYS KBD2_REPORT_KEYS +#else +# define REPORT_KEYS KBD_REPORT_KEYS +#endif + +// mouse +#define MOUSE_INTERFACE 1 +#define MOUSE_ENDPOINT 2 +#define MOUSE_SIZE 8 +#define MOUSE_BUFFER EP_DOUBLE_BUFFER + +// ---------------------------------------------------------------------------- + +// general void usb_init(void); // initialize everything uint8_t usb_configured(void); // is the USB port configured +// keyboard int8_t usb_keyboard_send(void); extern uint8_t keyboard_modifier_keys; -extern uint8_t keyboard_keys[6]; +extern uint8_t keyboard_keys[REPORT_KEYS]; extern volatile uint8_t keyboard_leds; +extern bool keyboard_nkro_enabled; +void usb_keyboard_nkro_enable(bool); + +// mouse +extern uint8_t usb_mouse_protocol; +extern uint8_t mouse_buttons; + +int8_t usb_mouse_send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons); +void usb_mouse_buttons(uint8_t buttons); + // ---------------------------------------------------------------------------- // Everything below this point is only intended for usb_serial.c @@ -55,7 +100,8 @@ extern volatile uint8_t keyboard_leds; ((s) == 16 ? 0x10 : \ 0x00))) -#define MAX_ENDPOINT 4 +#define MAX_ENDPOINT 4 +#define UERST_MASK 0x1E #define LSB(n) (n & 255) #define MSB(n) ((n >> 8) & 255) @@ -99,9 +145,18 @@ extern volatile uint8_t keyboard_leds; #define HID_SET_REPORT 9 #define HID_SET_IDLE 10 #define HID_SET_PROTOCOL 11 +#define HID_REPORT_INPUT 1 +#define HID_REPORT_OUTPUT 2 +#define HID_REPORT_FEATURE 3 // CDC (communication class device) #define CDC_SET_LINE_CODING 0x20 #define CDC_GET_LINE_CODING 0x21 #define CDC_SET_CONTROL_LINE_STATE 0x22 +// HID feature selectors +#define DEVICE_REMOTE_WAKEUP 1 +#define ENDPOINT_HALT 0 +#define TEST_MODE 2 + + #endif #endif diff --git a/firmware/lib/usb/atmega32u4/mouse.c b/firmware/lib/usb/atmega32u4/mouse.c new file mode 100644 index 00000000..1e4c8847 --- /dev/null +++ b/firmware/lib/usb/atmega32u4/mouse.c @@ -0,0 +1,28 @@ +/* ---------------------------------------------------------------------------- + * Copyright (c) 2013 Gyuri Horak + * Released under The MIT License (see "doc/licenses/MIT.md") + * Project located at + * ------------------------------------------------------------------------- */ + +/** description + * Implements the "keyboard" section of '.../firmware/lib/usb.h' + */ + +#include +#include "./keyboard/from-pjrc/usb.h" +#include "../../usb.h" + +// ---------------------------------------------------------------------------- + +void usb__m__send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons) { +#ifdef MOUSE_ENABLE + usb_mouse_send(x, y, wheel_v, wheel_h, buttons); +#endif +} + +void usb__m__buttons(uint8_t buttons) { +#ifdef MOUSE_ENABLE + usb_mouse_buttons(buttons); +#endif +} + diff --git a/firmware/makefile b/firmware/makefile index beacfd70..331c09bf 100644 --- a/firmware/makefile +++ b/firmware/makefile @@ -93,6 +93,14 @@ CFLAGS += -fdata-sections # / section in the output file if the # linker optimizations, and discarding # unused code. # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +ifdef MOUSE_ENABLE + CFLAGS += -DMOUSE_ENABLE +endif + +ifdef NKRO_ENABLE + CFLAGS += -DNKRO_ENABLE +endif + # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . LDFLAGS += -Wl,-Map=$(TARGET).map,--cref # generate a link map, with a cross # reference table @@ -136,7 +144,7 @@ all: $(TARGET).hex $(TARGET).eep clean: @echo @echo '--- cleaning ---' - git clean -dX # remove ignored files and directories + git clean -dXf # remove ignored files and directories # -----------------------------------------------------------------------------