mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-11-03 23:02:34 +01:00 
			
		
		
		
	add build option: NKRO_ENABLE(remove: USB_12KRO)
This commit is contained in:
		
							parent
							
								
									66ece29b0e
								
							
						
					
					
						commit
						51f17f0231
					
				@ -129,8 +129,8 @@ CDEFS += -DPRODUCT=$(PRODUCT)
 | 
			
		||||
ifdef MOUSE_DELAY_TIME
 | 
			
		||||
CDEFS += -DMOUSE_DELAY_TIME=$(MOUSE_DELAY_TIME)
 | 
			
		||||
endif
 | 
			
		||||
ifdef USB_12KRO
 | 
			
		||||
CDEFS += -DUSB_12KRO
 | 
			
		||||
ifdef NKRO_ENABLE
 | 
			
		||||
CDEFS += -DNKRO_ENABLE
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										109
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								README
									
									
									
									
									
								
							@ -2,42 +2,23 @@ t.m.k. Keyboard Firmware
 | 
			
		||||
========================
 | 
			
		||||
http://github.com/tmk/tmk_keyboard
 | 
			
		||||
 | 
			
		||||
This is keyboard firmware for PFU HHKB style keyboard and Teensy/Teensy++ 2.0.
 | 
			
		||||
OS see this as composite device which has keyboard and mouse.
 | 
			
		||||
This is keyboard firmware for AVR USB MCUs or Teensy/Teensy++ 2.0.
 | 
			
		||||
 | 
			
		||||
The project is heavily based on PJRC USB Keyboard/Mouse Example and
 | 
			
		||||
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
 | 
			
		||||
        Matrix wiring changed for casing.
 | 
			
		||||
        (and my Teensy PD3 seems to be latchuped and unusable. :<)
 | 
			
		||||
 | 
			
		||||
1.2     2010/10/13
 | 
			
		||||
        HHKB support
 | 
			
		||||
        horizontal mouse wheel support
 | 
			
		||||
        change keymaps
 | 
			
		||||
 | 
			
		||||
2.0     2010/10/27
 | 
			
		||||
        HHKB/Macway support merged
 | 
			
		||||
Functions
 | 
			
		||||
---------
 | 
			
		||||
Mouse key
 | 
			
		||||
System Control Key
 | 
			
		||||
    Power Down, Sleep, Wake Up & USB Remote Wake up
 | 
			
		||||
Media Control Key
 | 
			
		||||
    Volume Down/Up, Mute
 | 
			
		||||
USB NKRO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
$ make
 | 
			
		||||
 | 
			
		||||
http://winavr.sourceforge.net/
 | 
			
		||||
 | 
			
		||||
Debuging
 | 
			
		||||
--------
 | 
			
		||||
Debug print is on if 4 keys are pressed during booting. 
 | 
			
		||||
 | 
			
		||||
Debuging & Rescue
 | 
			
		||||
-----------------
 | 
			
		||||
Use PJRC's hid_listen.exe to see debug messages.
 | 
			
		||||
Press right Control + Shift + Alt + GUI + H to debug menu. 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
AVR Target board
 | 
			
		||||
----------------
 | 
			
		||||
Teensy/Teensy++
 | 
			
		||||
http://www.pjrc.com/teensy
 | 
			
		||||
Pressing any 3 keys when connected enables debug output.
 | 
			
		||||
Pressing any 4 keys when connected makes bootloader comes up.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Projects related
 | 
			
		||||
@ -83,59 +63,4 @@ 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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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".
 | 
			
		||||
#----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
# TODO: use config.h for build options?
 | 
			
		||||
VENDOR_ID = 0xFEED
 | 
			
		||||
PRODUCT_ID = 0xCAFE
 | 
			
		||||
MANUFACTURER = 't.m.k.'
 | 
			
		||||
PRODUCT = 't.m.k. HHKB pro'
 | 
			
		||||
PRODUCT = 'HHKB Mod'
 | 
			
		||||
DESCRIPTION = 't.m.k. firmware for HHKB pro'
 | 
			
		||||
 | 
			
		||||
MOUSE_DELAY_TIME = 127
 | 
			
		||||
USB_12KRO = yes
 | 
			
		||||
NKRO_ENABLE = true
 | 
			
		||||
 | 
			
		||||
# Target file name (without extension).
 | 
			
		||||
