add build option: NKRO_ENABLE(remove: USB_12KRO)
This commit is contained in:
parent
66ece29b0e
commit
51f17f0231
12 changed files with 413 additions and 259 deletions
|
@ -129,8 +129,8 @@ CDEFS += -DPRODUCT=$(PRODUCT)
|
||||||
ifdef MOUSE_DELAY_TIME
|
ifdef MOUSE_DELAY_TIME
|
||||||
CDEFS += -DMOUSE_DELAY_TIME=$(MOUSE_DELAY_TIME)
|
CDEFS += -DMOUSE_DELAY_TIME=$(MOUSE_DELAY_TIME)
|
||||||
endif
|
endif
|
||||||
ifdef USB_12KRO
|
ifdef NKRO_ENABLE
|
||||||
CDEFS += -DUSB_12KRO
|
CDEFS += -DNKRO_ENABLE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
109
README
109
README
|
@ -2,42 +2,23 @@ t.m.k. Keyboard Firmware
|
||||||
========================
|
========================
|
||||||
http://github.com/tmk/tmk_keyboard
|
http://github.com/tmk/tmk_keyboard
|
||||||
|
|
||||||
This is keyboard firmware for PFU HHKB style keyboard and Teensy/Teensy++ 2.0.
|
This is keyboard firmware for AVR USB MCUs or Teensy/Teensy++ 2.0.
|
||||||
OS see this as composite device which has keyboard and mouse.
|
|
||||||
|
|
||||||
The project is heavily based on PJRC USB Keyboard/Mouse Example and
|
The project is heavily based on PJRC USB Keyboard/Mouse Example and
|
||||||
owes a debt to preceding keyboard firmware projects.
|
owes a debt to preceding keyboard firmware projects.
|
||||||
|
|
||||||
|
http://www.pjrc.com/teensy
|
||||||
|
|
||||||
Version
|
|
||||||
-------
|
|
||||||
0.1 2010/08/23
|
|
||||||
It works as normal keyboard.
|
|
||||||
It is for modified Macway keyboard(TP-999KB-E).
|
|
||||||
|
|
||||||
1.0 2010/10/02
|
|
||||||
keyboard has mouse key now.
|
|
||||||
keyboard with layers.(see keymap.c)
|
|
||||||
FN_1(right cmd):
|
|
||||||
vi style layer
|
|
||||||
FN_2(next to right shift):
|
|
||||||
HHKB style layer
|
|
||||||
FN_3(left bottom):
|
|
||||||
h j k l: mouse move
|
|
||||||
a s d spc: mouse buttons
|
|
||||||
m ,: mouse wheel
|
|
||||||
|
|
||||||
1.1 2010/10/08
|
Functions
|
||||||
Matrix wiring changed for casing.
|
---------
|
||||||
(and my Teensy PD3 seems to be latchuped and unusable. :<)
|
Mouse key
|
||||||
|
System Control Key
|
||||||
1.2 2010/10/13
|
Power Down, Sleep, Wake Up & USB Remote Wake up
|
||||||
HHKB support
|
Media Control Key
|
||||||
horizontal mouse wheel support
|
Volume Down/Up, Mute
|
||||||
change keymaps
|
USB NKRO
|
||||||
|
|
||||||
2.0 2010/10/27
|
|
||||||
HHKB/Macway support merged
|
|
||||||
|
|
||||||
|
|
||||||
Build
|
Build
|
||||||
|
@ -47,17 +28,16 @@ Compiling sources need AVR GCC, AVR Libc and GNU make.(You can use WinAVR on Win
|
||||||
$ cd <target> (hhkb or macway)
|
$ cd <target> (hhkb or macway)
|
||||||
$ make
|
$ make
|
||||||
|
|
||||||
|
http://winavr.sourceforge.net/
|
||||||
|
|
||||||
Debuging
|
|
||||||
--------
|
Debuging & Rescue
|
||||||
Debug print is on if 4 keys are pressed during booting.
|
-----------------
|
||||||
Use PJRC's hid_listen.exe to see debug messages.
|
Use PJRC's hid_listen.exe to see debug messages.
|
||||||
|
Press right Control + Shift + Alt + GUI + H to debug menu.
|
||||||
|
|
||||||
|
Pressing any 3 keys when connected enables debug output.
|
||||||
AVR Target board
|
Pressing any 4 keys when connected makes bootloader comes up.
|
||||||
----------------
|
|
||||||
Teensy/Teensy++
|
|
||||||
http://www.pjrc.com/teensy
|
|
||||||
|
|
||||||
|
|
||||||
Projects related
|
Projects related
|
||||||
|
@ -83,59 +63,4 @@ ps2avr
|
||||||
http://sourceforge.net/projects/ps2avr/
|
http://sourceforge.net/projects/ps2avr/
|
||||||
|
|
||||||
|
|
||||||
TODO & ideas
|
|
||||||
------------
|
|
||||||
licensing notes(GPL)
|
|
||||||
I think GPL is not infringement of PJRC license.
|
|
||||||
souce code cleaning
|
|
||||||
sleep&wakeup
|
|
||||||
debouncing logic
|
|
||||||
will be coded when bouncing occurs.
|
|
||||||
bouncing doesnt occur on my ALPS switch so far.
|
|
||||||
scan rate is too slow?(to be measure)
|
|
||||||
|
|
||||||
Trackpoint(PS/2)
|
|
||||||
receive PS/2 signal from TrackPoint
|
|
||||||
send USB HID report
|
|
||||||
Thinkpad keyboard support
|
|
||||||
turn keyboard to USB keyboard/mouse composite device
|
|
||||||
setting menu(configure without changing firmware)
|
|
||||||
console for display
|
|
||||||
keymap/layer setting
|
|
||||||
mouse speed/acceleration
|
|
||||||
matrix display
|
|
||||||
PS/2 keyboard mode
|
|
||||||
with USB to PS/2 dumb adapter(possible?)
|
|
||||||
AT90USBKEY support
|
|
||||||
and other AVR USB boards
|
|
||||||
|
|
||||||
DONE:
|
|
||||||
support for HHKB pro matrix signal
|
|
||||||
exchange controller board with teensy
|
|
||||||
2010/10/11
|
|
||||||
keymap
|
|
||||||
Matias half keyboard style
|
|
||||||
2010/10/23
|
|
||||||
souce code cleaning
|
|
||||||
2010/10/23
|
|
||||||
debug on/off
|
|
||||||
debug off by default
|
|
||||||
pressing keys during booting
|
|
||||||
2010/10/23
|
|
||||||
mouse horizontal wheel
|
|
||||||
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
|
|
||||||
2010/10/13
|
|
||||||
debug on/off
|
|
||||||
Fn key conbination during normal operation
|
|
||||||
matrix print on/off
|
|
||||||
key print on/off
|
|
||||||
mouse print on/off
|
|
||||||
2010/10/26
|
|
||||||
layer switching
|
|
||||||
time before switching
|
|
||||||
timeout when not used during specific time
|
|
||||||
2010/10/30
|
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
99
USB_NKRO.txt
Normal file
99
USB_NKRO.txt
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
USB NKRO MEMO
|
||||||
|
=============
|
||||||
|
2010/12/07
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
USB - boot mode, NKRO, compatibility, etc...
|
||||||
|
http://geekhack.org/showthread.php?t=13162
|
||||||
|
NKey Rollover - Overview, Testing Methodology, and Results
|
||||||
|
http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results
|
||||||
|
|
||||||
|
|
||||||
|
Terminogy
|
||||||
|
---------
|
||||||
|
NKRO
|
||||||
|
ghost
|
||||||
|
matrix
|
||||||
|
mechanical with diodes
|
||||||
|
membrane
|
||||||
|
|
||||||
|
|
||||||
|
OS Support Status
|
||||||
|
-----------------
|
||||||
|
NKRO is possible at least relatively new OS.
|
||||||
|
Following OS supports both Extended and Bitmarp report.
|
||||||
|
Windows7 64bit
|
||||||
|
Windows2000 SP4
|
||||||
|
Ubuntu 10.4(Linux 2.6)
|
||||||
|
|
||||||
|
|
||||||
|
USB NKRO methods
|
||||||
|
----------------
|
||||||
|
1. Virtual keyboards
|
||||||
|
Keyboard can increase its KRO by using virtual keyboards with Standard or Extended report.
|
||||||
|
If the keyboard has 2 virtul keyboard with Standard report(6KRO), it gets 12KRO.
|
||||||
|
Using this method means the keyboard is a composite device.
|
||||||
|
|
||||||
|
2. Exteded report
|
||||||
|
It needs large report size for this method to achive NKRO.
|
||||||
|
If a keyboard has 101keys, it needs 103byte report. It seems to be inefficient.
|
||||||
|
|
||||||
|
3. Bitmap report
|
||||||
|
If the keyboard has less than 128keys, 16byte report will be enough for NKRO.
|
||||||
|
The 16byte report seems to be reasonable cost to get NKRO.
|
||||||
|
|
||||||
|
|
||||||
|
Report Format
|
||||||
|
-------------
|
||||||
|
Other report formats than followings are possible, though these format are typical one.
|
||||||
|
|
||||||
|
1. Standard 8bytes
|
||||||
|
modifiers(bitmap) 1byte
|
||||||
|
reserved 1byte(not used)
|
||||||
|
keys(array) 1byte*6
|
||||||
|
Standard report can send 6keys plus 8modifiers simultaneously.
|
||||||
|
Standard report is used by most keyboards in the marketplace.
|
||||||
|
Standard report is identical to boot protocol report.
|
||||||
|
Standard report is hard to suffer from compatibility problems.
|
||||||
|
|
||||||
|
2. Extended standard 16,32,64bytes
|
||||||
|
modifiers(bitmap) 1byte
|
||||||
|
reserved 1byte(not used)
|
||||||
|
keys(array) 1byte*(14,32,62)
|
||||||
|
Extended report can send N-keys by using N+2bytes.
|
||||||
|
Extended report is expected to be compatible with boot protocol.
|
||||||
|
|
||||||
|
3. Bitmap 16,32,64bytes
|
||||||
|
keys(bitmap) (16,32)bytes
|
||||||
|
Bitmap report can send at most 128keys by 16bytes and 256keys by 32bytes.
|
||||||
|
Bitmap report can achieve USB NKRO efficiently in terms of report size.
|
||||||
|
Bitmap report needs a deliberation for boot protocol implementation.
|
||||||
|
|
||||||
|
|
||||||
|
Compatibility Problem
|
||||||
|
---------------------
|
||||||
|
Some BIOS doesn't send SET_PROTCOL request, a keyboard can't switch to boot protocol mode.
|
||||||
|
This may cuase a problem on a keyboard which uses other report than Standard.
|
||||||
|
|
||||||
|
|
||||||
|
Windows Problem
|
||||||
|
---------------
|
||||||
|
1. Windows accepts only 6keys in case of Standard report.
|
||||||
|
It should be able to send 6keys plus 8modifiers.
|
||||||
|
|
||||||
|
2. Windows accepts only 10keys in case of 16bytes Extended report.
|
||||||
|
It should be able to send 14keys plus 8modifiers.
|
||||||
|
|
||||||
|
3. Windows accepts only 18keys in case of 32bytes Extended report.
|
||||||
|
It should be able to send 30keys plus 8modifiers.
|
||||||
|
|
||||||
|
If keys are pressed in excess of the number, wrong keys are registered on Windows.
|
||||||
|
|
||||||
|
|
||||||
|
This problem will be reportedly fixed soon.(2010/12/05)
|
||||||
|
http://forums.anandtech.com/showpost.php?p=30873364&postcount=17
|
||||||
|
|
||||||
|
|
||||||
|
EOF
|
|
@ -39,14 +39,15 @@
|
||||||
# To rebuild project do "make clean" then "make all".
|
# To rebuild project do "make clean" then "make all".
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# TODO: use config.h for build options?
|
||||||
VENDOR_ID = 0xFEED
|
VENDOR_ID = 0xFEED
|
||||||
PRODUCT_ID = 0xCAFE
|
PRODUCT_ID = 0xCAFE
|
||||||
MANUFACTURER = 't.m.k.'
|
MANUFACTURER = 't.m.k.'
|
||||||
PRODUCT = 't.m.k. HHKB pro'
|
PRODUCT = 'HHKB Mod'
|
||||||
DESCRIPTION = 't.m.k. firmware for HHKB pro'
|
DESCRIPTION = 't.m.k. firmware for HHKB pro'
|
||||||
|
|
||||||
MOUSE_DELAY_TIME = 127
|
MOUSE_DELAY_TIME = 127
|
||||||
USB_12KRO = yes
|
NKRO_ENABLE = true
|
||||||
|
|
||||||
# Target file name (without extension).
|
# Target file name (without extension).
|
||||||
TARGET = tmk_hhkb
|
TARGET = tmk_hhkb
|
||||||
|
|
|
@ -42,8 +42,8 @@ static const uint8_t PROGMEM fn_keycode[] = {
|
||||||
KB_NO, // FN_0 [NOT USED]
|
KB_NO, // FN_0 [NOT USED]
|
||||||
KB_NO, // FN_1 layer 1
|
KB_NO, // FN_1 layer 1
|
||||||
KB_SLSH, // FN_2 layer 2
|
KB_SLSH, // FN_2 layer 2
|
||||||
KB_SCOLON, // FN_3 layer 3
|
KB_SCLN, // FN_3 layer 3
|
||||||
KB_SPACE, // FN_4 layer 4
|
KB_SPC, // FN_4 layer 4
|
||||||
KB_NO, // FN_5 [NOT USED]
|
KB_NO, // FN_5 [NOT USED]
|
||||||
KB_NO, // FN_6 [NOT USED]
|
KB_NO, // FN_6 [NOT USED]
|
||||||
KB_NO // FN_7 layer 1
|
KB_NO // FN_7 layer 1
|
||||||
|
@ -67,7 +67,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
KB_TAB, KB_Q, KB_W, KB_E, KB_R, KB_T, KB_Y, KB_U, KB_I, KB_O, KB_P, KB_LBRC,KB_RBRC,KB_BSPC, \
|
KB_TAB, KB_Q, KB_W, KB_E, KB_R, KB_T, KB_Y, KB_U, KB_I, KB_O, KB_P, KB_LBRC,KB_RBRC,KB_BSPC, \
|
||||||
KB_LCTL,KB_A, KB_S, KB_D, KB_F, KB_G, KB_H, KB_J, KB_K, KB_L, FN_3, KB_QUOT,KB_ENT, \
|
KB_LCTL,KB_A, KB_S, KB_D, KB_F, KB_G, KB_H, KB_J, KB_K, KB_L, FN_3, KB_QUOT,KB_ENT, \
|
||||||
KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, FN_2, KB_RSFT,FN_1, \
|
KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, FN_2, KB_RSFT,FN_1, \
|
||||||
KB_LGUI,KB_LALT,FN_4, KB_RALT,FN_7),
|
KB_LGUI,KB_LALT,FN_4, KB_RALT,KB_RGUI),
|
||||||
|
|
||||||
/* Layer 1: HHKB mode (HHKB Fn)
|
/* Layer 1: HHKB mode (HHKB Fn)
|
||||||
* ,-----------------------------------------------------------.
|
* ,-----------------------------------------------------------.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -68,7 +69,7 @@ void proc_matrix(void) {
|
||||||
if (code == KB_NO) {
|
if (code == KB_NO) {
|
||||||
// do nothing
|
// do nothing
|
||||||
} else if (IS_MOD(code)) {
|
} else if (IS_MOD(code)) {
|
||||||
usb_keyboard_mods |= MOD_BIT(code);
|
usb_keyboard_add_mod(code);
|
||||||
} else if (IS_FN(code)) {
|
} else if (IS_FN(code)) {
|
||||||
fn_bits |= FN_BIT(code);
|
fn_bits |= FN_BIT(code);
|
||||||
} else if (IS_MOUSE(code)) {
|
} else if (IS_MOUSE(code)) {
|
||||||
|
@ -111,22 +112,7 @@ void proc_matrix(void) {
|
||||||
|
|
||||||
// normal keys
|
// normal keys
|
||||||
else {
|
else {
|
||||||
// TODO: fix ugly code
|
usb_keyboard_add_key(code);
|
||||||
int8_t i = 0;
|
|
||||||
int8_t empty = -1;
|
|
||||||
for (; i < KEYBOARD_REPORT_MAX; i++) {
|
|
||||||
if (usb_keyboard_keys_prev[i] == code) {
|
|
||||||
usb_keyboard_keys[i] = code;
|
|
||||||
break;
|
|
||||||
} else if (empty == -1 && usb_keyboard_keys_prev[i] == 0 && usb_keyboard_keys[i] == 0) {
|
|
||||||
empty = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == KEYBOARD_REPORT_MAX) {
|
|
||||||
if (empty != -1) {
|
|
||||||
usb_keyboard_keys[empty] = code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,20 +128,24 @@ void proc_matrix(void) {
|
||||||
layer_switching(fn_bits);
|
layer_switching(fn_bits);
|
||||||
|
|
||||||
// TODO: clean code
|
// TODO: clean code
|
||||||
// when 4 left modifier keys down
|
// special mode for control, develop and debug
|
||||||
if (keymap_is_special_mode(fn_bits)) {
|
if (keymap_is_special_mode(fn_bits)) {
|
||||||
switch (usb_keyboard_keys[0]) {
|
switch (usb_keyboard_get_key()) {
|
||||||
case KB_H: // help
|
case KB_H: // help
|
||||||
print_enable = true;
|
print_enable = true;
|
||||||
print("b: jump to bootloader\n");
|
print("b: jump to bootloader\n");
|
||||||
print("d: debug print toggle\n");
|
print("d: toggle debug enable\n");
|
||||||
print("x: matrix debug toggle\n");
|
print("x: toggle matrix debug\n");
|
||||||
print("k: keyboard debug toggle\n");
|
print("k: toggle keyboard debug\n");
|
||||||
print("m: mouse debug toggle\n");
|
print("m: toggle mouse debug\n");
|
||||||
print("p: print enable toggle\n");
|
print("p: toggle print enable\n");
|
||||||
print("v: print version\n");
|
print("v: print version\n");
|
||||||
print("t: print timer count\n");
|
print("t: print timer count\n");
|
||||||
print("r: print registers\n");
|
print("s: print status\n");
|
||||||
|
print("`: toggle protcol(boot/report)\n");
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
print("n: toggle NKRO\n");
|
||||||
|
#endif
|
||||||
print("ESC: power down/wake up\n");
|
print("ESC: power down/wake up\n");
|
||||||
_delay_ms(500);
|
_delay_ms(500);
|
||||||
print_enable = false;
|
print_enable = false;
|
||||||
|
@ -243,13 +233,42 @@ void proc_matrix(void) {
|
||||||
}
|
}
|
||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
break;
|
break;
|
||||||
case KB_R:
|
case KB_S:
|
||||||
usb_keyboard_clear_report();
|
usb_keyboard_clear_report();
|
||||||
usb_keyboard_send();
|
usb_keyboard_send();
|
||||||
|
print("UDCON: "); phex(UDCON); print("\n");
|
||||||
print("UDIEN: "); phex(UDIEN); print("\n");
|
print("UDIEN: "); phex(UDIEN); print("\n");
|
||||||
print("UDINT: "); phex(UDINT); print("\n");
|
print("UDINT: "); phex(UDINT); print("\n");
|
||||||
|
print("usb_keyboard_leds:"); phex(usb_keyboard_leds); print("\n");
|
||||||
|
print("usb_keyboard_protocol:"); phex(usb_keyboard_protocol); print("\n");
|
||||||
|
print("usb_keyboard_idle_config:"); phex(usb_keyboard_idle_config); print("\n");
|
||||||
|
print("usb_keyboard_idle_count:"); phex(usb_keyboard_idle_count); print("\n");
|
||||||
|
print("mouse_protocol:"); phex(mouse_protocol); print("\n");
|
||||||
|
if (usb_keyboard_nkro) print("NKRO: enabled\n"); else print("NKRO: disabled\n");
|
||||||
|
_delay_ms(500);
|
||||||
|
break;
|
||||||
|
case KB_GRV:
|
||||||
|
usb_keyboard_clear_report();
|
||||||
|
usb_keyboard_send();
|
||||||
|
usb_keyboard_protocol = !usb_keyboard_protocol;
|
||||||
|
mouse_protocol = !mouse_protocol;
|
||||||
|
print("keyboard protcol: ");
|
||||||
|
if (usb_keyboard_protocol) print("report"); else print("boot");
|
||||||
|
print("\n");
|
||||||
|
print("mouse protcol: ");
|
||||||
|
if (mouse_protocol) print("report"); else print("boot");
|
||||||
|
print("\n");
|
||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
break;
|
break;
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
case KB_N:
|
||||||
|
usb_keyboard_clear_report();
|
||||||
|
usb_keyboard_send();
|
||||||
|
usb_keyboard_nkro = !usb_keyboard_nkro;
|
||||||
|
if (usb_keyboard_nkro) print("NKRO: enabled\n"); else print("NKRO: disabled\n");
|
||||||
|
_delay_ms(1000);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case KB_ESC:
|
case KB_ESC:
|
||||||
usb_keyboard_clear_report();
|
usb_keyboard_clear_report();
|
||||||
usb_keyboard_send();
|
usb_keyboard_send();
|
||||||
|
|
10
tmk.c
10
tmk.c
|
@ -66,8 +66,7 @@ int main(void)
|
||||||
|
|
||||||
matrix_init();
|
matrix_init();
|
||||||
matrix_scan();
|
matrix_scan();
|
||||||
// bootloader comes up when any 4 or more keys are pressed at startup
|
if (matrix_key_count() >= 3) {
|
||||||
if (matrix_key_count() >= 4) {
|
|
||||||
#ifdef DEBUG_LED
|
#ifdef DEBUG_LED
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
DEBUG_LED_CONFIG;
|
DEBUG_LED_CONFIG;
|
||||||
|
@ -80,6 +79,13 @@ int main(void)
|
||||||
_delay_ms(5000);
|
_delay_ms(5000);
|
||||||
#endif
|
#endif
|
||||||
print_enable = true;
|
print_enable = true;
|
||||||
|
debug_enable = true;
|
||||||
|
debug_matrix = true;
|
||||||
|
debug_keyboard = true;
|
||||||
|
debug_mouse = true;
|
||||||
|
print("debug enabled.\n");
|
||||||
|
}
|
||||||
|
if (matrix_key_count() >= 4) {
|
||||||
print("jump to bootloader...\n");
|
print("jump to bootloader...\n");
|
||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
jump_bootloader(); // not return
|
jump_bootloader(); // not return
|
||||||
|
|
95
usb.c
Normal file → Executable file
95
usb.c
Normal file → Executable file
|
@ -90,12 +90,12 @@ bool suspend = false;
|
||||||
// 0:control endpoint is enabled automatically by controller.
|
// 0:control endpoint is enabled automatically by controller.
|
||||||
static const uint8_t PROGMEM endpoint_config_table[] = {
|
static const uint8_t PROGMEM endpoint_config_table[] = {
|
||||||
// enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation)
|
// enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation)
|
||||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 1
|
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD_SIZE) | KBD_BUFFER, // 1
|
||||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2
|
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2
|
||||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
|
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
|
||||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4
|
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4
|
||||||
#ifdef USB_12KRO
|
#ifdef NKRO_ENABLE
|
||||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 5
|
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5
|
||||||
#else
|
#else
|
||||||
0, // 5
|
0, // 5
|
||||||
#endif
|
#endif
|
||||||
|
@ -158,16 +158,52 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = {
|
||||||
0x95, 0x01, // Report Count (1),
|
0x95, 0x01, // Report Count (1),
|
||||||
0x75, 0x03, // Report Size (3),
|
0x75, 0x03, // Report Size (3),
|
||||||
0x91, 0x03, // Output (Constant), ;LED report padding
|
0x91, 0x03, // Output (Constant), ;LED report padding
|
||||||
0x95, 0x06, // Report Count (6),
|
0x95, KBD_REPORT_KEYS, // Report Count (),
|
||||||
0x75, 0x08, // Report Size (8),
|
0x75, 0x08, // Report Size (8),
|
||||||
0x15, 0x00, // Logical Minimum (0),
|
0x15, 0x00, // Logical Minimum (0),
|
||||||
0x25, 0x68, // Logical Maximum(104),
|
0x25, 0xFF, // Logical Maximum(255),
|
||||||
0x05, 0x07, // Usage Page (Key Codes),
|
0x05, 0x07, // Usage Page (Key Codes),
|
||||||
0x19, 0x00, // Usage Minimum (0),
|
0x19, 0x00, // Usage Minimum (0),
|
||||||
0x29, 0x68, // Usage Maximum (104),
|
0x29, 0xFF, // Usage Maximum (255),
|
||||||
0x81, 0x00, // Input (Data, Array),
|
0x81, 0x00, // Input (Data, Array),
|
||||||
0xc0 // End Collection
|
0xc0 // End Collection
|
||||||
};
|
};
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
static uint8_t PROGMEM keyboard2_hid_report_desc[] = {
|
||||||
|
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||||
|
0x09, 0x06, // Usage (Keyboard),
|
||||||
|
0xA1, 0x01, // Collection (Application),
|
||||||
|
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
|
||||||
|
0x95, 0x01, // Report Count (1),
|
||||||
|
0x75, 0x08, // Report Size (8),
|
||||||
|
0x81, 0x03, // Input (Constant), ;Reserved byte
|
||||||
|
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), ;LED report
|
||||||
|
0x95, 0x01, // Report Count (1),
|
||||||
|
0x75, 0x03, // Report Size (3),
|
||||||
|
0x91, 0x03, // Output (Constant), ;LED report padding
|
||||||
|
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
|
||||||
|
|
||||||
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
|
// 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.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
|
||||||
|
@ -296,13 +332,13 @@ static uint8_t PROGMEM extra_hid_report_desc[] = {
|
||||||
0xc0 // END_COLLECTION
|
0xc0 // END_COLLECTION
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KEYBOARD_HID_DESC_OFFSET (9+(9+9+7)*0+9)
|
#define KBD_HID_DESC_OFFSET (9+(9+9+7)*0+9)
|
||||||
#define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*1+9)
|
#define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*1+9)
|
||||||
#define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*2+9)
|
#define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*2+9)
|
||||||
#define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*3+9)
|
#define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*3+9)
|
||||||
#ifdef USB_12KRO
|
#ifdef NKRO_ENABLE
|
||||||
# define NUM_INTERFACES 5
|
# define NUM_INTERFACES 5
|
||||||
# define KEYBOARD2_HID_DESC_OFFSET (9+(9+9+7)*4+9)
|
# define KBD2_HID_DESC_OFFSET (9+(9+9+7)*4+9)
|
||||||
#else
|
#else
|
||||||
# define NUM_INTERFACES 4
|
# define NUM_INTERFACES 4
|
||||||
#endif
|
#endif
|
||||||
|
@ -322,7 +358,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||||
9, // bLength
|
9, // bLength
|
||||||
4, // bDescriptorType
|
4, // bDescriptorType
|
||||||
KEYBOARD_INTERFACE, // bInterfaceNumber
|
KBD_INTERFACE, // bInterfaceNumber
|
||||||
0, // bAlternateSetting
|
0, // bAlternateSetting
|
||||||
1, // bNumEndpoints
|
1, // bNumEndpoints
|
||||||
0x03, // bInterfaceClass (0x03 = HID)
|
0x03, // bInterfaceClass (0x03 = HID)
|
||||||
|
@ -341,10 +377,10 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||||
7, // bLength
|
7, // bLength
|
||||||
5, // bDescriptorType
|
5, // bDescriptorType
|
||||||
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
|
KBD_ENDPOINT | 0x80, // bEndpointAddress
|
||||||
0x03, // bmAttributes (0x03=intr)
|
0x03, // bmAttributes (0x03=intr)
|
||||||
KEYBOARD_SIZE, 0, // wMaxPacketSize
|
KBD_SIZE, 0, // wMaxPacketSize
|
||||||
1, // bInterval
|
10, // bInterval
|
||||||
|
|
||||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||||
9, // bLength
|
9, // bLength
|
||||||
|
@ -353,8 +389,13 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||||
0, // bAlternateSetting
|
0, // bAlternateSetting
|
||||||
1, // bNumEndpoints
|
1, // bNumEndpoints
|
||||||
0x03, // bInterfaceClass (0x03 = HID)
|
0x03, // bInterfaceClass (0x03 = HID)
|
||||||
|
// ThinkPad T23 BIOS doesn't work with boot mouse.
|
||||||
|
0x00, // bInterfaceSubClass (0x01 = Boot)
|
||||||
|
0x00, // bInterfaceProtocol (0x02 = Mouse)
|
||||||
|
/*
|
||||||
0x01, // bInterfaceSubClass (0x01 = Boot)
|
0x01, // bInterfaceSubClass (0x01 = Boot)
|
||||||
0x02, // bInterfaceProtocol (0x02 = Mouse)
|
0x02, // bInterfaceProtocol (0x02 = Mouse)
|
||||||
|
*/
|
||||||
0, // iInterface
|
0, // iInterface
|
||||||
// HID descriptor, HID 1.11 spec, section 6.2.1
|
// HID descriptor, HID 1.11 spec, section 6.2.1
|
||||||
9, // bLength
|
9, // bLength
|
||||||
|
@ -427,11 +468,11 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||||
EXTRA_SIZE, 0, // wMaxPacketSize
|
EXTRA_SIZE, 0, // wMaxPacketSize
|
||||||
10, // bInterval
|
10, // bInterval
|
||||||
|
|
||||||
#ifdef USB_12KRO
|
#ifdef NKRO_ENABLE
|
||||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||||
9, // bLength
|
9, // bLength
|
||||||
4, // bDescriptorType
|
4, // bDescriptorType
|
||||||
KEYBOARD_INTERFACE2, // bInterfaceNumber
|
KBD2_INTERFACE, // bInterfaceNumber
|
||||||
0, // bAlternateSetting
|
0, // bAlternateSetting
|
||||||
1, // bNumEndpoints
|
1, // bNumEndpoints
|
||||||
0x03, // bInterfaceClass (0x03 = HID)
|
0x03, // bInterfaceClass (0x03 = HID)
|
||||||
|
@ -445,14 +486,14 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||||
0, // bCountryCode
|
0, // bCountryCode
|
||||||
1, // bNumDescriptors
|
1, // bNumDescriptors
|
||||||
0x22, // bDescriptorType
|
0x22, // bDescriptorType
|
||||||
sizeof(keyboard_hid_report_desc), // wDescriptorLength
|
sizeof(keyboard2_hid_report_desc), // wDescriptorLength
|
||||||
0,
|
0,
|
||||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||||
7, // bLength
|
7, // bLength
|
||||||
5, // bDescriptorType
|
5, // bDescriptorType
|
||||||
KEYBOARD_ENDPOINT2 | 0x80, // bEndpointAddress
|
KBD2_ENDPOINT | 0x80, // bEndpointAddress
|
||||||
0x03, // bmAttributes (0x03=intr)
|
0x03, // bmAttributes (0x03=intr)
|
||||||
KEYBOARD_SIZE, 0, // wMaxPacketSize
|
KBD2_SIZE, 0, // wMaxPacketSize
|
||||||
1, // bInterval
|
1, // bInterval
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -494,17 +535,17 @@ static struct descriptor_list_struct {
|
||||||
// CONFIGURATION descriptor
|
// CONFIGURATION descriptor
|
||||||
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
|
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
|
||||||
// HID/REPORT descriptors
|
// HID/REPORT descriptors
|
||||||
{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
|
{0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9},
|
||||||
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
|
{0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
|
||||||
{0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
|
{0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
|
||||||
{0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
|
{0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
|
||||||
{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
|
{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
|
||||||
{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
|
{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
|
||||||
{0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
|
{0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
|
||||||
{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
|
{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
|
||||||
#ifdef USB_12KRO
|
#ifdef NKRO_ENABLE
|
||||||
{0x2100, KEYBOARD_INTERFACE2, config1_descriptor+KEYBOARD2_HID_DESC_OFFSET, 9},
|
{0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9},
|
||||||
{0x2200, KEYBOARD_INTERFACE2, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
|
{0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)},
|
||||||
#endif
|
#endif
|
||||||
// STRING descriptors
|
// STRING descriptors
|
||||||
{0x0300, 0x0000, (const uint8_t *)&string0, 4},
|
{0x0300, 0x0000, (const uint8_t *)&string0, 4},
|
||||||
|
@ -603,7 +644,7 @@ ISR(USB_GEN_vect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (usb_keyboard_idle_config && (++div4 & 3) == 0) {
|
if (usb_keyboard_idle_config && (++div4 & 3) == 0) {
|
||||||
UENUM = KEYBOARD_ENDPOINT;
|
UENUM = KBD_ENDPOINT;
|
||||||
if (UEINTX & (1<<RWAL)) {
|
if (UEINTX & (1<<RWAL)) {
|
||||||
usb_keyboard_idle_count++;
|
usb_keyboard_idle_count++;
|
||||||
if (usb_keyboard_idle_count == usb_keyboard_idle_config) {
|
if (usb_keyboard_idle_count == usb_keyboard_idle_config) {
|
||||||
|
@ -728,10 +769,12 @@ ISR(USB_COM_vect)
|
||||||
for (i=1; i<=6; i++) {
|
for (i=1; i<=6; i++) {
|
||||||
UENUM = i;
|
UENUM = i;
|
||||||
en = pgm_read_byte(cfg++);
|
en = pgm_read_byte(cfg++);
|
||||||
UECONX = en;
|
|
||||||
if (en) {
|
if (en) {
|
||||||
|
UECONX = (1<<EPEN);
|
||||||
UECFG0X = pgm_read_byte(cfg++);
|
UECFG0X = pgm_read_byte(cfg++);
|
||||||
UECFG1X = pgm_read_byte(cfg++);
|
UECFG1X = pgm_read_byte(cfg++);
|
||||||
|
} else {
|
||||||
|
UECONX = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UERST = 0x7E;
|
UERST = 0x7E;
|
||||||
|
@ -788,7 +831,7 @@ ISR(USB_COM_vect)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wIndex == KEYBOARD_INTERFACE) {
|
if (wIndex == KBD_INTERFACE) {
|
||||||
if (bmRequestType == 0xA1) {
|
if (bmRequestType == 0xA1) {
|
||||||
if (bRequest == HID_GET_REPORT) {
|
if (bRequest == HID_GET_REPORT) {
|
||||||
usb_wait_in_ready();
|
usb_wait_in_ready();
|
||||||
|
|
198
usb_keyboard.c
198
usb_keyboard.c
|
@ -4,11 +4,12 @@
|
||||||
#include "usb_keyboard.h"
|
#include "usb_keyboard.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
// keyboard report.
|
// keyboard report.
|
||||||
static usb_keyboard_report_t _report0 = { {0}, 0 };
|
static usb_keyboard_report_t _report0 = { {0}, 0, false };
|
||||||
static usb_keyboard_report_t _report1 = { {0}, 0 };
|
static usb_keyboard_report_t _report1 = { {0}, 0, false };
|
||||||
usb_keyboard_report_t *usb_keyboard_report = &_report0;
|
usb_keyboard_report_t *usb_keyboard_report = &_report0;
|
||||||
usb_keyboard_report_t *usb_keyboard_report_prev = &_report1;
|
usb_keyboard_report_t *usb_keyboard_report_prev = &_report1;
|
||||||
|
|
||||||
|
@ -27,71 +28,33 @@ uint8_t usb_keyboard_idle_count=0;
|
||||||
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
|
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
|
||||||
volatile uint8_t usb_keyboard_leds=0;
|
volatile uint8_t usb_keyboard_leds=0;
|
||||||
|
|
||||||
|
// enable NKRO
|
||||||
|
bool usb_keyboard_nkro = false;
|
||||||
|
|
||||||
|
|
||||||
int8_t usb_keyboard_send(void)
|
int8_t usb_keyboard_send(void)
|
||||||
{
|
{
|
||||||
return usb_keyboard_send_report(usb_keyboard_report);
|
return usb_keyboard_send_report(usb_keyboard_report);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int8_t _send_report(usb_keyboard_report_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end);
|
||||||
int8_t usb_keyboard_send_report(usb_keyboard_report_t *report)
|
int8_t usb_keyboard_send_report(usb_keyboard_report_t *report)
|
||||||
{
|
{
|
||||||
uint8_t i, intr_state, timeout;
|
int8_t result = 0;
|
||||||
|
|
||||||
if (!usb_configured()) return -1;
|
#ifdef NKRO_ENABLE
|
||||||
intr_state = SREG;
|
if (usb_keyboard_nkro)
|
||||||
cli();
|
result = _send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS);
|
||||||
UENUM = KEYBOARD_ENDPOINT;
|
else
|
||||||
timeout = UDFNUML + 50;
|
|
||||||
while (1) {
|
|
||||||
// are we ready to transmit?
|
|
||||||
if (UEINTX & (1<<RWAL)) break;
|
|
||||||
SREG = intr_state;
|
|
||||||
// has the USB gone offline?
|
|
||||||
if (!usb_configured()) return -1;
|
|
||||||
// have we waited too long?
|
|
||||||
if (UDFNUML == timeout) return -1;
|
|
||||||
// get ready to try checking again
|
|
||||||
intr_state = SREG;
|
|
||||||
cli();
|
|
||||||
UENUM = KEYBOARD_ENDPOINT;
|
|
||||||
}
|
|
||||||
UEDATX = report->mods;
|
|
||||||
UEDATX = 0;
|
|
||||||
for (i = 0; i < 6; i++) {
|
|
||||||
UEDATX = report->keys[i];
|
|
||||||
}
|
|
||||||
UEINTX = 0x3A;
|
|
||||||
SREG = intr_state;
|
|
||||||
|
|
||||||
#ifdef USB_12KRO
|
|
||||||
if (!usb_configured()) return -1;
|
|
||||||
intr_state = SREG;
|
|
||||||
cli();
|
|
||||||
UENUM = KEYBOARD_ENDPOINT2;
|
|
||||||
timeout = UDFNUML + 50;
|
|
||||||
while (1) {
|
|
||||||
// are we ready to transmit?
|
|
||||||
if (UEINTX & (1<<RWAL)) break;
|
|
||||||
SREG = intr_state;
|
|
||||||
// has the USB gone offline?
|
|
||||||
if (!usb_configured()) return -1;
|
|
||||||
// have we waited too long?
|
|
||||||
if (UDFNUML == timeout) return -1;
|
|
||||||
// get ready to try checking again
|
|
||||||
intr_state = SREG;
|
|
||||||
cli();
|
|
||||||
UENUM = KEYBOARD_ENDPOINT2;
|
|
||||||
}
|
|
||||||
UEDATX = report->mods;
|
|
||||||
UEDATX = 0;
|
|
||||||
for (i = 6; i < 12; i++) {
|
|
||||||
UEDATX = report->keys[i];
|
|
||||||
}
|
|
||||||
UEINTX = 0x3A;
|
|
||||||
SREG = intr_state;
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
if (usb_keyboard_protocol)
|
||||||
|
result = _send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS);
|
||||||
|
else
|
||||||
|
result = _send_report(report, KBD_ENDPOINT, 0, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) return result;
|
||||||
usb_keyboard_idle_count = 0;
|
usb_keyboard_idle_count = 0;
|
||||||
report->is_sent =true;
|
report->is_sent =true;
|
||||||
usb_keyboard_print_report(report);
|
usb_keyboard_print_report(report);
|
||||||
|
@ -111,7 +74,7 @@ void usb_keyboard_clear_report(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_keyboard_clear_keys(void) {
|
void usb_keyboard_clear_keys(void) {
|
||||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) usb_keyboard_report->keys[i] = 0;
|
for (int i = 0; i < KEYS_MAX; i++) usb_keyboard_report->keys[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_keyboard_clear_mods(void)
|
void usb_keyboard_clear_mods(void)
|
||||||
|
@ -119,6 +82,17 @@ void usb_keyboard_clear_mods(void)
|
||||||
usb_keyboard_report->mods = 0;
|
usb_keyboard_report->mods = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void usb_keyboard_set_keys(uint8_t *keys)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < KEYS_MAX; i++)
|
||||||
|
usb_keyboard_report->keys[i] = keys[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_keyboard_set_mods(uint8_t mods)
|
||||||
|
{
|
||||||
|
usb_keyboard_report->mods = mods;
|
||||||
|
}
|
||||||
|
|
||||||
void usb_keyboard_add_code(uint8_t code)
|
void usb_keyboard_add_code(uint8_t code)
|
||||||
{
|
{
|
||||||
if (IS_MOD(code)) {
|
if (IS_MOD(code)) {
|
||||||
|
@ -128,25 +102,17 @@ void usb_keyboard_add_code(uint8_t code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void _add_key_byte(uint8_t code);
|
||||||
|
static inline void _add_key_bit(uint8_t code);
|
||||||
void usb_keyboard_add_key(uint8_t code)
|
void usb_keyboard_add_key(uint8_t code)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) {
|
#ifdef NKRO_ENABLE
|
||||||
if (!usb_keyboard_report->keys[i]) {
|
if (usb_keyboard_nkro) {
|
||||||
usb_keyboard_report->keys[i] = code;
|
_add_key_bit(code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
}
|
_add_key_byte(code);
|
||||||
|
|
||||||
void usb_keyboard_set_keys(uint8_t *keys)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++)
|
|
||||||
usb_keyboard_report->keys[i] = keys[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void usb_keyboard_set_mods(uint8_t mods)
|
|
||||||
{
|
|
||||||
usb_keyboard_report->mods = mods;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_keyboard_add_mod(uint8_t code)
|
void usb_keyboard_add_mod(uint8_t code)
|
||||||
|
@ -165,12 +131,18 @@ void usb_keyboard_del_code(uint8_t code)
|
||||||
|
|
||||||
void usb_keyboard_del_key(uint8_t code)
|
void usb_keyboard_del_key(uint8_t code)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) {
|
#ifdef NKRO_ENABLE
|
||||||
|
if ((code>>3) < KEYS_MAX) {
|
||||||
|
usb_keyboard_keys[code>>3] &= ~(1<<(code&7));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for (int i = 0; i < KEYS_MAX; i++) {
|
||||||
if (usb_keyboard_report->keys[i] == code) {
|
if (usb_keyboard_report->keys[i] == code) {
|
||||||
usb_keyboard_report->keys[i] = KB_NO;
|
usb_keyboard_report->keys[i] = KB_NO;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_keyboard_del_mod(uint8_t code)
|
void usb_keyboard_del_mod(uint8_t code)
|
||||||
|
@ -186,7 +158,7 @@ bool usb_keyboard_is_sent(void)
|
||||||
bool usb_keyboard_has_key(void)
|
bool usb_keyboard_has_key(void)
|
||||||
{
|
{
|
||||||
uint8_t keys = 0;
|
uint8_t keys = 0;
|
||||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) keys |= usb_keyboard_report->keys[i];
|
for (int i = 0; i < KEYS_MAX; i++) keys |= usb_keyboard_report->keys[i];
|
||||||
return keys ? true : false;
|
return keys ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,10 +167,86 @@ bool usb_keyboard_has_mod(void)
|
||||||
return usb_keyboard_report->mods ? true : false;
|
return usb_keyboard_report->mods ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t usb_keyboard_get_key(void)
|
||||||
|
{
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
if (usb_keyboard_nkro) {
|
||||||
|
uint8_t i = 0;
|
||||||
|
for (; i < KEYS_MAX && !usb_keyboard_keys[i]; i++);
|
||||||
|
return i<<3 | biton(usb_keyboard_keys[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return usb_keyboard_keys[0];
|
||||||
|
}
|
||||||
|
|
||||||
void usb_keyboard_print_report(usb_keyboard_report_t *report)
|
void usb_keyboard_print_report(usb_keyboard_report_t *report)
|
||||||
{
|
{
|
||||||
if (!debug_keyboard) return;
|
if (!debug_keyboard) return;
|
||||||
print("keys: ");
|
print("keys: ");
|
||||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { phex(report->keys[i]); print(" "); }
|
for (int i = 0; i < KEYS_MAX; i++) { phex(report->keys[i]); print(" "); }
|
||||||
print(" mods: "); phex(report->mods); print("\n");
|
print(" mods: "); phex(report->mods); print("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int8_t _send_report(usb_keyboard_report_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end)
|
||||||
|
{
|
||||||
|
uint8_t intr_state, timeout;
|
||||||
|
|
||||||
|
if (!usb_configured()) return -1;
|
||||||
|
intr_state = SREG;
|
||||||
|
cli();
|
||||||
|
UENUM = endpoint;
|
||||||
|
timeout = UDFNUML + 50;
|
||||||
|
while (1) {
|
||||||
|
// are we ready to transmit?
|
||||||
|
if (UEINTX & (1<<RWAL)) break;
|
||||||
|
SREG = intr_state;
|
||||||
|
// has the USB gone offline?
|
||||||
|
if (!usb_configured()) return -1;
|
||||||
|
// have we waited too long?
|
||||||
|
if (UDFNUML == timeout) return -1;
|
||||||
|
// get ready to try checking again
|
||||||
|
intr_state = SREG;
|
||||||
|
cli();
|
||||||
|
UENUM = endpoint;
|
||||||
|
}
|
||||||
|
UEDATX = report->mods;
|
||||||
|
UEDATX = 0;
|
||||||
|
for (uint8_t i = keys_start; i < keys_end; i++) {
|
||||||
|
UEDATX = report->keys[i];
|
||||||
|
}
|
||||||
|
UEINTX = 0x3A;
|
||||||
|
SREG = intr_state;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _add_key_byte(uint8_t code)
|
||||||
|
{
|
||||||
|
// TODO: fix ugly code
|
||||||
|
int8_t i = 0;
|
||||||
|
int8_t empty = -1;
|
||||||
|
for (; i < KEYS_MAX; i++) {
|
||||||
|
if (usb_keyboard_keys_prev[i] == code) {
|
||||||
|
usb_keyboard_keys[i] = code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (empty == -1 &&
|
||||||
|
usb_keyboard_keys_prev[i] == 0 &&
|
||||||
|
usb_keyboard_keys[i] == 0) {
|
||||||
|
empty = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == KEYS_MAX) {
|
||||||
|
if (empty != -1) {
|
||||||
|
usb_keyboard_keys[empty] = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _add_key_bit(uint8_t code)
|
||||||
|
{
|
||||||
|
if ((code>>3) < KEYS_MAX) {
|
||||||
|
usb_keyboard_keys[code>>3] |= 1<<(code&7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,26 @@
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
|
|
||||||
#define KEYBOARD_INTERFACE 0
|
#define KBD_INTERFACE 0
|
||||||
#define KEYBOARD_ENDPOINT 1
|
#define KBD_ENDPOINT 1
|
||||||
#ifdef USB_12KRO
|
#define KBD_SIZE 8
|
||||||
#define KEYBOARD_INTERFACE2 4
|
#define KBD_BUFFER EP_DOUBLE_BUFFER
|
||||||
#define KEYBOARD_ENDPOINT2 5
|
#define KBD_REPORT_KEYS (KBD_SIZE - 2)
|
||||||
|
|
||||||
|
// secondary keyboard
|
||||||
|
#ifdef NKRO_ENABLE
|
||||||
|
#define KBD2_INTERFACE 4
|
||||||
|
#define KBD2_ENDPOINT 5
|
||||||
|
#define KBD2_SIZE 16
|
||||||
|
#define KBD2_BUFFER EP_DOUBLE_BUFFER
|
||||||
|
#define KBD2_REPORT_KEYS (KBD2_SIZE - 2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS
|
||||||
|
#define KEYS_MAX KBD2_REPORT_KEYS
|
||||||
|
#else
|
||||||
|
#define KEYS_MAX KBD_REPORT_KEYS
|
||||||
#endif
|
#endif
|
||||||
#define KEYBOARD_SIZE 8
|
|
||||||
#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER
|
|
||||||
|
|
||||||
#define BIT_LCTRL (1<<0)
|
#define BIT_LCTRL (1<<0)
|
||||||
#define BIT_LSHIFT (1<<1)
|
#define BIT_LSHIFT (1<<1)
|
||||||
|
@ -28,13 +40,8 @@
|
||||||
#define BIT_LSFT BIT_LSHIFT
|
#define BIT_LSFT BIT_LSHIFT
|
||||||
#define BIT_RSFT BIT_RSHIFT
|
#define BIT_RSFT BIT_RSHIFT
|
||||||
|
|
||||||
#ifdef USB_12KRO
|
|
||||||
# define KEYBOARD_REPORT_MAX 12
|
|
||||||
#else
|
|
||||||
# define KEYBOARD_REPORT_MAX 6
|
|
||||||
#endif
|
|
||||||
typedef struct report {
|
typedef struct report {
|
||||||
uint8_t keys[KEYBOARD_REPORT_MAX];
|
uint8_t keys[KEYS_MAX];
|
||||||
uint8_t mods;
|
uint8_t mods;
|
||||||
bool is_sent;
|
bool is_sent;
|
||||||
} usb_keyboard_report_t;
|
} usb_keyboard_report_t;
|
||||||
|
@ -52,9 +59,9 @@ extern uint8_t usb_keyboard_protocol;
|
||||||
extern uint8_t usb_keyboard_idle_config;
|
extern uint8_t usb_keyboard_idle_config;
|
||||||
extern uint8_t usb_keyboard_idle_count;
|
extern uint8_t usb_keyboard_idle_count;
|
||||||
extern volatile uint8_t usb_keyboard_leds;
|
extern volatile uint8_t usb_keyboard_leds;
|
||||||
|
extern bool usb_keyboard_nkro;
|
||||||
|
|
||||||
|
|
||||||
int8_t usb_keyboard_press(uint8_t key, uint8_t modifier);
|
|
||||||
int8_t usb_keyboard_send(void);
|
int8_t usb_keyboard_send(void);
|
||||||
int8_t usb_keyboard_send_report(usb_keyboard_report_t *report);
|
int8_t usb_keyboard_send_report(usb_keyboard_report_t *report);
|
||||||
|
|
||||||
|
@ -64,7 +71,7 @@ void usb_keyboard_clear_report(void);
|
||||||
void usb_keyboard_clear_keys(void);
|
void usb_keyboard_clear_keys(void);
|
||||||
void usb_keyboard_clear_mods(void);
|
void usb_keyboard_clear_mods(void);
|
||||||
|
|
||||||
void usb_keyboard_set_keys(uint8_t keys[6]);
|
void usb_keyboard_set_keys(uint8_t *keys);
|
||||||
void usb_keyboard_set_mods(uint8_t mods);
|
void usb_keyboard_set_mods(uint8_t mods);
|
||||||
|
|
||||||
void usb_keyboard_add_code(uint8_t code);
|
void usb_keyboard_add_code(uint8_t code);
|
||||||
|
@ -79,6 +86,8 @@ bool usb_keyboard_is_sent(void);
|
||||||
bool usb_keyboard_has_key(void);
|
bool usb_keyboard_has_key(void);
|
||||||
bool usb_keyboard_has_mod(void);
|
bool usb_keyboard_has_mod(void);
|
||||||
|
|
||||||
|
uint8_t usb_keyboard_get_key(void);
|
||||||
|
|
||||||
void usb_keyboard_print_report(usb_keyboard_report_t *report);
|
void usb_keyboard_print_report(usb_keyboard_report_t *report);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,8 +59,10 @@ int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel, int8_t hwheel)
|
||||||
UEDATX = mouse_buttons;
|
UEDATX = mouse_buttons;
|
||||||
UEDATX = x;
|
UEDATX = x;
|
||||||
UEDATX = y;
|
UEDATX = y;
|
||||||
|
if (mouse_protocol) {
|
||||||
UEDATX = wheel;
|
UEDATX = wheel;
|
||||||
UEDATX = hwheel;
|
UEDATX = hwheel;
|
||||||
|
}
|
||||||
|
|
||||||
UEINTX = 0x3A;
|
UEINTX = 0x3A;
|
||||||
SREG = intr_state;
|
SREG = intr_state;
|
||||||
|
|
2
util.c
2
util.c
|
@ -1,5 +1,6 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
// bit population
|
||||||
int bitpop(uint8_t bits)
|
int bitpop(uint8_t bits)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
@ -8,6 +9,7 @@ int bitpop(uint8_t bits)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// most significant on-bit
|
||||||
int biton(uint8_t bits)
|
int biton(uint8_t bits)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
Loading…
Reference in a new issue