summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2012-06-07 02:25:15 +0900
committertmk <nobody@nowhere>2012-06-07 02:47:33 +0900
commitf4125707399d11a7d80587659c464b9bcddb8c56 (patch)
tree1d2a02e30f8cd103e8f4dc36629c09f6a3d44fef /common
parent225de7a847a511d004bf909b1334e19497cf2f9d (diff)
Moved files to common, protocol and doc directory
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 (comm