TARGET = tmk_hhkb
 | 
			
		||||
 | 
			
		||||
@ -42,8 +42,8 @@ static const uint8_t PROGMEM fn_keycode[] = {
 | 
			
		||||
    KB_NO,          // FN_0 [NOT USED]
 | 
			
		||||
    KB_NO,          // FN_1 layer 1
 | 
			
		||||
    KB_SLSH,        // FN_2 layer 2
 | 
			
		||||
    KB_SCOLON,      // FN_3 layer 3
 | 
			
		||||
    KB_SPACE,       // FN_4 layer 4
 | 
			
		||||
    KB_SCLN,        // FN_3 layer 3
 | 
			
		||||
    KB_SPC,         // FN_4 layer 4
 | 
			
		||||
    KB_NO,          // FN_5 [NOT USED]
 | 
			
		||||
    KB_NO,          // FN_6 [NOT USED]
 | 
			
		||||
    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_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_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)
 | 
			
		||||
     * ,-----------------------------------------------------------.
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
@ -68,7 +69,7 @@ void proc_matrix(void) {
 | 
			
		||||
            if (code == KB_NO) {
 | 
			
		||||
                // do nothing
 | 
			
		||||
            } else if (IS_MOD(code)) {
 | 
			
		||||
                usb_keyboard_mods |= MOD_BIT(code);
 | 
			
		||||
                usb_keyboard_add_mod(code);
 | 
			
		||||
            } else if (IS_FN(code)) {
 | 
			
		||||
                fn_bits |= FN_BIT(code);
 | 
			
		||||
            } else if (IS_MOUSE(code)) {
 | 
			
		||||
@ -111,22 +112,7 @@ void proc_matrix(void) {
 | 
			
		||||
 | 
			
		||||
            // normal keys
 | 
			
		||||
            else {
 | 
			
		||||
                // TODO: fix ugly 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;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                usb_keyboard_add_key(code);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -142,20 +128,24 @@ void proc_matrix(void) {
 | 
			
		||||
    layer_switching(fn_bits);
 | 
			
		||||
 | 
			
		||||
    // TODO: clean code
 | 
			
		||||
    // when 4 left modifier keys down
 | 
			
		||||
    // special mode for control, develop and debug
 | 
			
		||||
    if (keymap_is_special_mode(fn_bits)) {
 | 
			
		||||
        switch (usb_keyboard_keys[0]) {
 | 
			
		||||
        switch (usb_keyboard_get_key()) {
 | 
			
		||||
            case KB_H: // help
 | 
			
		||||
                print_enable = true;
 | 
			
		||||
                print("b: jump to bootloader\n");
 | 
			
		||||
                print("d: debug print toggle\n");
 | 
			
		||||
                print("x: matrix debug toggle\n");
 | 
			
		||||
                print("k: keyboard debug toggle\n");
 | 
			
		||||
                print("m: mouse debug toggle\n");
 | 
			
		||||
                print("p: print enable toggle\n");
 | 
			
		||||
                print("d: toggle debug enable\n");
 | 
			
		||||
                print("x: toggle matrix debug\n");
 | 
			
		||||
                print("k: toggle keyboard debug\n");
 | 
			
		||||
                print("m: toggle mouse debug\n");
 | 
			
		||||
                print("p: toggle print enable\n");
 | 
			
		||||
                print("v: print version\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");
 | 
			
		||||
                _delay_ms(500);
 | 
			
		||||
                print_enable = false;
 | 
			
		||||
@ -243,13 +233,42 @@ void proc_matrix(void) {
 | 
			
		||||
                }
 | 
			
		||||
                _delay_ms(1000);
 | 
			
		||||
                break;
 | 
			
		||||
            case KB_R:
 | 
			
		||||
            case KB_S:
 | 
			
		||||
                usb_keyboard_clear_report();
 | 
			
		||||
                usb_keyboard_send();
 | 
			
		||||
                print("UDCON: "); phex(UDCON); print("\n");
 | 
			
		||||
                print("UDIEN: "); phex(UDIEN); 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);
 | 
			
		||||
                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:
 | 
			
		||||
                usb_keyboard_clear_report();
 | 
			
		||||
                usb_keyboard_send();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								tmk.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tmk.c
									
									
									
									
									
								
							@ -66,8 +66,7 @@ int main(void)
 | 
			
		||||
 | 
			
		||||
    matrix_init();
 | 
			
		||||
    matrix_scan();
 | 
			
		||||
    // bootloader comes up when any 4 or more keys are pressed at startup
 | 
			
		||||
    if (matrix_key_count() >= 4) {
 | 
			
		||||
    if (matrix_key_count() >= 3) {
 | 
			
		||||
#ifdef DEBUG_LED
 | 
			
		||||
        for (int i = 0; i < 6; i++) {
 | 
			
		||||
            DEBUG_LED_CONFIG;
 | 
			
		||||
@ -80,6 +79,13 @@ int main(void)
 | 
			
		||||
        _delay_ms(5000);
 | 
			
		||||
#endif
 | 
			
		||||
        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");
 | 
			
		||||
        _delay_ms(1000);
 | 
			
		||||
        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.
 | 
			
		||||
static const uint8_t PROGMEM endpoint_config_table[] = {
 | 
			
		||||
	// 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(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
 | 
			
		||||
	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(EXTRA_SIZE)    | EXTRA_BUFFER,    // 4
 | 
			
		||||
#ifdef USB_12KRO
 | 
			
		||||
	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 5
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KBD2_SIZE)      | KBD2_BUFFER,      // 5
 | 
			
		||||
#else
 | 
			
		||||
        0, // 5
 | 
			
		||||
#endif
 | 
			
		||||
@ -158,16 +158,52 @@ static 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(255),
 | 
			
		||||
        0x05, 0x07,          //   Usage Page (Key Codes),
 | 
			
		||||
        0x19, 0x00,          //   Usage Minimum (0),
 | 
			
		||||
        0x29, 0x68,          //   Usage Maximum (104),
 | 
			
		||||
        0x29, 0xFF,          //   Usage Maximum (255),
 | 
			
		||||
        0x81, 0x00,          //   Input (Data, Array),
 | 
			
		||||
        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
 | 
			
		||||
// 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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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 DEBUG_HID_DESC_OFFSET	(9+(9+9+7)*2+9)
 | 
			
		||||
#define EXTRA_HID_DESC_OFFSET	(9+(9+9+7)*3+9)
 | 
			
		||||
#ifdef USB_12KRO
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
#   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
 | 
			
		||||
#   define NUM_INTERFACES	4
 | 
			
		||||
#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
 | 
			
		||||
	9,					// bLength
 | 
			
		||||
	4,					// bDescriptorType
 | 
			
		||||
	KEYBOARD_INTERFACE,			// bInterfaceNumber
 | 
			
		||||
	KBD_INTERFACE,				// bInterfaceNumber
 | 
			
		||||
	0,					// bAlternateSetting
 | 
			
		||||
	1,					// bNumEndpoints
 | 
			
		||||
	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
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
 | 
			
		||||
	9,					// bLength
 | 
			
		||||
@ -353,8 +389,13 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
 | 
			
		||||
	0,					// bAlternateSetting
 | 
			
		||||
	1,					// bNumEndpoints
 | 
			
		||||
	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)
 | 
			
		||||
	0x02,					// bInterfaceProtocol (0x02 = Mouse)
 | 
			
		||||
*/
 | 
			
		||||
	0,					// iInterface
 | 
			
		||||
	// HID descriptor, HID 1.11 spec, section 6.2.1
 | 
			
		||||
	9,					// bLength
 | 
			
		||||
@ -427,11 +468,11 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
 | 
			
		||||
	EXTRA_SIZE, 0,				// wMaxPacketSize
 | 
			
		||||
	10,					// bInterval
 | 
			
		||||
 | 
			
		||||
#ifdef USB_12KRO
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
 | 
			
		||||
	9,					// bLength
 | 
			
		||||
	4,					// bDescriptorType
 | 
			
		||||
	KEYBOARD_INTERFACE2,			// bInterfaceNumber
 | 
			
		||||
	KBD2_INTERFACE,				// bInterfaceNumber
 | 
			
		||||
	0,					// bAlternateSetting
 | 
			
		||||
	1,					// bNumEndpoints
 | 
			
		||||
	0x03,					// bInterfaceClass (0x03 = HID)
 | 
			
		||||
@ -445,14 +486,14 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
 | 
			
		||||
	0,					// bCountryCode
 | 
			
		||||
	1,					// bNumDescriptors
 | 
			
		||||
	0x22,					// bDescriptorType
 | 
			
		||||
	sizeof(keyboard_hid_report_desc),     	// wDescriptorLength
 | 
			
		||||
	sizeof(keyboard2_hid_report_desc),     	// wDescriptorLength
 | 
			
		||||
	0,
 | 
			
		||||
	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
 | 
			
		||||
	7,					// bLength
 | 
			
		||||
	5,					// bDescriptorType
 | 
			
		||||
	KEYBOARD_ENDPOINT2 | 0x80,		// bEndpointAddress
 | 
			
		||||
	KBD2_ENDPOINT | 0x80,			// bEndpointAddress
 | 
			
		||||
	0x03,					// bmAttributes (0x03=intr)
 | 
			
		||||
	KEYBOARD_SIZE, 0,			// wMaxPacketSize
 | 
			
		||||
	KBD2_SIZE, 0,				// wMaxPacketSize
 | 
			
		||||
	1,					// bInterval
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
@ -494,17 +535,17 @@ static struct descriptor_list_struct {
 | 
			
		||||
        // CONFIGURATION descriptor
 | 
			
		||||
	{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
 | 
			
		||||
        // HID/REPORT descriptors
 | 
			
		||||
	{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
 | 
			
		||||
	{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
 | 
			
		||||
	{0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9},
 | 
			
		||||
	{0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
 | 
			
		||||
	{0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
 | 
			
		||||
	{0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
 | 
			
		||||
	{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
 | 
			
		||||
	{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
 | 
			
		||||
	{0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
 | 
			
		||||
	{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
 | 
			
		||||
#ifdef USB_12KRO
 | 
			
		||||
	{0x2100, KEYBOARD_INTERFACE2, config1_descriptor+KEYBOARD2_HID_DESC_OFFSET, 9},
 | 
			
		||||
	{0x2200, KEYBOARD_INTERFACE2, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
 | 
			
		||||
#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},
 | 
			
		||||
@ -603,7 +644,7 @@ ISR(USB_GEN_vect)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (usb_keyboard_idle_config && (++div4 & 3) == 0) {
 | 
			
		||||
			UENUM = KEYBOARD_ENDPOINT;
 | 
			
		||||
			UENUM = KBD_ENDPOINT;
 | 
			
		||||
			if (UEINTX & (1<<RWAL)) {
 | 
			
		||||
				usb_keyboard_idle_count++;
 | 
			
		||||
				if (usb_keyboard_idle_count == usb_keyboard_idle_config) {
 | 
			
		||||
@ -728,10 +769,12 @@ ISR(USB_COM_vect)
 | 
			
		||||
			for (i=1; i<=6; i++) {
 | 
			
		||||
				UENUM = i;
 | 
			
		||||
				en = pgm_read_byte(cfg++);
 | 
			
		||||
				UECONX = en;
 | 
			
		||||
                                if (en) {
 | 
			
		||||
                                    UECONX = (1<<EPEN);
 | 
			
		||||
                                    UECFG0X = pgm_read_byte(cfg++);
 | 
			
		||||
                                    UECFG1X = pgm_read_byte(cfg++);
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    UECONX = 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
        		UERST = 0x7E;
 | 
			
		||||
@ -788,7 +831,7 @@ ISR(USB_COM_vect)
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
		}
 | 
			
		||||
		if (wIndex == KEYBOARD_INTERFACE) {
 | 
			
		||||
		if (wIndex == KBD_INTERFACE) {
 | 
			
		||||
			if (bmRequestType == 0xA1) {
 | 
			
		||||
				if (bRequest == HID_GET_REPORT) {
 | 
			
		||||
					usb_wait_in_ready();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										198
									
								
								usb_keyboard.c
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								usb_keyboard.c
									
									
									
									
									
								
							@ -4,11 +4,12 @@
 | 
			
		||||
#include "usb_keyboard.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// keyboard report.
 | 
			
		||||
static usb_keyboard_report_t _report0 = { {0}, 0 };
 | 
			
		||||
static usb_keyboard_report_t _report1 = { {0}, 0 };
 | 
			
		||||
static usb_keyboard_report_t _report0 = { {0}, 0, false };
 | 
			
		||||
static usb_keyboard_report_t _report1 = { {0}, 0, false };
 | 
			
		||||
usb_keyboard_report_t *usb_keyboard_report = &_report0;
 | 
			
		||||
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
 | 
			
		||||
volatile uint8_t usb_keyboard_leds=0;
 | 
			
		||||
 | 
			
		||||
// enable NKRO
 | 
			
		||||
bool usb_keyboard_nkro = false;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int8_t usb_keyboard_send(void)
 | 
			
		||||
{
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t i, intr_state, timeout;
 | 
			
		||||
    int8_t result = 0;
 | 
			
		||||
 | 
			
		||||
	if (!usb_configured()) return -1;
 | 
			
		||||
	intr_state = SREG;
 | 
			
		||||
	cli();
 | 
			
		||||
	UENUM = KEYBOARD_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 = 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;
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (usb_keyboard_nkro)
 | 
			
		||||
        result = _send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS);
 | 
			
		||||
    else
 | 
			
		||||
#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;
 | 
			
		||||
    report->is_sent =true;
 | 
			
		||||
    usb_keyboard_print_report(report);
 | 
			
		||||
@ -111,7 +74,7 @@ void usb_keyboard_clear_report(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)
 | 
			
		||||
@ -119,6 +82,17 @@ void usb_keyboard_clear_mods(void)
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) {
 | 
			
		||||
        if (!usb_keyboard_report->keys[i]) {
 | 
			
		||||
            usb_keyboard_report->keys[i] = code;
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (usb_keyboard_nkro) {
 | 
			
		||||
        _add_key_bit(code);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
#endif
 | 
			
		||||
    _add_key_byte(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)
 | 
			
		||||
{
 | 
			
		||||
    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) {
 | 
			
		||||
            usb_keyboard_report->keys[i] = KB_NO;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_keyboard_del_mod(uint8_t code)
 | 
			
		||||
@ -186,7 +158,7 @@ bool usb_keyboard_is_sent(void)
 | 
			
		||||
bool usb_keyboard_has_key(void)
 | 
			
		||||
{
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -195,10 +167,86 @@ bool usb_keyboard_has_mod(void)
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    if (!debug_keyboard) return;
 | 
			
		||||
    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");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define KEYBOARD_INTERFACE	0
 | 
			
		||||
#define KEYBOARD_ENDPOINT	1
 | 
			
		||||
#ifdef USB_12KRO
 | 
			
		||||
#define KEYBOARD_INTERFACE2	4
 | 
			
		||||
#define KEYBOARD_ENDPOINT2	5
 | 
			
		||||
#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		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
 | 
			
		||||
#define KEYBOARD_SIZE		8
 | 
			
		||||
#define KEYBOARD_BUFFER		EP_DOUBLE_BUFFER
 | 
			
		||||
 | 
			
		||||
#define BIT_LCTRL   (1<<0)
 | 
			
		||||
#define BIT_LSHIFT  (1<<1)
 | 
			
		||||
@ -28,13 +40,8 @@
 | 
			
		||||
#define BIT_LSFT BIT_LSHIFT
 | 
			
		||||
#define BIT_RSFT BIT_RSHIFT
 | 
			
		||||
 | 
			
		||||
#ifdef USB_12KRO
 | 
			
		||||
#   define KEYBOARD_REPORT_MAX	12
 | 
			
		||||
#else
 | 
			
		||||
#   define KEYBOARD_REPORT_MAX	6
 | 
			
		||||
#endif
 | 
			
		||||
typedef struct report {
 | 
			
		||||
    uint8_t keys[KEYBOARD_REPORT_MAX];
 | 
			
		||||
    uint8_t keys[KEYS_MAX];
 | 
			
		||||
    uint8_t mods;
 | 
			
		||||
    bool is_sent;
 | 
			
		||||
} 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_count;
 | 
			
		||||
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_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_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_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_mod(void);
 | 
			
		||||
 | 
			
		||||
uint8_t usb_keyboard_get_key(void);
 | 
			
		||||
 | 
			
		||||
void usb_keyboard_print_report(usb_keyboard_report_t *report);
 | 
			
		||||
 | 
			
		||||
#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 = x;
 | 
			
		||||
	UEDATX = y;
 | 
			
		||||
        if (mouse_protocol) {
 | 
			
		||||
            UEDATX = wheel;
 | 
			
		||||
            UEDATX = hwheel;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
	UEINTX = 0x3A;
 | 
			
		||||
	SREG = intr_state;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user