SRC += keyboard.c \ | |||||
SRC += host.c \ | |||||
keyboard.c \ | |||||
command.c \ | command.c \ | ||||
layer.c \ | layer.c \ | ||||
timer.c \ | timer.c \ | ||||
print.c \ | print.c \ | ||||
util.c | util.c | ||||
# Option modules | # Option modules | ||||
ifdef MOUSEKEY_ENABLE | ifdef MOUSEKEY_ENABLE | ||||
SRC += mousekey.c | SRC += mousekey.c | ||||
OPT_DEFS += -DMOUSEKEY_ENABLE | |||||
endif | endif | ||||
ifdef PS2_MOUSE_ENABLE | ifdef PS2_MOUSE_ENABLE | ||||
SRC += ps2.c \ | SRC += ps2.c \ | ||||
ps2_mouse.c | ps2_mouse.c | ||||
OPT_DEFS += -DPS2_MOUSE_ENABLE | |||||
endif | |||||
ifdef USB_EXTRA_ENABLE | |||||
OPT_DEFS += -DUSB_EXTRA_ENABLE | |||||
endif | |||||
ifdef USB_NKRO_ENABLE | |||||
OPT_DEFS += -DUSB_NKRO_ENABLE | |||||
endif | |||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
OPT_DEFS += -DUSB_MOUSE_ENABLE | |||||
endif | endif | ||||
include $(COMMON_DIR)/Makefile.rules | include $(COMMON_DIR)/Makefile.rules |
# Following variables need to be set in <target>/Makefile: | |||||
# TARGET | |||||
# COMMON_DIR | |||||
# TARGET_DIR | |||||
# TARGET_SRC | |||||
# MCU | |||||
# F_CPU | |||||
OPT_DEFS += -DHOST_PJRC | |||||
# List C source files here. (C dependencies are automatically generated.) | |||||
SRC = usb_keyboard.c \ | SRC = usb_keyboard.c \ | ||||
usb_debug.c \ | usb_debug.c \ | ||||
usb.c \ | usb.c \ | ||||
jump_bootloader.c | jump_bootloader.c | ||||
SRC += $(TARGET_SRC) | SRC += $(TARGET_SRC) | ||||
# C source file search path | |||||
VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/pjrc | |||||
# Option modules | # Option modules | ||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | ||||
SRC += usb_mouse.c | SRC += usb_mouse.c | ||||
ifdef USB_EXTRA_ENABLE | ifdef USB_EXTRA_ENABLE | ||||
SRC += usb_extra.c | SRC += usb_extra.c | ||||
endif | endif | ||||
# C source file search path | |||||
VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/pjrc |
CSTANDARD = -std=gnu99 | CSTANDARD = -std=gnu99 | ||||
ifdef MOUSEKEY_ENABLE | |||||
OPT_DEFS += -DMOUSEKEY_ENABLE | |||||
endif | |||||
ifdef PS2_MOUSE_ENABLE | |||||
OPT_DEFS += -DPS2_MOUSE_ENABLE | |||||
endif | |||||
ifdef USB_EXTRA_ENABLE | |||||
OPT_DEFS += -DUSB_EXTRA_ENABLE | |||||
endif | |||||
ifdef USB_NKRO_ENABLE | |||||
OPT_DEFS += -DUSB_NKRO_ENABLE | |||||
endif | |||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
OPT_DEFS += -DUSB_MOUSE_ENABLE | |||||
endif | |||||
# Place -D or -U options here for C sources | # Place -D or -U options here for C sources | ||||
CDEFS = -DF_CPU=$(F_CPU)UL | CDEFS = -DF_CPU=$(F_CPU)UL | ||||
CDEFS += $(OPT_DEFS) | CDEFS += $(OPT_DEFS) |
# Following variables need to be set in <target>/Makefile: | |||||
# TARGET | |||||
# COMMON_DIR | |||||
# TARGET_DIR | |||||
# TARGET_SRC | |||||
# MCU | |||||
# F_CPU | |||||
OPT_DEFS += -DHOST_VUSB | |||||
# List C source files here. (C dependencies are automatically generated.) | |||||
SRC = usbdrv.c \ | SRC = usbdrv.c \ | ||||
usbdrvasm.S \ | usbdrvasm.S \ | ||||
oddebug.c | oddebug.c |
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <util/delay.h> | |||||
#include "usb_keycodes.h" | |||||
#include "host.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "timer.h" | |||||
#include "layer.h" | |||||
#include "matrix_skel.h" | |||||
#include "command.h" | |||||
#ifdef HOST_PJRC | |||||
# include "jump_bootloader.h" | |||||
# include "usb_keyboard.h" | |||||
# ifdef USB_EXTRA_ENABLE | |||||
# include "usb_extra.h" | |||||
# endif | |||||
#endif | |||||
static void help(void); | |||||
static void switch_layer(uint8_t layer); | |||||
uint8_t command_proc(void) | |||||
{ | |||||
if (!IS_COMMAND()) | |||||
return 0; | |||||
uint8_t processed = 1; | |||||
bool last_print_enable = print_enable; | |||||
print_enable = true; | |||||
switch (keyboard_report->keys[0]) { | |||||
case KB_H: | |||||
help(); | |||||
break; | |||||
case KB_B: | |||||
#ifdef HOST_PJRC | |||||
host_clear_keyboard_report(); | |||||
host_send_keyboard_report(); | |||||
print("jump to bootloader...\n"); | |||||
_delay_ms(1000); | |||||
jump_bootloader(); // not return | |||||
#endif | |||||
break; | |||||
case KB_D: | |||||
debug_enable = !debug_enable; | |||||
if (debug_enable) { | |||||
last_print_enable = true; | |||||
print("debug enabled.\n"); | |||||
debug_matrix = true; | |||||
debug_keyboard = true; | |||||
debug_mouse = true; | |||||
} else { | |||||
print("debug disabled.\n"); | |||||
last_print_enable = false; | |||||
debug_matrix = false; | |||||
debug_keyboard = false; | |||||
debug_mouse = false; | |||||
} | |||||
break; | |||||
case KB_X: // debug matrix toggle | |||||
debug_matrix = !debug_matrix; | |||||
if (debug_matrix) | |||||
print("debug matrix enabled.\n"); | |||||
else | |||||
print("debug matrix disabled.\n"); | |||||
break; | |||||
case KB_K: // debug keyboard toggle | |||||
debug_keyboard = !debug_keyboard; | |||||
if (debug_keyboard) | |||||
print("debug keyboard enabled.\n"); | |||||
else | |||||
print("debug keyboard disabled.\n"); | |||||
break; | |||||
case KB_M: // debug mouse toggle | |||||
debug_mouse = !debug_mouse; | |||||
if (debug_mouse) | |||||
print("debug mouse enabled.\n"); | |||||
else | |||||
print("debug mouse disabled.\n"); | |||||
break; | |||||
case KB_V: // print version & information | |||||
print(STR(DESCRIPTION) "\n"); | |||||
break; | |||||
case KB_T: // print timer | |||||
print("timer: "); phex16(timer_count); print("\n"); | |||||
break; | |||||
case KB_P: // print toggle | |||||
if (print_enable) { | |||||
print("print disabled.\n"); | |||||
last_print_enable = false; | |||||
} else { | |||||
last_print_enable = true; | |||||
print("print enabled.\n"); | |||||
} | |||||
break; | |||||
case KB_S: | |||||
#ifdef HOST_PJRC | |||||
print("UDCON: "); phex(UDCON); print("\n"); | |||||
print("UDIEN: "); phex(UDIEN); print("\n"); | |||||
print("UDINT: "); phex(UDINT); print("\n"); | |||||
print("host_keyboard_leds:"); phex(host_keyboard_leds()); print("\n"); | |||||
#endif | |||||
break; | |||||
#ifdef USB_NKRO_ENABLE | |||||
case KB_N: | |||||
keyboard_nkro = !keyboard_nkro; | |||||
if (keyboard_nkro) | |||||
print("USB_NKRO: enabled\n"); | |||||
else | |||||
print("USB_NKRO: disabled\n"); | |||||
break; | |||||
#endif | |||||
#ifdef USB_EXTRA_ENABLE | |||||
case KB_ESC: | |||||
if (suspend && remote_wakeup) { | |||||
usb_remote_wakeup(); | |||||
} else { | |||||
usb_extra_system_send(SYSTEM_POWER_DOWN); | |||||
} | |||||
break; | |||||
#endif | |||||
case KB_BSPC: | |||||
matrix_init(); | |||||
print("clear matrix\n"); | |||||
break; | |||||
case KB_0: | |||||
switch_layer(0); | |||||
break; | |||||
case KB_1: | |||||
switch_layer(1); | |||||
break; | |||||
case KB_2: | |||||
switch_layer(2); | |||||
break; | |||||
case KB_3: | |||||
switch_layer(3); | |||||
break; | |||||
case KB_4: | |||||
switch_layer(4); | |||||
break; | |||||
default: | |||||
processed = 0; | |||||
} | |||||
if (processed) | |||||
_delay_ms(500); | |||||
print_enable = last_print_enable; | |||||
return processed; | |||||
} | |||||
static void help(void) | |||||
{ | |||||
print("b: jump to bootloader\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("s: print status\n"); | |||||
#ifdef USB_NKRO_ENABLE | |||||
print("n: toggle USB_NKRO\n"); | |||||
#endif | |||||
print("Backspace: clear matrix\n"); | |||||
print("ESC: power down/wake up\n"); | |||||
print("0: switch to Layer0 \n"); | |||||
print("1: switch to Layer1 \n"); | |||||
print("2: switch to Layer2 \n"); | |||||
print("3: switch to Layer3 \n"); | |||||
print("4: switch to Layer4 \n"); | |||||
} | |||||
static void switch_layer(uint8_t layer) | |||||
{ | |||||
print("current_layer: "); phex(current_layer); print("\n"); | |||||
print("default_layer: "); phex(default_layer); print("\n"); | |||||
current_layer = layer; | |||||
default_layer = layer; | |||||
print("switch to Layer: "); phex(layer); print("\n"); | |||||
} |
#ifndef COMMAND_H | |||||
#define COMMAND | |||||
uint8_t command_proc(void); | |||||
#endif |
# keyboard dependent files | # keyboard dependent files | ||||
TARGET_SRC = tmk.c \ | TARGET_SRC = tmk.c \ | ||||
host_pjrc.c \ | |||||
keymap.c \ | keymap.c \ | ||||
matrix.c \ | matrix.c \ | ||||
led.c | led.c |
/* matrix size */ | /* matrix size */ | ||||
#define MATRIX_ROWS 8 | #define MATRIX_ROWS 8 | ||||
#define MATRIX_COLS 8 | #define MATRIX_COLS 8 | ||||
/* define if matrix has ghost */ | /* define if matrix has ghost */ | ||||
//#define MATRIX_HAS_GHOST | //#define MATRIX_HAS_GHOST | ||||
/* key combination for command */ | |||||
#define IS_COMMAND() (keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT)) | |||||
/* USB NKey Rollover */ | /* USB NKey Rollover */ | ||||
#ifdef USB_NKRO_ENABLE | #ifdef USB_NKRO_ENABLE | ||||
#endif | #endif |
#include "stdint.h" | |||||
#include "led.h" | |||||
/* HHKB has no LEDs */ | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
} | |||||
#define MOUSE_BTN5 (1<<4) | #define MOUSE_BTN5 (1<<4) | ||||
#define REPORT_KEYS 6 | |||||
#if defined(HOST_PJRC) | |||||
# include "usb.h" | |||||
# if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS | |||||
# define REPORT_KEYS KBD2_REPORT_KEYS | |||||
# else | |||||
# define REPORT_KEYS KBD_REPORT_KEYS | |||||
# endif | |||||
#elif defined(HOST_VUSB) | |||||
# define REPORT_KEYS 6 | |||||
#endif | |||||
typedef struct { | typedef struct { | ||||
uint8_t mods; | uint8_t mods; | ||||
uint8_t rserved; | uint8_t rserved; | ||||
uint8_t buttons; | uint8_t buttons; | ||||
int8_t x; | int8_t x; | ||||
int8_t y; | int8_t y; | ||||
/* | |||||
int8_t v; | int8_t v; | ||||
int8_t h; | int8_t h; | ||||
*/ | |||||
} report_mouse_t; | } report_mouse_t; | ||||
#ifdef USB_NKRO_ENABLE | |||||
extern bool keyboard_nkro; | |||||
#endif | |||||
extern report_keyboard_t *keyboard_report; | extern report_keyboard_t *keyboard_report; | ||||
extern report_keyboard_t *keyboard_report_prev; | extern report_keyboard_t *keyboard_report_prev; | ||||
uint8_t host_keyboard_leds(void); | |||||
/* keyboard report operations */ | /* keyboard report operations */ | ||||
void host_add_key(uint8_t key); | void host_add_key(uint8_t key); | ||||
void host_add_mod_bit(uint8_t mod); | void host_add_mod_bit(uint8_t mod); | ||||
void host_send_keyboard_report(void); | void host_send_keyboard_report(void); | ||||
void host_send_mouse_report(void); | |||||
void host_mouse_send(report_mouse_t *report); | void host_mouse_send(report_mouse_t *report); | ||||
#endif | #endif |
#endif | #endif | ||||
static uint8_t last_led = 0; | |||||
static uint8_t last_leds = 0; | |||||
void keyboard_init(void) | void keyboard_init(void) | ||||
ps2_mouse_usb_send(); | ps2_mouse_usb_send(); | ||||
#endif | #endif | ||||
if (last_led != host_keyboard_led()) { | |||||
led_set(host_keyboard_led()); | |||||
last_led = host_keyboard_led(); | |||||
if (last_leds != host_keyboard_leds()) { | |||||
keyboard_set_leds(host_keyboard_leds()); | |||||
last_leds = host_keyboard_leds(); | |||||
} | } | ||||
} | } | ||||
void keyboard_set_leds(uint8_t leds) | |||||
{ | |||||
led_set(leds); | |||||
} |
#ifndef KEYBOARD_H | #ifndef KEYBOARD_H | ||||
#define KEYBOARD_H | #define KEYBOARD_H | ||||
#include <stdint.h> | |||||
void keyboard_init(void); | void keyboard_init(void); | ||||
void keyboard_proc(void); | void keyboard_proc(void); | ||||
void keyboard_set_leds(uint8_t leds); | |||||
#endif | #endif | ||||
#include "timer.h" | #include "timer.h" | ||||
#include "layer.h" | #include "layer.h" | ||||
/* | /* | ||||
* Parameters: | * Parameters: | ||||
* ENTER_DELAY |=======| | * ENTER_DELAY |=======| |
# define MOUSEKEY_DELAY_TIME 255 | # define MOUSEKEY_DELAY_TIME 255 | ||||
#endif | #endif | ||||
// acceleration parameters | |||||
uint8_t mousekey_move_unit = 2; | |||||
uint8_t mousekey_resolution = 5; | |||||
static inline uint8_t move_unit(void) | static inline uint8_t move_unit(void) | ||||
{ | { | ||||
uint16_t unit = 10 + (mousekey_repeat); | |||||
return (unit > 127 ? 127 : unit); | |||||
uint16_t unit = 5 + mousekey_repeat*2; | |||||
return (unit > 63 ? 63 : unit); | |||||
} | } | ||||
void mousekey_decode(uint8_t code) | void mousekey_decode(uint8_t code) | ||||
else if (code == KB_MS_BTN1) report.buttons |= MOUSE_BTN1; | else if (code == KB_MS_BTN1) report.buttons |= MOUSE_BTN1; | ||||
else if (code == KB_MS_BTN2) report.buttons |= MOUSE_BTN2; | else if (code == KB_MS_BTN2) report.buttons |= MOUSE_BTN2; | ||||
else if (code == KB_MS_BTN3) report.buttons |= MOUSE_BTN3; | else if (code == KB_MS_BTN3) report.buttons |= MOUSE_BTN3; | ||||
/* | |||||
else if (code == KB_MS_BTN4) report.buttons |= MOUSE_BTN4; | else if (code == KB_MS_BTN4) report.buttons |= MOUSE_BTN4; | ||||
else if (code == KB_MS_BTN5) report.buttons |= MOUSE_BTN5; | else if (code == KB_MS_BTN5) report.buttons |= MOUSE_BTN5; | ||||
else if (code == KB_MS_WH_UP) report.v += 1; | else if (code == KB_MS_WH_UP) report.v += 1; | ||||
else if (code == KB_MS_WH_DOWN) report.v -= 1; | else if (code == KB_MS_WH_DOWN) report.v -= 1; | ||||
else if (code == KB_MS_WH_LEFT) report.h -= 1; | else if (code == KB_MS_WH_LEFT) report.h -= 1; | ||||
else if (code == KB_MS_WH_RIGHT)report.h += 1; | else if (code == KB_MS_WH_RIGHT)report.h += 1; | ||||
*/ | |||||
} | } | ||||
bool mousekey_changed(void) | bool mousekey_changed(void) | ||||
{ | { | ||||
return (report.buttons != report_prev.buttons || | return (report.buttons != report_prev.buttons || | ||||
report.x != report_prev.x || | |||||
report.y != report_prev.y || | |||||
report.x || report.y); | |||||
//return (report.buttons != report_prev.buttons || report.x || report.y); | |||||
report.x || report.y || report.v || report.h); | |||||
} | } | ||||
void mousekey_send(void) | void mousekey_send(void) | ||||
if (!mousekey_changed()) { | if (!mousekey_changed()) { | ||||
mousekey_repeat = 0; | mousekey_repeat = 0; | ||||
mousekey_clear_report(); | |||||
return; | return; | ||||
} | } | ||||
// send immediately when buttun state is changed | // send immediately when buttun state is changed | ||||
if (report.buttons == report_prev.buttons) { | if (report.buttons == report_prev.buttons) { | ||||
// TODO: delay parameter setting | |||||
if ((timer_elapsed(last_timer) < (mousekey_repeat == 1 ? 20 : 5))) { | |||||
if (timer_elapsed(last_timer) < 5) { | |||||
mousekey_clear_report(); | |||||
return; | return; | ||||
} | } | ||||
} | } | ||||
if (mousekey_repeat != 0xFF) { | |||||
mousekey_repeat++; | |||||
} | |||||
if (report.x && report.y) { | if (report.x && report.y) { | ||||
report.x *= 0.7; | report.x *= 0.7; | ||||
report.y *= 0.7; | report.y *= 0.7; | ||||
} | } | ||||
/* | |||||
print("mousekey_repeat: "); phex(mousekey_repeat); print("\n"); | |||||
print("timer: "); phex16(timer_read()); print("\n"); | |||||
print("last_timer: "); phex16(last_timer); print("\n"); | |||||
print("mousekey: "); phex(report.buttons); print(" "); phex(report.x); print(" "); phex(report.y); print("\n"); | |||||
*/ | |||||
mousekey_debug(); | mousekey_debug(); | ||||
host_mouse_send(&report); | host_mouse_send(&report); | ||||
report_prev.buttons = report.buttons; | |||||
report_prev.x = report.x; | |||||
report_prev.y = report.y; | |||||
if (mousekey_repeat != 0xFF) mousekey_repeat++; | |||||
report_prev = report; | |||||
last_timer = timer_read(); | last_timer = timer_read(); | ||||
mousekey_clear_report(); | mousekey_clear_report(); | ||||
} | } | ||||
report.buttons = 0; | report.buttons = 0; | ||||
report.x = 0; | report.x = 0; | ||||
report.y = 0; | report.y = 0; | ||||
report.v = 0; | |||||
report.h = 0; | |||||
} | } | ||||
static void mousekey_debug(void) | static void mousekey_debug(void) | ||||
phex(report.buttons); print("|"); | phex(report.buttons); print("|"); | ||||
phex(report.x); print(" "); | phex(report.x); print(" "); | ||||
phex(report.y); print(" "); | phex(report.y); print(" "); | ||||
/* | |||||
phex(report.v); print(" "); | phex(report.v); print(" "); | ||||
phex(report.h); | phex(report.h); | ||||
*/ | |||||
phex(mousekey_repeat); | |||||
print("\n"); | print("\n"); | ||||
} | } |
#include <stdint.h> | |||||
#include "usb_keycodes.h" | |||||
#include "usb_keyboard.h" | |||||
#include "usb_mouse.h" | |||||
#include "debug.h" | |||||
#include "host.h" | |||||
#ifdef USB_NKRO_ENABLE | |||||
bool keyboard_nkro = false; | |||||
#endif | |||||
static report_keyboard_t report0; | |||||
static report_keyboard_t report1; | |||||
report_keyboard_t *keyboard_report = &report0; | |||||
report_keyboard_t *keyboard_report_prev = &report1; | |||||
static inline void add_key_byte(uint8_t code); | |||||
static inline void add_key_bit(uint8_t code); | |||||
uint8_t host_keyboard_leds(void) | |||||
{ | |||||
return usb_keyboard_leds; | |||||
} | |||||
/* keyboard report operations */ | |||||
void host_add_key(uint8_t key) | |||||
{ | |||||
#ifdef USB_NKRO_ENABLE | |||||
if (keyboard_nkro) { | |||||
add_key_bit(key); | |||||
return; | |||||
} | |||||
#endif | |||||
add_key_byte(key); | |||||
} | |||||
void host_add_mod_bit(uint8_t mod) | |||||
{ | |||||
keyboard_report->mods |= mod; | |||||
} | |||||
void host_set_mods(uint8_t mods) | |||||
{ | |||||
keyboard_report->mods = mods; | |||||
} | |||||
void host_add_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
host_add_mod_bit(MOD_BIT(code)); | |||||
} else { | |||||
host_add_key(code); | |||||
} | |||||
} | |||||
void host_swap_keyboard_report(void) | |||||
{ | |||||
report_keyboard_t *tmp = keyboard_report_prev; | |||||
keyboard_report_prev = keyboard_report; | |||||
keyboard_report = tmp; | |||||
} | |||||
void host_clear_keyboard_report(void) | |||||
{ | |||||
keyboard_report->mods = 0; | |||||
for (int8_t i = 0; i < REPORT_KEYS; i++) { | |||||
keyboard_report->keys[i] = 0; | |||||
} | |||||
} | |||||
uint8_t host_has_anykey(void) | |||||
{ | |||||
uint8_t cnt = 0; | |||||
for (int i = 0; i < REPORT_KEYS; i++) { | |||||
if (keyboard_report->keys[i]) | |||||
cnt++; | |||||
} | |||||
return cnt; | |||||
} | |||||
uint8_t *host_get_keys(void) | |||||
{ | |||||
return keyboard_report->keys; | |||||
} | |||||
uint8_t host_get_mods(void) | |||||
{ | |||||
return keyboard_report->mods; | |||||
} | |||||
void host_send_keyboard_report(void) | |||||
{ | |||||
usb_keyboard_send_report(keyboard_report); | |||||
} | |||||
void host_mouse_send(report_mouse_t *report) | |||||
{ | |||||
usb_mouse_send(report->x, report->y, report->v, report->h, report->buttons); | |||||
} | |||||
static inline void add_key_byte(uint8_t code) | |||||
{ | |||||
// TODO: fix ugly code | |||||
int8_t i = 0; | |||||
int8_t empty = -1; | |||||
for (; i < REPORT_KEYS; i++) { | |||||
if (keyboard_report_prev->keys[i] == code) { | |||||
keyboard_report->keys[i] = code; | |||||
break; | |||||
} | |||||
if (empty == -1 && | |||||
keyboard_report_prev->keys[i] == 0 && | |||||
keyboard_report->keys[i] == 0) { | |||||
empty = i; | |||||
} | |||||
} | |||||
if (i == REPORT_KEYS) { | |||||
if (empty != -1) { | |||||
keyboard_report->keys[empty] = code; | |||||
} | |||||
} | |||||
} | |||||
static inline void add_key_bit(uint8_t code) | |||||
{ | |||||
if ((code>>3) < REPORT_KEYS) { | |||||
keyboard_report->keys[code>>3] |= 1<<(code&7); | |||||
} else { | |||||
debug("add_key_bit: can't add: "); phex(code); debug("\n"); | |||||
} | |||||
} |
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) { | ||||
usb_keyboard_idle_count = 0; | usb_keyboard_idle_count = 0; | ||||
UEDATX = usb_keyboard_mods; | |||||
UEDATX = keyboard_report->mods; | |||||
UEDATX = 0; | UEDATX = 0; | ||||
for (i=0; i<6; i++) { | for (i=0; i<6; i++) { | ||||
UEDATX = usb_keyboard_keys[i]; | |||||
UEDATX = keyboard_report->keys[i]; | |||||
} | } | ||||
UEINTX = 0x3A; | UEINTX = 0x3A; | ||||
} | } | ||||
if (bmRequestType == 0xA1) { | if (bmRequestType == 0xA1) { | ||||
if (bRequest == HID_GET_REPORT) { | if (bRequest == HID_GET_REPORT) { | ||||
usb_wait_in_ready(); | usb_wait_in_ready(); | ||||
UEDATX = usb_keyboard_mods; | |||||
UEDATX = keyboard_report->mods; | |||||
UEDATX = 0; | UEDATX = 0; | ||||
for (i=0; i<6; i++) { | for (i=0; i<6; i++) { | ||||
UEDATX = usb_keyboard_keys[i]; | |||||
UEDATX = keyboard_report->keys[i]; | |||||
} | } | ||||
usb_send_in(); | usb_send_in(); | ||||
return; | return; |
void usb_remote_wakeup(void); | void usb_remote_wakeup(void); | ||||
#define EP_TYPE_CONTROL 0x00 | #define EP_TYPE_CONTROL 0x00 | ||||
#define EP_TYPE_BULK_IN 0x81 | #define EP_TYPE_BULK_IN 0x81 | ||||
#define EP_TYPE_BULK_OUT 0x80 | #define EP_TYPE_BULK_OUT 0x80 | ||||
#define ENDPOINT_HALT 0 | #define ENDPOINT_HALT 0 | ||||
#define TEST_MODE 2 | #define TEST_MODE 2 | ||||
/*------------------------------------------------------------------* | |||||
* Keyboard descriptor setting | |||||
*------------------------------------------------------------------*/ | |||||
#define KBD_INTERFACE 0 | |||||
#define KBD_ENDPOINT 1 | |||||
#define KBD_SIZE 8 | |||||
#define KBD_BUFFER EP_DOUBLE_BUFFER | |||||
#define KBD_REPORT_KEYS (KBD_SIZE - 2) | |||||
// secondary keyboard | |||||
#ifdef USB_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 - 1) | |||||
#endif | |||||
#endif | #endif |
#include "print.h" | #include "print.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include "host.h" | |||||
// keyboard report. | |||||
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; | |||||
// protocol setting from the host. We use exactly the same report | // protocol setting from the host. We use exactly the same report | ||||
// either way, so this variable only stores the setting since we | // either way, so this variable only stores the setting since we | ||||
// are required to be able to report which setting is in use. | // are required to be able to report which setting is in use. | ||||
// 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 USB NKRO | |||||
bool usb_keyboard_nkro = false; | |||||
static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end); | |||||
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) | |||||
int8_t usb_keyboard_send_report(report_keyboard_t *report) | |||||
{ | { | ||||
int8_t result = 0; | int8_t result = 0; | ||||
#ifdef USB_NKRO_ENABLE | #ifdef USB_NKRO_ENABLE | ||||
if (usb_keyboard_nkro) | |||||
result = _send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS); | |||||
if (keyboard_nkro) | |||||
result = send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS); | |||||
else | else | ||||
#endif | #endif | ||||
{ | { | ||||
if (usb_keyboard_protocol) | if (usb_keyboard_protocol) | ||||
result = _send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS); | |||||
result = send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS); | |||||
else | else | ||||
result = _send_report(report, KBD_ENDPOINT, 0, 6); | |||||
result = send_report(report, KBD_ENDPOINT, 0, 6); | |||||
} | } | ||||
if (result) return result; | if (result) return result; | ||||
usb_keyboard_idle_count = 0; | usb_keyboard_idle_count = 0; | ||||
report->is_sent =true; | |||||
usb_keyboard_print_report(report); | usb_keyboard_print_report(report); | ||||
return 0; | return 0; | ||||
} | } | ||||
void usb_keyboard_swap_report(void) { | |||||
usb_keyboard_report_t *tmp = usb_keyboard_report_prev; | |||||
usb_keyboard_report_prev = usb_keyboard_report; | |||||
usb_keyboard_report = tmp; | |||||
} | |||||
void usb_keyboard_clear_report(void) { | |||||
usb_keyboard_clear_keys(); | |||||
usb_keyboard_clear_mods(); | |||||
usb_keyboard_report->is_sent = false; | |||||
} | |||||
void usb_keyboard_clear_keys(void) { | |||||
for (int i = 0; i < KEYS_MAX; i++) usb_keyboard_report->keys[i] = 0; | |||||
} | |||||
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)) { | |||||
usb_keyboard_add_mod(code); | |||||
} else { | |||||
usb_keyboard_add_key(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) | |||||
{ | |||||
#ifdef USB_NKRO_ENABLE | |||||
if (usb_keyboard_nkro) { | |||||
_add_key_bit(code); | |||||
return; | |||||
} | |||||
#endif | |||||
_add_key_byte(code); | |||||
} | |||||
void usb_keyboard_add_mod(uint8_t code) | |||||
{ | |||||
usb_keyboard_report->mods |= MOD_BIT(code); | |||||
} | |||||
void usb_keyboard_del_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
usb_keyboard_del_mod(code); | |||||
} else { | |||||
usb_keyboard_del_key(code); | |||||
} | |||||
} | |||||
void usb_keyboard_del_key(uint8_t code) | |||||
{ | |||||
#ifdef USB_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) | |||||
{ | |||||
usb_keyboard_report->mods &= ~MOD_BIT(code); | |||||
} | |||||
bool usb_keyboard_is_sent(void) | |||||
{ | |||||
return usb_keyboard_report->is_sent; | |||||
} | |||||
bool usb_keyboard_has_key(void) | |||||
{ | |||||
uint8_t keys = 0; | |||||
for (int i = 0; i < KEYS_MAX; i++) keys |= usb_keyboard_report->keys[i]; | |||||
return keys ? true : false; | |||||
} | |||||
bool usb_keyboard_has_mod(void) | |||||
{ | |||||
return usb_keyboard_report->mods ? true : false; | |||||
} | |||||
uint8_t usb_keyboard_get_key(void) | |||||
{ | |||||
#ifdef USB_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(report_keyboard_t *report) | |||||
{ | { | ||||
if (!debug_keyboard) return; | if (!debug_keyboard) return; | ||||
print("keys: "); | print("keys: "); | ||||
for (int i = 0; i < KEYS_MAX; i++) { phex(report->keys[i]); print(" "); } | |||||
for (int i = 0; i < REPORT_KEYS; 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) | |||||
static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end) | |||||
{ | { | ||||
uint8_t intr_state, timeout; | uint8_t intr_state, timeout; | ||||
UENUM = endpoint; | UENUM = endpoint; | ||||
} | } | ||||
UEDATX = report->mods; | UEDATX = report->mods; | ||||
if (!usb_keyboard_nkro) | |||||
if (!keyboard_nkro) | |||||
UEDATX = 0; | UEDATX = 0; | ||||
for (uint8_t i = keys_start; i < keys_end; i++) { | for (uint8_t i = keys_start; i < keys_end; i++) { | ||||
UEDATX = report->keys[i]; | UEDATX = report->keys[i]; | ||||
SREG = intr_state; | SREG = intr_state; | ||||
return 0; | 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); | |||||
} | |||||
} | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include "usb.h" | #include "usb.h" | ||||
#include "host.h" | |||||
#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 USB_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 - 1) | |||||
#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 | |||||
typedef struct report { | |||||
uint8_t keys[KEYS_MAX]; | |||||
uint8_t mods; | |||||
bool is_sent; | |||||
} usb_keyboard_report_t; | |||||
#define usb_keyboard_keys usb_keyboard_report->keys | |||||
#define usb_keyboard_mods usb_keyboard_report->mods | |||||
#define usb_keyboard_keys_prev usb_keyboard_report_prev->keys | |||||
#define usb_keyboard_mods_prev usb_keyboard_report_prev->mods | |||||
extern usb_keyboard_report_t *usb_keyboard_report; | |||||
extern usb_keyboard_report_t *usb_keyboard_report_prev; | |||||
extern uint8_t usb_keyboard_protocol; | 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_send(void); | |||||
int8_t usb_keyboard_send_report(usb_keyboard_report_t *report); | |||||
void usb_keyboard_swap_report(void); | |||||
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); | |||||
void usb_keyboard_set_mods(uint8_t mods); | |||||
void usb_keyboard_add_code(uint8_t code); | |||||
void usb_keyboard_add_key(uint8_t code); | |||||
void usb_keyboard_add_mod(uint8_t code); | |||||
void usb_keyboard_del_code(uint8_t code); | |||||
void usb_keyboard_del_key(uint8_t code); | |||||
void usb_keyboard_del_mod(uint8_t code); | |||||
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); | |||||
int8_t usb_keyboard_send_report(report_keyboard_t *report); | |||||
void usb_keyboard_print_report(report_keyboard_t *report); | |||||
#endif | #endif |
matrix.c \ | matrix.c \ | ||||
led.c \ | led.c \ | ||||
ps2.c \ | ps2.c \ | ||||
host_vusb.c \ | |||||
usart_print.c | usart_print.c | ||||
OPT_DEFS = -DDEBUG_LEVEL=0 | OPT_DEFS = -DDEBUG_LEVEL=0 |
PS/2 to USB keyboard converter with V-USB | |||||
========================================= | |||||
2011/02/07 | |||||
NOT COMPLETED | |||||
development was suspended. | |||||
TODO: | |||||
PS/2 library: losts data from keyboard occasionally, | |||||
should use interrupt thoroughly for communication. | |||||
Code cleaning: merge code changed here to other subprojects and common modules. |
/* matrix size */ | /* matrix size */ | ||||
#define MATRIX_ROWS 32 // keycode bit: 3-0 | #define MATRIX_ROWS 32 // keycode bit: 3-0 | ||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | #define MATRIX_COLS 8 // keycode bit: 6-4 | ||||
/* define if matrix has ghost */ | |||||
//#define MATRIX_HAS_GHOST | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ | |||||
keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ | |||||
) | |||||
/* USB NKey Rollover */ | /* USB NKey Rollover */ | ||||
#ifdef USB_NKRO_ENABLE | #ifdef USB_NKRO_ENABLE | ||||
# define MOUSEKEY_DELAY_TIME 255 | # define MOUSEKEY_DELAY_TIME 255 | ||||
#endif | #endif | ||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ | |||||
keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ | |||||
) | |||||
/* PS/2 lines */ | /* PS/2 lines */ | ||||
#define PS2_CLOCK_PORT PORTD | #define PS2_CLOCK_PORT PORTD |
report_keyboard_t *keyboard_report = &report0; | report_keyboard_t *keyboard_report = &report0; | ||||
report_keyboard_t *keyboard_report_prev = &report1; | report_keyboard_t *keyboard_report_prev = &report1; | ||||
static uint8_t keyboard_led = 0; | |||||
static uint8_t keyboard_leds = 0; | |||||
static uchar idleRate = 0; | static uchar idleRate = 0; | ||||
uint8_t host_keyboard_led(void) | |||||
uint8_t host_keyboard_leds(void) | |||||
{ | { | ||||
return keyboard_led; | |||||
return keyboard_leds; | |||||
} | } | ||||
switch (last_req.kind) { | switch (last_req.kind) { | ||||
case SET_LED: | case SET_LED: | ||||
//debug("SET_LED\n"); | //debug("SET_LED\n"); | ||||
keyboard_led = data[0]; | |||||
keyboard_leds = data[0]; | |||||
last_req.len = 0; | last_req.len = 0; | ||||
return 1; | return 1; | ||||
break; | break; |