summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/bootloader.c22
-rw-r--r--common/bootloader.h25
-rw-r--r--common/command.c243
-rw-r--r--common/command.h25
-rw-r--r--common/controller_teensy.h27
-rw-r--r--common/debug.h36
-rw-r--r--common/host.c237
-rw-r--r--common/host.h57
-rw-r--r--common/host_driver.h33
-rw-r--r--common/keyboard.c203
-rw-r--r--common/keyboard.h28
-rw-r--r--common/keymap.h34
-rw-r--r--common/layer.c207
-rw-r--r--common/layer.h32
-rw-r--r--common/led.h33
-rw-r--r--common/matrix.h49
-rwxr-xr-xcommon/mousekey.c132
-rw-r--r--common/mousekey.h29
-rw-r--r--common/print.c93
-rw-r--r--common/print.h45
-rw-r--r--common/report.h96
-rw-r--r--common/sendchar.h27
-rw-r--r--common/sendchar_null.c23
-rw-r--r--common/sendchar_uart.c25
-rw-r--r--common/timer.c89
-rw-r--r--common/timer.h53
-rw-r--r--common/uart.c129
-rw-r--r--common/uart.h11
-rw-r--r--common/usb_keycodes.h423
-rw-r--r--common/util.c37
-rw-r--r--common/util.h34
31 files changed, 2537 insertions, 0 deletions
diff --git a/common/bootloader.c b/common/bootloader.c
new file mode 100644
index 0000000000..5cbfc72e5b
--- /dev/null
+++ b/common/bootloader.c
@@ -0,0 +1,22 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "bootloader.h"
+
+
+void bootloader_jump(void) __attribute__ ((weak));
+void bootloader_jump(void) {}
diff --git a/common/bootloader.h b/common/bootloader.h
new file mode 100644
index 0000000000..44775039d5
--- /dev/null
+++ b/common/bootloader.h
@@ -0,0 +1,25 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BOOTLOADER_H
+#define BOOTLOADER_H
+
+
+/* give code for your bootloader to come up if needed */
+void bootloader_jump(void);
+
+#endif
diff --git a/common/command.c b/common/command.c
new file mode 100644
index 0000000000..e325a5d847
--- /dev/null
+++ b/common/command.c
@@ -0,0 +1,243 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#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.h"
+#include "bootloader.h"
+#include "command.h"
+
+#ifdef HOST_PJRC
+# include "usb_keyboard.h"
+# ifdef EXTRAKEY_ENABLE
+# include "usb_extra.h"
+# endif
+#endif
+
+#ifdef HOST_VUSB
+# include "usbdrv.h"
+#endif
+
+
+static uint8_t command_common(void);
+static void help(void);
+static void switch_layer(uint8_t layer);
+
+static bool last_print_enable;
+
+uint8_t command_proc(void)
+{
+ uint8_t processed = 0;
+ last_print_enable = print_enable;
+
+ if (!IS_COMMAND())
+ return 0;
+
+ print_enable = true;
+ if (command_extra() || command_common()) {
+ processed = 1;
+ _delay_ms(500);
+ }
+ print_enable = last_print_enable;
+ return processed;
+}
+
+/* This allows to define extra commands. return 0 when not processed. */
+uint8_t command_extra(void) __attribute__ ((weak));
+uint8_t command_extra(void)
+{
+ return 0;
+}
+
+
+static uint8_t command_common(void)
+{
+ switch (host_get_first_key()) {
+ case KB_H:
+ help();
+ break;
+ case KB_B:
+ host_clear_keyboard_report();
+ host_send_keyboard_report();
+ print("jump to bootloader... ");
+ _delay_ms(1000);
+ bootloader_jump(); // not return
+ print("not supported.\n");
+ 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 (last_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("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");
+#endif
+
+#ifdef HOST_VUSB
+# if USB_COUNT_SOF
+ print("usbSofCount: "); phex(usbSofCount); print("\n");
+# endif
+#endif
+ break;
+#ifdef NKRO_ENABLE
+ case KB_N:
+ // send empty report before change
+ host_clear_keyboard_report();
+ host_send_keyboard_report();
+ keyboard_nkro = !keyboard_nkro;
+ if (keyboard_nkro)
+ print("NKRO: enabled\n");
+ else
+ print("NKRO: disabled\n");
+ break;
+#endif
+#ifdef EXTRAKEY_ENABLE
+ case KB_ESC:
+ host_clear_keyboard_report();
+ host_send_keyboard_report();
+#ifdef HOST_PJRC
+ if (suspend && remote_wakeup) {
+ usb_remote_wakeup();
+ } else {
+ host_system_send(SYSTEM_POWER_DOWN);
+ host_system_send(0);
+ _delay_ms(500);
+ }
+#else
+ host_system_send(SYSTEM_POWER_DOWN);
+ host_system_send(0);
+ _delay_ms(500);
+#endif
+ 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:
+ return 0;
+ }
+ return 1;
+}
+
+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 NKRO_ENABLE
+ print("n: toggle 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");
+}
diff --git a/common/command.h b/common/command.h
new file mode 100644
index 0000000000..4888f5ee0b
--- /dev/null
+++ b/common/command.h
@@ -0,0 +1,25 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef COMMAND_H
+#define COMMAND
+
+uint8_t command_proc(void);
+/* This allows to extend commands. Return 0 when command is not processed. */
+uint8_t command_extra(void);
+
+#endif
diff --git a/common/controller_teensy.h b/common/controller_teensy.h
new file mode 100644
index 0000000000..6c3f47ce4e
--- /dev/null
+++ b/common/controller_teensy.h
@@ -0,0 +1,27 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef TEENSY_H
+#define TEENSY_H 1
+
+// for Teensy/Teensy++ 2.0
+#define DEBUG_LED 1
+#define DEBUG_LED_CONFIG (DDRD |= (1<<6))
+#define DEBUG_LED_ON (PORTD |= (1<<6))
+#define DEBUG_LED_OFF (PORTD &= ~(1<<6))
+
+#endif
diff --git a/common/debug.h b/common/debug.h
new file mode 100644
index 0000000000..230d3b3499
--- /dev/null
+++ b/common/debug.h
@@ -0,0 +1,36 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef DEBUG_H
+#define DEBUG_H 1
+
+#include "print.h"
+
+
+#define debug(s) if(debug_enable) print(s)
+#define debug_hex(c) if(debug_enable) phex(c)
+#define debug_hex16(i) if(debug_enable) phex16(i)
+#define debug_bin(c) if(debug_enable) pbin(c)
+#define debug_bin_reverse(c) if(debug_enable) pbin_reverse(c)
+
+
+bool debug_enable;
+bool debug_matrix;
+bool debug_keyboard;
+bool debug_mouse;
+
+#endif
diff --git a/common/host.c b/common/host.c
new file mode 100644
index 0000000000..cc26d55c22
--- /dev/null
+++ b/common/host.c
@@ -0,0 +1,237 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include "usb_keycodes.h"
+#include "host.h"
+#include "util.h"
+#include "debug.h"
+
+
+#ifdef NKRO_ENABLE
+bool keyboard_nkro = false;
+#endif
+
+static host_driver_t *driver;
+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 del_key_byte(uint8_t code);
+static inline void add_key_bit(uint8_t code);
+static inline void del_key_bit(uint8_t code);
+
+
+void host_set_driver(host_driver_t *d)
+{
+ driver = d;
+}
+
+host_driver_t *host_get_driver(void)
+{
+ return driver;
+}
+
+uint8_t host_keyboard_leds(void)
+{
+ if (!driver) return 0;
+ return (*driver->keyboard_leds)();
+}
+
+/* keyboard report operations */
+void host_add_key(uint8_t key)
+{
+#ifdef NKRO_ENABLE
+ if (keyboard_nkro) {
+ add_key_bit(key);
+ return;
+ }
+#endif
+ add_key_byte(key);
+}
+
+void host_del_key(uint8_t key)
+{
+#ifdef NKRO_ENABLE
+ if (keyboard_nkro) {
+ del_key_bit(key);
+ return;
+ }
+#endif
+ del_key_byte(key);
+}
+
+void host_add_mod_bit(uint8_t mod)
+{
+ keyboard_report->mods |= mod;
+}
+
+void host_del_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_del_code(uint8_t code)
+{
+ if (IS_MOD(code)) {
+ host_del_mod_bit(MOD_BIT(code));
+ } else {
+ host_del_key(code);
+ }
+}
+
+void host_swap_keyboard_report(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ report_keyboard_t *tmp = keyboard_report_prev;
+ keyboard_report_prev = keyboard_report;
+ keyboard_report = tmp;
+ SREG = sreg;
+}
+
+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_first_key(void)
+{
+#ifdef NKRO_ENABLE
+ if (keyboard_nkro) {
+ uint8_t i = 0;
+ for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++)
+ ;
+ return i<<3 | biton(keyboard_report->keys[i]);
+ }
+#endif
+ return keyboard_report->keys[0];
+}
+
+
+void host_send_keyboard_report(void)
+{
+ if (!driver) return;
+ (*driver->send_keyboard)(keyboard_report);
+}
+
+void host_mouse_send(report_mouse_t *report)
+{
+ if (!driver) return;
+ (*driver->send_mouse)(report);
+}
+
+void host_system_send(uint16_t data)
+{
+ if (!driver) return;
+ (*driver->send_system)(data);
+}
+
+void host_consumer_send(uint16_t data)
+{
+ // TODO: this is needed?
+ static uint16_t last_data = 0;
+ if (data == last_data) return;
+ last_data = data;
+
+ if (!driver) return;
+ (*driver->send_consumer)(data);
+}
+
+
+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 del_key_byte(uint8_t code)
+{
+ int i = 0;
+ for (; i < REPORT_KEYS; i++) {
+ if (keyboard_report->keys[i] == code) {
+ keyboard_report->keys[i] = 0;
+ break;
+ }
+ }
+}
+
+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");
+ }
+}
+
+static inline void del_key_bit(uint8_t code)
+{
+ if ((code>>3) < REPORT_KEYS) {
+ keyboard_report->keys[code>>3] &= ~(1<<(code&7));
+ } else {
+ debug("del_key_bit: can't del: "); phex(code); debug("\n");
+ }
+}
diff --git a/common/host.h b/common/host.h
new file mode 100644
index 0000000000..11b9aacd7c
--- /dev/null
+++ b/common/host.h
@@ -0,0 +1,57 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOST_H
+#define HOST_H
+
+#include <stdint.h>
+#include "report.h"
+#include "host_driver.h"
+
+
+#ifdef NKRO_ENABLE
+extern bool keyboard_nkro;
+#endif
+
+extern report_keyboard_t *keyboard_report;
+extern report_keyboard_t *keyboard_report_prev;
+
+
+void host_set_driver(host_driver_t *driver);
+host_driver_t *host_get_driver(void);
+uint8_t host_keyboard_leds(void);
+
+/* keyboard report operations */
+void host_add_key(uint8_t key);
+void host_del_key(uint8_t key);
+void host_add_mod_bit(uint8_t mod);
+void host_del_mod_bit(uint8_t mod);
+void host_set_mods(uint8_t mods);
+void host_add_code(uint8_t code);
+void host_del_code(uint8_t code);
+void host_swap_keyboard_report(void);
+void host_clear_keyboard_report(void);
+uint8_t host_has_anykey(void);
+uint8_t host_get_first_key(void);
+
+
+void host_send_keyboard_report(void);
+void host_mouse_send(report_mouse_t *report);
+void host_system_send(uint16_t data);
+void host_consumer_send(uint16_t data);
+
+#endif
diff --git a/common/host_driver.h b/common/host_driver.h
new file mode 100644
index 0000000000..edb9e5dd9c
--- /dev/null
+++ b/common/host_driver.h
@@ -0,0 +1,33 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOST_DRIVER_H
+#define HOST_DRIVER_H
+
+#include <stdint.h>
+#include "report.h"
+
+
+typedef struct {
+ uint8_t (*keyboard_leds)(void);
+ void (*send_keyboard)(report_keyboard_t *);
+ void (*send_mouse)(report_mouse_t *);
+ void (*send_system)(uint16_t);
+ void (*send_consumer)(uint16_t);
+} host_driver_t;
+
+#endif
diff --git a/common/keyboard.c b/common/keyboard.c
new file mode 100644
index 0000000000..5c2643c951
--- /dev/null
+++ b/common/keyboard.c
@@ -0,0 +1,203 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "keyboard.h"
+#include "host.h"
+#include "layer.h"
+#include "matrix.h"
+#include "led.h"
+#include "usb_keycodes.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "command.h"
+#ifdef MOUSEKEY_ENABLE
+#include "mousekey.h"
+#endif
+#ifdef EXTRAKEY_ENABLE
+#include <util/delay.h>
+#endif
+
+
+static uint8_t last_leds = 0;
+
+
+void keyboard_init(void)
+{
+ timer_init();
+ matrix_init();
+#ifdef PS2_MOUSE_ENABLE
+ ps2_mouse_init();
+#endif
+}
+
+void keyboard_proc(void)
+{
+ uint8_t fn_bits = 0;
+#ifdef EXTRAKEY_ENABLE
+ uint16_t consumer_code = 0;
+#endif
+
+ matrix_scan();
+
+ if (matrix_is_modified()) {
+ if (debug_matrix) matrix_print();
+#ifdef DEBUG_LED
+ // LED flash for debug
+ DEBUG_LED_CONFIG;
+ DEBUG_LED_ON;
+#endif
+ }
+
+ if (matrix_has_ghost()) {
+ // should send error?
+ debug("matrix has ghost!!\n");
+ return;
+ }
+
+ host_swap_keyboard_report();
+ host_clear_keyboard_report();
+ for (int row = 0; row < matrix_rows(); row++) {
+ for (int col = 0; col < matrix_cols(); col++) {
+ if (!matrix_is_on(row, col)) continue;
+
+ uint8_t code = layer_get_keycode(row, col);
+ if (code == KB_NO) {
+ // do nothing
+ } else if (IS_MOD(code)) {
+ host_add_mod_bit(MOD_BIT(code));
+ } else if (IS_FN(code)) {
+ fn_bits |= FN_BIT(code);
+ }
+// TODO: use table or something
+#ifdef EXTRAKEY_ENABLE
+ // System Control
+ else if (code == KB_SYSTEM_POWER) {
+#ifdef HOST_PJRC
+ if (suspend && remote_wakeup) {
+ usb_remote_wakeup();
+ } else {
+ host_system_send(SYSTEM_POWER_DOWN);
+ }
+#else
+ host_system_send(SYSTEM_POWER_DOWN);
+#endif
+ host_system_send(0);
+ _delay_ms(500);
+ } else if (code == KB_SYSTEM_SLEEP) {
+ host_system_send(SYSTEM_SLEEP);
+ host_system_send(0);
+ _delay_ms(500);
+ } else if (code == KB_SYSTEM_WAKE) {
+ host_system_send(SYSTEM_WAKE_UP);
+ host_system_send(0);
+ _delay_ms(500);
+ }
+ // Consumer Page
+ else if (code == KB_AUDIO_MUTE) {
+ consumer_code = AUDIO_MUTE;
+ } else if (code == KB_AUDIO_VOL_UP) {
+ consumer_code = AUDIO_VOL_UP;
+ } else if (code == KB_AUDIO_VOL_DOWN) {
+ consumer_code = AUDIO_VOL_DOWN;
+ }
+ else if (code == KB_MEDIA_NEXT_TRACK) {
+ consumer_code = TRANSPORT_NEXT_TRACK;
+ } else if (code == KB_MEDIA_PREV_TRACK) {
+ consumer_code = TRANSPORT_PREV_TRACK;
+ } else if (code == KB_MEDIA_STOP) {
+ consumer_code = TRANSPORT_STOP;
+ } else if (code == KB_MEDIA_PLAY_PAUSE) {
+ consumer_code = TRANSPORT_PLAY_PAUSE;
+ } else if (code == KB_MEDIA_SELECT) {
+ consumer_code = AL_CC_CONFIG;
+ }
+ else if (code == KB_MAIL) {
+ consumer_code = AL_EMAIL;
+ } else if (code == KB_CALCULATOR) {
+ consumer_code = AL_CALCULATOR;
+ } else if (code == KB_MY_COMPUTER) {
+ consumer_code = AL_LOCAL_BROWSER;
+ }
+ else if (code == KB_WWW_SEARCH) {
+ consumer_code = AC_SEARCH;
+ } else if (code == KB_WWW_HOME) {
+ consumer_code = AC_HOME;
+ } else if (code == KB_WWW_BACK) {
+ consumer_code = AC_BACK;
+ } else if (code == KB_WWW_FORWARD) {
+ consumer_code = AC_FORWARD;
+ } else if (code == KB_WWW_STOP) {
+ consumer_code = AC_STOP;
+ } else if (code == KB_WWW_REFRESH) {
+ consumer_code = AC_REFRESH;
+ } else if (code == KB_WWW_FAVORITES) {
+ consumer_code = AC_BOOKMARKS;
+ }
+#endif
+ else if (IS_KEY(code)) {
+ host_add_key(code);
+ }
+#ifdef MOUSEKEY_ENABLE
+ else if (IS_MOUSEKEY(code)) {
+ mousekey_decode(code);
+ }
+#endif
+ else {
+ debug("ignore keycode: "); debug_hex(code); debug("\n");
+ }
+ }
+ }
+
+ layer_switching(fn_bits);
+
+ if (command_proc()) {
+ return;
+ }
+
+ // TODO: should send only when changed from last report
+ if (matrix_is_modified()) {
+ host_send_keyboard_report();
+#ifdef EXTRAKEY_ENABLE
+ host_consumer_send(consumer_code);
+#endif
+#ifdef DEBUG_LED
+ // LED flash for debug
+ DEBUG_LED_CONFIG;
+ DEBUG_LED_OFF;
+#endif
+ }
+
+#ifdef MOUSEKEY_ENABLE
+ mousekey_send();
+#endif
+
+#ifdef PS2_MOUSE_ENABLE
+ // TODO: should comform new API
+ if (ps2_mouse_read() == 0)
+ ps2_mouse_usb_send();
+#endif
+
+ 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);
+}
diff --git a/common/keyboard.h b/common/keyboard.h
new file mode 100644
index 0000000000..988dac36ed
--- /dev/null
+++ b/common/keyboard.h
@@ -0,0 +1,28 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYBOARD_H
+#define KEYBOARD_H
+
+#include <stdint.h>
+
+
+void keyboard_init(void);
+void keyboard_proc(void);
+void keyboard_set_leds(uint8_t leds);
+
+#endif
diff --git a/common/keymap.h b/common/keymap.h
new file mode 100644
index 0000000000..7dfd6c2a1b
--- /dev/null
+++ b/common/keymap.h
@@ -0,0 +1,34 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYMAP_H
+#define KEYMAP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+/* keycode in specific layer */
+uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
+
+/* layer to move during press Fn key */
+uint8_t keymap_fn_layer(uint8_t fn_bits);
+
+/* keycode to send when release Fn key without using */
+uint8_t keymap_fn_keycode(uint8_t fn_bits);
+
+#endif
diff --git a/common/layer.c b/common/layer.c
new file mode 100644
index 0000000000..0854eede0d
--- /dev/null
+++ b/common/layer.c
@@ -0,0 +1,207 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "keymap.h"
+#include "host.h"
+#include "debug.h"
+#include "timer.h"
+#include "usb_keycodes.h"
+#include "layer.h"
+
+
+/*
+ * Parameters:
+ * SWITCH_DELAY |=======|
+ * SEND_FN_TERM |================|
+ *
+ * Fn key processing cases:
+ * 1. release Fn after SEND_FN_TERM.
+ * Layer sw ___________|~~~~~~~~~~~|___
+ * Fn press ___|~~~~~~~~~~~~~~~~~~~|___
+ * Fn send ___________________________
+ *
+ * 2. release Fn during SEND_FN_TERM.(not layer used)
+ * Layer sw ___________|~~~~~~|________
+ * Fn press ___|~~~~~~~~~~~~~~|________
+ * Fn key send __________________|~|______
+ * other key press ___________________________
+ * other key send ___________________________
+ *
+ * 3. release Fn during SEND_FN_TERM.(layer used)
+ * Layer sw ___________|~~~~~~|________
+ * Fn press ___|~~~~~~~~~~~~~~|________
+ * Fn key send ___________________________
+ * Fn send ___________________________
+ * other key press _____________|~~|__________
+ * other key send _____________|~~|__________
+ *
+ * 4. press other key during SWITCH_DELAY.
+ * Layer sw ___________________________
+ * Fn key press ___|~~~~~~~~~|_____________
+ * Fn key send ______|~~~~~~|_____________
+ * other key press ______|~~~|________________
+ * other key send _______|~~|________________
+ *
+ * 5. press Fn while press other key.
+ * Layer sw ___________________________
+ * Fn key press ___|~~~~~~~~~|_____________
+ * Fn key send ___|~~~~~~~~~|_____________
+ * other key press ~~~~~~~|___________________
+ * other key send ~~~~~~~|___________________
+ *
+ * 6. press Fn twice quickly and keep holding down.(repeat)
+ * Layer sw ___________________________
+ * Fn key press ___|~|____|~~~~~~~~~~~~~~~~
+ * Fn key send _____|~|__|~~~~~~~~~~~~~~~~
+ */
+
+// LAYER_SWITCH_DELAY: prevent from moving to new layer
+#ifndef LAYER_SWITCH_DELAY
+# define LAYER_SWITCH_DELAY 150
+#endif
+
+// LAYER_SEND_FN_TERM: send keycode if release key in this term
+#ifndef LAYER_SEND_FN_TERM
+# define LAYER_SEND_FN_TERM 500
+#endif
+
+
+uint8_t default_layer = 0;
+uint8_t current_layer = 0;
+
+static bool layer_used = false;
+static uint8_t new_layer(uint8_t fn_bits);
+
+
+uint8_t layer_get_keycode(uint8_t row, uint8_t col)
+{
+ uint8_t code = keymap_get_keycode(current_layer, row, col);
+ // normal key or mouse key
+ if ((IS_KEY(code) || IS_MOUSEKEY(code))) {
+ layer_used = true;
+ }
+ return code;
+}
+
+// bit substract b from a
+#define BIT_SUBST(a, b) (a&(a^b))
+void layer_switching(uint8_t fn_bits)
+{
+ // layer switching
+ static uint8_t last_fn = 0;
+ static uint8_t last_mods = 0;
+ static uint16_t last_timer = 0;
+ static uint8_t sent_fn = 0;
+
+ if (fn_bits == last_fn) { // Fn state is not changed
+ if (fn_bits == 0) {
+ // do nothing
+ } else {
+ if (!keymap_fn_keycode(BIT_SUBST(fn_bits, sent_fn)) ||
+ timer_elapsed(last_timer) > LAYER_SWITCH_DELAY) {
+ uint8_t _layer_to_switch = new_layer(BIT_SUBST(fn_bits, sent_fn));
+ if (current_layer != _layer_to_switch) { // not switch layer yet
+ debug("Fn case: 1,2,3(LAYER_SWITCH_DELAY passed)\n");
+ debug("Switch Layer: "); debug_hex(current_layer);
+ current_layer = _layer_to_switch;
+ layer_used = false;
+ debug(" -> "); debug_hex(current_layer); debug("\n");
+ }
+ } else {
+ if (host_has_anykey()) { // other keys is pressed
+ uint8_t _fn_to_send = BIT_SUBST(fn_bits, sent_fn);
+ if (_fn_to_send) {
+ debug("Fn case: 4(press other key during SWITCH_DELAY.)\n");
+ // send only Fn key first
+ uint8_t tmp_mods = keyboard_report->mods;
+ host_add_code(keymap_fn_keycode(_fn_to_send));
+ host_set_mods(last_mods);
+ host_send_keyboard_report();
+ host_set_mods(tmp_mods);
+ host_del_code(keymap_fn_keycode(_fn_to_send));
+ sent_fn |= _fn_to_send;
+ }
+ }
+ }
+ // add Fn keys to send
+ //host_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys
+ }
+ } else { // Fn state is changed(edge)
+ uint8_t fn_changed = 0;
+
+ debug("fn_bits: "); debug_bin(fn_bits); debug("\n");
+ debug("sent_fn: "); debug_bin(sent_fn); debug("\n");
+ debug("last_fn: "); debug_bin(last_fn); debug("\n");
+ debug("last_mods: "); debug_hex(last_mods); debug("\n");
+ debug("last_timer: "); debug_hex16(last_timer); debug("\n");
+ debug("timer_count: "); debug_hex16(timer_count); debug("\n");
+
+ // pressed Fn
+ if ((fn_changed = BIT_SUBST(fn_bits, last_fn))) {
+ debug("fn_changed: "); debug_bin(fn_changed); debug("\n");
+ if (host_has_anykey()) {
+ debug("Fn case: 5(pressed Fn with other key)\n");
+ sent_fn |= fn_changed;
+ } else if (fn_changed & sent_fn) { // pressed same Fn in a row
+ if (timer_elapsed(last_timer) > LAYER_SEND_FN_TERM) {
+ debug("Fn case: 6(not repeat)\n");
+ // time passed: not repeate
+ sent_fn &= ~fn_changed;
+ } else {
+ debug("Fn case: 6(repeat)\n");
+ }
+ }
+ }
+ // released Fn
+ if ((fn_changed = BIT_SUBST(last_fn, fn_bits))) {
+ debug("fn_changed: "); debug_bin(fn_changed); debug("\n");
+ if (timer_elapsed(last_timer) < LAYER_SEND_FN_TERM) {
+ if (!layer_used && BIT_SUBST(fn_changed, sent_fn)) {
+ debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n");
+ // send only Fn key first
+ uint8_t tmp_mods = keyboard_report->mods;
+ host_add_code(keymap_fn_keycode(fn_changed));
+ host_set_mods(last_mods);
+ host_send_keyboard_report();
+ host_set_mods(tmp_mods);
+ host_del_code(keymap_fn_keycode(fn_changed));
+ sent_fn |= fn_changed;
+ }
+ }
+ debug("Switch Layer(released Fn): "); debug_hex(current_layer);
+ current_layer = new_layer(BIT_SUBST(fn_bits, sent_fn));
+ debug(" -> "); debug_hex(current_layer); debug("\n");
+ }
+
+ layer_used = false;
+ last_fn = fn_bits;
+ last_mods = keyboard_report->mods;
+ last_timer = timer_read();
+ }
+ // send Fn keys
+ for (uint8_t i = 0; i < 8; i++) {
+ if ((sent_fn & fn_bits) & (1<<i)) {
+ host_add_code(keymap_fn_keycode(1<<i));
+ }
+ }
+}
+
+inline
+static uint8_t new_layer(uint8_t fn_bits)
+{
+ return (fn_bits ? keymap_fn_layer(fn_bits) : default_layer);
+}
diff --git a/common/layer.h b/common/layer.h
new file mode 100644
index 0000000000..d9e8cebb8f
--- /dev/null
+++ b/common/layer.h
@@ -0,0 +1,32 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef LAYER_H
+#define LAYER_H 1
+
+#include <stdint.h>
+
+extern uint8_t default_layer;
+extern uint8_t current_layer;
+
+/* return keycode for switch */
+uint8_t layer_get_keycode(uint8_t row, uint8_t col);
+
+/* process layer switching */
+void layer_switching(uint8_t fn_bits);
+
+#endif
diff --git a/common/led.h b/common/led.h
new file mode 100644
index 0000000000..402a247b9a
--- /dev/null
+++ b/common/led.h
@@ -0,0 +1,33 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef LED_H
+#define LED_H
+#include "stdint.h"
+
+
+/* keyboard LEDs */
+#define USB_LED_NUM_LOCK 0
+#define USB_LED_CAPS_LOCK 1
+#define USB_LED_SCROLL_LOCK 2
+#define USB_LED_COMPOSE 3
+#define USB_LED_KANA 4
+
+
+void led_set(uint8_t usb_led);
+
+#endif
diff --git a/common/matrix.h b/common/matrix.h
new file mode 100644
index 0000000000..c4b2cab518
--- /dev/null
+++ b/common/matrix.h
@@ -0,0 +1,49 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MATRIX_H
+#define MATRIX_H
+
+#include <stdbool.h>
+
+/* number of matrix rows */
+uint8_t matrix_rows(void);
+/* number of matrix columns */
+uint8_t matrix_cols(void);
+/* intialize matrix for scaning. should be called once. */
+void matrix_init(void);
+/* scan all key states on matrix */
+uint8_t matrix_scan(void);
+/* whether modified from previous scan. used after matrix_scan. */
+bool matrix_is_modified(void);
+/* whether ghosting occur on matrix. */
+bool matrix_has_ghost(void);
+/* whether a swtich is on */
+bool matrix_is_on(uint8_t row, uint8_t col);
+/* matrix state on row */
+#if (MATRIX_COLS <= 8)
+uint8_t matrix_get_row(uint8_t row);
+#else
+uint16_t matrix_get_row(uint8_t row);
+#endif
+/* count keys pressed */
+uint8_t matrix_key_count(void);
+/* print matrix for debug */
+void matrix_print(void);
+
+
+#endif
diff --git a/common/mousekey.c b/common/mousekey.c
new file mode 100755
index 0000000000..76bd0fd363
--- /dev/null
+++ b/common/mousekey.c
@@ -0,0 +1,132 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <util/delay.h>
+#include "usb_keycodes.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "mousekey.h"
+
+
+static report_mouse_t report;
+static report_mouse_t report_prev;
+
+static uint8_t mousekey_repeat = 0;
+
+static void mousekey_debug(void);
+
+
+/*
+ * TODO: fix acceleration algorithm
+ * see wikipedia http://en.wikipedia.org/wiki/Mouse_keys
+ */
+#ifndef MOUSEKEY_DELAY_TIME
+# define MOUSEKEY_DELAY_TIME 255
+#endif
+
+// acceleration parameters
+uint8_t mousekey_move_unit = 2;
+uint8_t mousekey_resolution = 5;
+
+
+static inline uint8_t move_unit(void)
+{
+ uint16_t unit = 5 + mousekey_repeat*2;
+ return (unit > 63 ? 63 : unit);
+}
+
+void mousekey_decode(uint8_t code)
+{
+ if (code == KB_MS_UP) report.y = -move_unit();
+ else if (code == KB_MS_DOWN) report.y = move_unit();
+ else if (code == KB_MS_LEFT) report.x = -move_unit();
+ else if (code == KB_MS_RIGHT) report.x = move_unit();
+ 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_BTN3) report.buttons |= MOUSE_BTN3;
+ 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_WH_UP) report.v += move_unit()/4;
+ else if (code == KB_MS_WH_DOWN) report.v -= move_unit()/4;
+ else if (code == KB_MS_WH_LEFT) report.h -= move_unit()/4;
+ else if (code == KB_MS_WH_RIGHT)report.h += move_unit()/4;
+}
+
+bool mousekey_changed(void)
+{
+ return (report.buttons != report_prev.buttons ||
+ report.x || report.y || report.v || report.h);
+}
+
+void mousekey_send(void)
+{
+ static uint16_t last_timer = 0;
+
+ if (!mousekey_changed()) {
+ mousekey_repeat = 0;
+ mousekey_clear_report();
+ return;
+ }
+
+ // send immediately when buttun state is changed
+ if (report.buttons == report_prev.buttons) {
+ if (timer_elapsed(last_timer) < 100) {
+ mousekey_clear_report();
+ return;
+ }
+ }
+
+ if (mousekey_repeat != 0xFF) {
+ mousekey_repeat++;
+ }
+
+ if (report.x && report.y) {
+ report.x *= 0.7;
+ report.y *= 0.7;
+ }
+
+ mousekey_debug();
+ host_mouse_send(&report);
+ report_prev = report;
+ last_timer = timer_read();
+ mousekey_clear_report();
+}
+
+void mousekey_clear_report(void)
+{
+ report.buttons = 0;
+ report.x = 0;
+ report.y = 0;
+ report.v = 0;
+ report.h = 0;
+}
+
+static void mousekey_debug(void)
+{
+ if (!debug_mouse) return;
+ print("mousekey[btn|x y v h]: ");
+ phex(report.buttons); print("|");
+ phex(report.x); print(" ");
+ phex(report.y); print(" ");
+ phex(report.v); print(" ");
+ phex(report.h);
+ phex(mousekey_repeat);
+ print("\n");
+}
diff --git a/common/mousekey.h b/common/mousekey.h
new file mode 100644
index 0000000000..c2c24e9fa5
--- /dev/null
+++ b/common/mousekey.h
@@ -0,0 +1,29 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MOUSEKEY_H
+#define MOUSEKEY_H
+
+#include <stdbool.h>
+#include "host.h"
+
+void mousekey_decode(uint8_t code);
+bool mousekey_changed(void);
+void mousekey_send(void);
+void mousekey_clear_report(void);
+
+#endif
diff --git a/common/print.c b/common/print.c
new file mode 100644
index 0000000000..558181ea72
--- /dev/null
+++ b/common/print.c
@@ -0,0 +1,93 @@
+/* Very basic print functions, intended to be used with usb_debug_only.c
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2008 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include "print.h"
+#include "sendchar.h"
+
+
+bool print_enable = false;
+
+void print_S(const char *s)
+{
+ if (!print_enable) return;
+ char c;
+
+ while (1) {
+ c = *s++;
+ if (!c) break;
+ if (c == '\n') sendchar('\r');
+ sendchar(c);
+ }
+}
+
+void print_P(const char *s)
+{
+ if (!print_enable) return;
+ char c;
+
+ while (1) {
+ c = pgm_read_byte(s++);
+ if (!c) break;
+ if (c == '\n') sendchar('\r');
+ sendchar(c);
+ }
+}
+
+void phex1(unsigned char c)
+{
+ if (!print_enable) return;
+ sendchar(c + ((c < 10) ? '0' : 'A' - 10));
+}
+
+void phex(unsigned char c)
+{
+ if (!print_enable) return;
+ phex1(c >> 4);
+ phex1(c & 15);
+}
+
+void phex16(unsigned int i)
+{
+ if (!print_enable) return;
+ phex(i >> 8);
+ phex(i);
+}
+
+
+void pbin(unsigned char c)
+{
+ if (!print_enable) return;
+ for (int i = 7; i >= 0; i--) {
+ sendchar((c & (1<<i)) ? '1' : '0');
+ }
+}
+
+void pbin_reverse(unsigned char c)
+{
+ if (!print_enable) return;
+ for (int i = 0; i < 8; i++) {
+ sendchar((c & (1<<i)) ? '1' : '0');
+ }
+}
diff --git a/common/print.h b/common/print.h
new file mode 100644
index 0000000000..686fa89acc
--- /dev/null
+++ b/common/print.h
@@ -0,0 +1,45 @@
+/* Very basic print functions, intended to be used with usb_debug_only.c
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2008 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PRINT_H__
+#define PRINT_H__ 1
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/pgmspace.h>
+
+
+extern bool print_enable;
+
+// this macro allows you to write print("some text") and
+// the string is automatically placed into flash memory :)
+#define print(s) print_P(PSTR(s))
+
+void print_S(const char *s);
+void print_P(const char *s);
+void phex(unsigned char c);
+void phex16(unsigned int i);
+void pbin(unsigned char c);
+void pbin_reverse(unsigned char c);
+
+#endif
diff --git a/common/report.h b/common/report.h
new file mode 100644
index 0000000000..b85b86c5f8
--- /dev/null
+++ b/common/report.h
@@ -0,0 +1,96 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef REPORT_H
+#define REPORT_H
+
+#include <stdint.h>
+
+
+/* report id */
+#define REPORT_ID_MOUSE 1
+#define REPORT_ID_SYSTEM 2
+#define REPORT_ID_CONSUMER 3
+
+/* mouse buttons */
+#define MOUSE_BTN1 (1<<0)
+#define MOUSE_BTN2 (1<<1)
+#define MOUSE_BTN3 (1<<2)
+#define MOUSE_BTN4 (1<<3)
+#define MOUSE_BTN5 (1<<4)
+
+// Consumer Page(0x0C)
+// following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
+#define AUDIO_MUTE 0x00E2
+#define AUDIO_VOL_UP 0x00E9
+#define AUDIO_VOL_DOWN 0x00EA
+#define TRANSPORT_NEXT_TRACK 0x00B5
+#define TRANSPORT_PREV_TRACK 0x00B6
+#define TRANSPORT_STOP 0x00B7
+#define TRANSPORT_PLAY_PAUSE 0x00CD
+#define AL_CC_CONFIG 0x0183
+#define AL_EMAIL 0x018A
+#define AL_CALCULATOR 0x0192
+#define AL_LOCAL_BROWSER 0x0194
+#define AC_SEARCH 0x0221
+#define AC_HOME 0x0223
+#define AC_BACK 0x0224
+#define AC_FORWARD 0x0225
+#define AC_STOP 0x0226
+#define AC_REFRESH 0x0227
+#define AC_BOOKMARKS 0x022A
+// supplement for Bluegiga iWRAP HID(not supported by Windows?)
+#define AL_LOCK 0x019E
+#define TRANSPORT_RECORD 0x00B2
+#define TRANSPORT_REWIND 0x00B4
+#define TRANSPORT_EJECT 0x00B8
+#define AC_MINIMIZE 0x0206
+
+// Generic Desktop Page(0x01)
+#define SYSTEM_POWER_DOWN 0x0081
+#define SYSTEM_SLEEP 0x0082
+#define SYSTEM_WAKE_UP 0x0083
+
+
+// key report size(NKRO or boot mode)
+#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
+#else
+# define REPORT_KEYS 6
+#endif
+
+typedef struct {
+ uint8_t mods;
+ uint8_t rserved;
+ uint8_t keys[REPORT_KEYS];
+} report_keyboard_t;
+
+typedef struct {
+ uint8_t report_id;
+ uint8_t buttons;
+ int8_t x;
+ int8_t y;
+ int8_t v;
+ int8_t h;
+} report_mouse_t;
+
+#endif
diff --git a/common/sendchar.h b/common/sendchar.h
new file mode 100644
index 0000000000..7c81303c7a
--- /dev/null
+++ b/common/sendchar.h
@@ -0,0 +1,27 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef SENDCHAR_H
+#define SENDCHAR_H
+
+#include <stdint.h>
+
+
+/* transmit a character. return 0 on success, -1 on error. */
+int8_t sendchar(uint8_t c);
+
+#endif
diff --git a/common/sendchar_null.c b/common/sendchar_null.c
new file mode 100644
index 0000000000..2933306228
--- /dev/null
+++ b/common/sendchar_null.c
@@ -0,0 +1,23 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "sendchar.h"
+
+
+int8_t sendchar(uint8_t c)
+{
+ return 0;
+}
diff --git a/common/sendchar_uart.c b/common/sendchar_uart.c
new file mode 100644
index 0000000000..0241859eb7
--- /dev/null
+++ b/common/sendchar_uart.c
@@ -0,0 +1,25 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "uart.h"
+#include "sendchar.h"
+
+
+int8_t sendchar(uint8_t c)
+{
+ uart_putchar(c);
+ return 0;
+}
diff --git a/common/timer.c b/common/timer.c
new file mode 100644
index 0000000000..48a38c9b68
--- /dev/null
+++ b/common/timer.c
@@ -0,0 +1,89 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+#include "timer.h"
+
+
+// counter resolution 1ms
+volatile uint16_t timer_count = 0;
+
+void timer_init(void)
+{
+ // Timer0 CTC mode
+ TCCR0A = 0x02;
+
+#if TIMER_PRESCALER == 1
+ TCCR0B = 0x01;
+#elif TIMER_PRESCALER == 8
+ TCCR0B = 0x02;
+#elif TIMER_PRESCALER == 64
+ TCCR0B = 0x03;
+#elif TIMER_PRESCALER == 256
+ TCCR0B = 0x04;
+#elif TIMER_PRESCALER == 1024
+ TCCR0B = 0x05;
+#else
+# error "Timer prescaler value is NOT vaild."
+#endif
+
+ OCR0A = TIMER_RAW_TOP;
+ TIMSK0 = (1<<OCIE0A);
+}
+
+inline
+void timer_clear(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ timer_count = 0;
+ SREG = sreg;
+}
+
+inline
+uint16_t timer_read(void)
+{
+ uint16_t t;
+
+ uint8_t sreg = SREG;
+ cli();
+ t = timer_count;
+ SREG = sreg;
+
+ return t;
+}
+
+inline
+uint16_t timer_elapsed(uint16_t last)
+{
+ uint16_t t;
+
+ uint8_t sreg = SREG;
+ cli();
+ t = timer_count;
+ SREG = sreg;
+
+ return TIMER_DIFF_MS(t, last);
+}
+
+// excecuted once per 1ms.(excess for just timer count?)
+ISR(TIMER0_COMPA_vect)
+{
+ timer_count++;
+}
diff --git a/common/timer.h b/common/timer.h
new file mode 100644
index 0000000000..f9e8181e6f
--- /dev/null
+++ b/common/timer.h
@@ -0,0 +1,53 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef TIMER_H
+#define TIMER_H 1
+
+#include <stdint.h>
+
+#ifndef TIMER_PRESCALER
+# if F_CPU > 16000000
+# define TIMER_PRESCALER 256
+# elif F_CPU >= 4000000
+# define TIMER_PRESCALER 64
+# else
+# define TIMER_PRESCALER 8
+# endif
+#endif
+#define TIMER_RAW_FREQ (F_CPU/TIMER_PRESCALER)
+#define TIMER_RAW TCNT0
+#define TIMER_RAW_TOP (TIMER_RAW_FREQ/1000)
+
+#if (TIMER_RAW_TOP > 255)
+# error "Timer0 can't count 1ms at this clock freq. Use larger prescaler."
+#endif
+
+#define TIMER_DIFF(a, b, max) ((a) >= (b) ? (a) - (b) : (max) - (b) + (a))
+#define TIMER_DIFF_RAW(a, b) TIMER_DIFF(a, b, UINT8_MAX)
+#define TIMER_DIFF_MS(a, b) TIMER_DIFF(a, b, UINT16_MAX)
+
+
+extern volatile uint16_t timer_count;
+
+
+void timer_init(void);
+void timer_clear(void);
+uint16_t timer_read(void);
+uint16_t timer_elapsed(uint16_t last);
+
+#endif
diff --git a/common/uart.c b/common/uart.c
new file mode 100644
index 0000000000..c17649b082
--- /dev/null
+++ b/common/uart.c
@@ -0,0 +1,129 @@
+// TODO: Teensy support(ATMega32u4/AT90USB128)
+// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
+/* UART Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// Version 1.0: Initial Release
+// Version 1.1: Add support for Teensy 2.0, minor optimizations
+
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#include "uart.h"
+
+// These buffers may be any size from 2 to 256 bytes.
+#define RX_BUFFER_SIZE 64
+#define TX_BUFFER_SIZE 40
+
+static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
+static volatile uint8_t tx_buffer_head;
+static volatile uint8_t tx_buffer_tail;
+static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
+static volatile uint8_t rx_buffer_head;
+static volatile uint8_t rx_buffer_tail;
+
+// Initialize the UART
+void uart_init(uint32_t baud)
+{
+ cli();
+ UBRR0 = (F_CPU / 4 / baud - 1) / 2;
+ UCSR0A = (1<<U2X0);
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
+ UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
+ tx_buffer_head = tx_buffer_tail = 0;
+ rx_buffer_head = rx_buffer_tail = 0;
+ sei();
+}
+
+// Transmit a byte
+void uart_putchar(uint8_t c)
+{
+ uint8_t i;
+
+ i = tx_buffer_head + 1;
+ if (i >= TX_BUFFER_SIZE) i = 0;
+ while (tx_buffer_tail == i) ; // wait until space in buffer
+ //cli();
+ tx_buffer[i] = c;
+ tx_buffer_head = i;
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0);
+ //sei();
+}
+
+// Receive a byte
+uint8_t uart_getchar(void)
+{
+ uint8_t c, i;
+
+ while (rx_buffer_head == rx_buffer_tail) ; // wait for character
+ i = rx_buffer_tail + 1;
+ if (i >= RX_BUFFER_SIZE) i = 0;
+ c = rx_buffer[i];
+ rx_buffer_tail = i;
+ return c;
+}
+
+// Return the number of bytes waiting in the receive buffer.
+// Call this before uart_getchar() to check if it will need
+// to wait for a byte to arrive.
+uint8_t uart_available(void)
+{
+ uint8_t head, tail;
+
+ head = rx_buffer_head;
+ tail = rx_buffer_tail;
+ if (head >= tail) return head - tail;
+ return RX_BUFFER_SIZE + head - tail;
+}
+
+// Transmit Interrupt
+ISR(USART_UDRE_vect)
+{
+ uint8_t i;
+
+ if (tx_buffer_head == tx_buffer_tail) {
+ // buffer is empty, disable transmit interrupt
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
+ } else {
+ i = tx_buffer_tail + 1;
+ if (i >= TX_BUFFER_SIZE) i = 0;
+ UDR0 = tx_buffer[i];
+ tx_buffer_tail = i;
+ }
+}
+
+// Receive Interrupt
+ISR(USART_RX_vect)
+{
+ uint8_t c, i;
+
+ c = UDR0;
+ i = rx_buffer_head + 1;
+ if (i >= RX_BUFFER_SIZE) i = 0;
+ if (i != rx_buffer_tail) {
+ rx_buffer[i] = c;
+ rx_buffer_head = i;
+ }
+}
+
diff --git a/common/uart.h b/common/uart.h
new file mode 100644
index 0000000000..41136a396f
--- /dev/null
+++ b/common/uart.h
@@ -0,0 +1,11 @@
+#ifndef _uart_included_h_
+#define _uart_included_h_
+
+#include <stdint.h>
+
+void uart_init(uint32_t baud);
+void uart_putchar(uint8_t c);
+uint8_t uart_getchar(void);
+uint8_t uart_available(void);
+
+#endif
diff --git a/common/usb_keycodes.h b/common/usb_keycodes.h
new file mode 100644
index 0000000000..9b6cce1532
--- /dev/null
+++ b/common/usb_keycodes.h
@@ -0,0 +1,423 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Key codes: HID Keyboard/Keypad Page(0x07)
+ * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
+ */
+#ifndef USB_KEYCODES_H
+#define USB_KEYCODES_H
+
+
+#define IS_ERROR(code) (KB_ROLL_OVER <= (code) && (code) <= KB_UNDEFINED)
+#define IS_KEY(code) (KB_A <= (code) && (code) <= KB_EXSEL)
+#define IS_MOD(code) (KB_LCTRL <= (code) && (code) <= KB_RGUI)
+#define IS_FN(code) (KB_FN0 <= (code) && (code) <= KB_FN7)
+#define IS_MOUSEKEY(code) (KB_MS_UP <= (code) && (code) <= KB_MS_WH_RIGHT)
+#define IS_MOUSEKEY_MOVE(code) (KB_MS_UP <= (code) && (code) <= KB_MS_RIGHT)
+#define IS_MOUSEKEY_BUTTON(code) (KB_MS_BTN1 <= (code) && (code) <= KB_MS_BTN5)
+#define IS_MOUSEKEY_WHEEL(code) (KB_MS_WH_UP <= (code) && (code) <= KB_MS_WH_RIGHT)
+
+#define MOD_BIT(code) (1<<((code) & 0x07))
+#define FN_BIT(code) (1<<((code) - KB_FN0))
+
+
+/* Short names */
+#define KB_LCTL KB_LCTRL
+#define KB_RCTL KB_RCTRL
+#define KB_LSFT KB_LSHIFT
+#define KB_RSFT KB_RSHIFT
+#define KB_ESC KB_ESCAPE
+#define KB_BSPC KB_BSPACE
+#define KB_ENT KB_ENTER
+#define KB_DEL KB_DELETE
+#define KB_INS KB_INSERT
+#define KB_CAPS KB_CAPSLOCK
+#define KB_RGHT KB_RIGHT
+#define KB_PGDN KB_PGDOWN
+#define KB_PSCR KB_PSCREEN
+#define KB_SLCK KB_SCKLOCK
+#define KB_PAUS KB_PAUSE
+#define KB_BRK KB_PAUSE
+#define KB_NLCK KB_NUMLOCK
+#define KB_SPC KB_SPACE
+#define KB_MINS KB_MINUS
+#define KB_EQL KB_EQUAL
+#define KB_GRV KB_GRAVE
+#define KB_RBRC KB_RBRACKET
+#define KB_LBRC KB_LBRACKET
+#define KB_COMM KB_COMMA
+#define KB_BSLS KB_BSLASH
+#define KB_SLSH KB_SLASH
+#define KB_SCLN KB_SCOLON
+#define KB_QUOT KB_QUOTE
+#define KB_APP KB_APPLICATION
+#define KB_NUHS KB_NONUS_HASH
+#define KB_NUBS KB_NONUS_BSLASH
+#define KB_ERAS KB_ALT_ERASE,
+#define KB_CLR KB_CLEAR
+/* for Japanese */
+#define KB_ZKHK KB_GRAVE
+#define KB_RO KB_INT1
+#define KB_KANA KB_INT2
+#define KB_JYEN KB_INT3
+#define KB_HENK KB_INT4
+#define KB_MHEN KB_INT5
+/* Keypad */
+#define KB_P1 KB_KP_1
+#define KB_P2 KB_KP_2
+#define KB_P3 KB_KP_3
+#define KB_P4 KB_KP_4
+#define KB_P5 KB_KP_5
+#define KB_P6 KB_KP_6
+#define KB_P7 KB_KP_7
+#define KB_P8 KB_KP_8
+#define KB_P9 KB_KP_9
+#define KB_P0 KB_KP_0
+#define KB_PDOT KB_KP_DOT
+#define KB_PCMM KB_KP_COMMA
+#define KB_PSLS KB_KP_SLASH
+#define KB_PAST KB_KP_ASTERISK
+#define KB_PMNS KB_KP_MINUS
+#define KB_PPLS KB_KP_PLUS
+#define KB_PEQL KB_KP_EQUAL
+#define KB_PENT KB_KP_ENTER
+/* Mousekey */
+#define KB_MS_U KB_MS_UP
+#define KB_MS_D KB_MS_DOWN
+#define KB_MS_L KB_MS_LEFT
+#define KB_MS_R KB_MS_RIGHT
+#define KB_BTN1 KB_MS_BTN1
+#define KB_BTN2 KB_MS_BTN2
+#define KB_BTN3 KB_MS_BTN3
+#define KB_BTN4 KB_MS_BTN4
+#define KB_BTN5 KB_MS_BTN5
+#define KB_WH_U KB_MS_WH_UP
+#define KB_WH_D KB_MS_WH_DOWN
+#define KB_WH_L KB_MS_WH_LEFT
+#define KB_WH_R KB_MS_WH_RIGHT
+/* Sytem Control & Consumer usage */
+#define KB_PWR KB_SYSTEM_POWER
+#define KB_SLEP KB_SYSTEM_SLEEP
+#define KB_WAKE KB_SYSTEM_WAKE
+#define KB_MUTE KB_AUDIO_MUTE
+#define KB_VOLU KB_AUDIO_VOL_UP
+#define KB_VOLD KB_AUDIO_VOL_DOWN
+#define KB_MNXT KB_MEDIA_NEXT_TRACK
+#define KB_MPRV KB_MEDIA_PREV_TRACK
+#define KB_MSTP KB_MEDIA_STOP
+#define KB_MPLY KB_MEDIA_PLAY_PAUSE
+#define KB_MSEL KB_MEDIA_SELECT
+#define KB_MAIL KB_MAIL
+#define KB_CALC KB_CALCULATOR
+#define KB_MYCM KB_MY_COMPUTER
+#define KB_WSCH KB_WWW_SEARCH
+#define KB_WHOM KB_WWW_HOME
+#define KB_WBAK KB_WWW_BACK
+#define KB_WFWD KB_WWW_FORWARD
+#define KB_WSTP KB_WWW_STOP
+#define KB_WREF KB_WWW_REFRESH
+#define KB_WFAV KB_WWW_FAVORITES
+
+
+/* Special keycode */
+enum special_keycodes {
+ /* System Control */
+ KB_SYSTEM_POWER = 0xB0,
+ KB_SYSTEM_SLEEP,
+ KB_SYSTEM_WAKE,
+
+ /* Consumer Page */
+ KB_AUDIO_MUTE,
+ KB_AUDIO_VOL_UP,
+ KB_AUDIO_VOL_DOWN,
+ KB_MEDIA_NEXT_TRACK,
+ KB_MEDIA_PREV_TRACK,
+ KB_MEDIA_STOP,
+ KB_MEDIA_PLAY_PAUSE,
+ KB_MEDIA_SELECT,
+ KB_MAIL,
+ KB_CALCULATOR,
+ KB_MY_COMPUTER,
+ KB_WWW_SEARCH,
+ KB_WWW_HOME,
+ KB_WWW_BACK, /* 0xC0 */
+ KB_WWW_FORWARD,
+ KB_WWW_STOP,
+ KB_WWW_REFRESH,
+ KB_WWW_FAVORITES,
+
+ /* reserve 0xE0-E7 for Modifiers */
+
+ /* Layer Switching */
+ KB_FN0 = 0xE8,
+ KB_FN1,
+ KB_FN2,
+ KB_FN3,
+ KB_FN4,
+ KB_FN5,
+ KB_FN6,
+ KB_FN7,
+
+ /* Mousekey */
+ KB_MS_UP = 0xF0,
+ KB_MS_DOWN,
+ KB_MS_LEFT,
+ KB_MS_RIGHT,
+ KB_MS_BTN1,
+ KB_MS_BTN2,
+ KB_MS_BTN3,
+ KB_MS_BTN4,
+ KB_MS_BTN5,
+ /* Mousekey wheel */
+ KB_MS_WH_UP,
+ KB_MS_WH_DOWN,
+ KB_MS_WH_LEFT,
+ KB_MS_WH_RIGHT,
+};
+
+enum keycodes {
+ KB_NO = 0,
+ KB_ROLL_OVER,
+ KB_POST_FAIL,
+ KB_UNDEFINED,
+ KB_A,
+ KB_B,
+ KB_C,
+ KB_D,
+ KB_E,
+ KB_F,
+ KB_G,
+ KB_H,
+ KB_I,
+ KB_J,
+ KB_K,
+ KB_L,
+ KB_M, /* 0x10 */
+ KB_N,
+ KB_O,
+ KB_P,
+ KB_Q,
+ KB_R,
+ KB_S,
+ KB_T,
+ KB_U,
+ KB_V,
+ KB_W,
+ KB_X,
+ KB_Y,
+ KB_Z,
+ KB_1,
+ KB_2,
+ KB_3, /* 0x20 */
+ KB_4,
+ KB_5,
+ KB_6,
+ KB_7,
+ KB_8,
+ KB_9,
+ KB_0,
+ KB_ENTER,
+ KB_ESCAPE,
+ KB_BSPACE,
+ KB_TAB,
+ KB_SPACE,
+ KB_MINUS,
+ KB_EQUAL,
+ KB_LBRACKET,
+ KB_RBRACKET, /* 0x30 */
+ KB_BSLASH, /* \ (and |) */
+ KB_NONUS_HASH, /* Non-US # and ~ */
+ KB_SCOLON, /* ; (and :) */
+ KB_QUOTE, /* ' and " */
+ KB_GRAVE, /* Grave accent and tilde */
+ KB_COMMA, /* , and < */
+ KB_DOT, /* . and > */
+ KB_SLASH, /* / and ? */
+ KB_CAPSLOCK,
+ KB_F1,
+ KB_F2,
+ KB_F3,
+ KB_F4,
+ KB_F5,
+ KB_F6,
+ KB_F7, /* 0x40 */
+ KB_F8,
+ KB_F9,
+ KB_F10,
+ KB_F11,
+ KB_F12,
+ KB_PSCREEN,
+ KB_SCKLOCK,
+ KB_PAUSE,
+ KB_INSERT,
+ KB_HOME,
+ KB_PGUP,
+ KB_DELETE,
+ KB_END,
+ KB_PGDOWN,
+ KB_RIGHT,
+ KB_LEFT, /* 0x50 */
+ KB_DOWN,
+ KB_UP,
+ KB_NUMLOCK,
+ KB_KP_SLASH,
+ KB_KP_ASTERISK,
+ KB_KP_MINUS,
+ KB_KP_PLUS,
+ KB_KP_ENTER,
+ KB_KP_1,
+ KB_KP_2,
+ KB_KP_3,
+ KB_KP_4,
+ KB_KP_5,
+ KB_KP_6,
+ KB_KP_7,
+ KB_KP_8, /* 0x60 */
+ KB_KP_9,
+ KB_KP_0,
+ KB_KP_DOT,
+ KB_NONUS_BSLASH, /* Non-US \ and | */
+ KB_APPLICATION,
+ KB_POWER,
+ KB_KP_EQUAL,
+ KB_F13,
+ KB_F14,
+ KB_F15,
+ KB_F16,
+ KB_F17,
+ KB_F18,
+ KB_F19,
+ KB_F20,
+ KB_F21, /* 0x70 */
+ KB_F22,
+ KB_F23,
+ KB_F24,
+ KB_EXECUTE,
+ KB_HELP,
+ KB_MENU,
+ KB_SELECT,
+ KB_STOP,
+ KB_AGAIN,
+ KB_UNDO,
+ KB_CUT,
+ KB_COPY,
+ KB_PASTE,
+ KB_FIND,
+ KB__MUTE,
+ KB__VOLUP, /* 0x80 */
+ KB__VOLDOWN,
+ KB_LOCKING_CAPS, /* locking Caps Lock */
+ KB_LOCKING_NUM, /* locking Num Lock */
+ KB_LOCKING_SCROLL, /* locking Scroll Lock */
+ KB_KP_COMMA,
+ KB_KP_EQUAL_AS400, /* equal sign on AS/400 */
+ KB_INT1,
+ KB_INT2,
+ KB_INT3,
+ KB_INT4,
+ KB_INT5,
+ KB_INT6,
+ KB_INT7,
+ KB_INT8,
+ KB_INT9,
+ KB_LANG1, /* 0x90 */
+ KB_LANG2,
+ KB_LANG3,
+ KB_LANG4,
+ KB_LANG5,
+ KB_LANG6,
+ KB_LANG7,
+ KB_LANG8,
+ KB_LANG9,
+ KB_ALT_ERASE,
+ KB_SYSREQ,
+ KB_CANCEL,
+ KB_CLEAR,
+ KB_PRIOR,
+ KB_RETURN,
+ KB_SEPARATOR,
+ KB_OUT, /* 0xA0 */
+ KB_OPER,
+ KB_CLEAR_AGAIN,
+ KB_CRSEL,
+ KB_EXSEL,
+
+ /* NOTE: 0xB0-DF are used as special_keycodes */
+#if 0
+ KB_KP_00 = 0xB0,
+ KB_KP_000,
+ KB_THOUSANDS_SEPARATOR,
+ KB_DECIMAL_SEPARATOR,
+ KB_CURRENCY_UNIT,
+ KB_CURRENCY_SUB_UNIT,
+ KB_KP_LPAREN,
+ KB_KP_RPAREN,
+ KB_KP_LCBRACKET, /* { */
+ KB_KP_RCBRACKET, /* } */
+ KB_KP_TAB,
+ KB_KP_BSPACE,
+ KB_KP_A,
+ KB_KP_B,
+ KB_KP_C,
+ KB_KP_D,
+ KB_KP_E, /* 0xC0 */
+ KB_KP_F,
+ KB_KP_XOR,
+ KB_KP_HAT,
+ KB_KP_PERC,
+ KB_KP_LT,
+ KB_KP_GT,
+ KB_KP_AND,
+ KB_KP_LAZYAND,
+ KB_KP_OR,
+ KB_KP_LAZYOR,
+ KB_KP_COLON,
+ KB_KP_HASH,
+ KB_KP_SPACE,
+ KB_KP_ATMARK,
+ KB_KP_EXCLAMATION,
+ KB_KP_MEM_STORE, /* 0xD0 */
+ KB_KP_MEM_RECALL,
+ KB_KP_MEM_CLEAR,
+ KB_KP_MEM_ADD,
+ KB_KP_MEM_SUB,
+ KB_KP_MEM_MUL,
+ KB_KP_MEM_DIV,
+ KB_KP_PLUS_MINUS,
+ KB_KP_CLEAR,
+ KB_KP_CLEAR_ENTRY,
+ KB_KP_BINARY,
+ KB_KP_OCTAL,
+ KB_KP_DECIMAL,
+ KB_KP_HEXADECIMAL,
+#endif
+
+ /* Modifiers */
+ KB_LCTRL = 0xE0,
+ KB_LSHIFT,
+ KB_LALT,
+ KB_LGUI,
+ KB_RCTRL,
+ KB_RSHIFT,
+ KB_RALT,
+ KB_RGUI,
+
+ /* NOTE: 0xE8-FF are used as special_keycodes */
+};
+
+#endif /* USB_KEYCODES_H */
diff --git a/common/util.c b/common/util.c
new file mode 100644
index 0000000000..36afdd4470
--- /dev/null
+++ b/common/util.c
@@ -0,0 +1,37 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util.h"
+
+// bit population
+int bitpop(uint8_t bits)
+{
+ int c;
+ for (c = 0; bits; c++)
+ bits &= bits -1;
+ return c;
+}
+
+// most significant on-bit
+int biton(uint8_t bits)
+{
+ int n = 0;
+ if (bits >> 4) { bits >>= 4; n += 4;}
+ if (bits >> 2) { bits >>= 2; n += 2;}
+ if (bits >> 1) { bits >>= 1; n += 1;}
+ return n;
+}
diff --git a/common/util.h b/common/util.h
new file mode 100644
index 0000000000..66bccbfa58
--- /dev/null
+++ b/common/util.h
@@ -0,0 +1,34 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UTIL_H
+#define UTIL_H 1
+
+#include <stdint.h>
+
+// convert to L string
+#define LSTR(s) XLSTR(s)
+#define XLSTR(s) L ## #s
+// convert to string
+#define STR(s) XSTR(s)
+#define XSTR(s) #s
+
+
+int bitpop(uint8_t bits);
+int biton(uint8_t bits);
+
+#endif