diff --git a/converter/ps2_usb/matrix.c b/converter/ps2_usb/matrix.c
index 4187ea060..a4c27f5d5 100644
--- a/converter/ps2_usb/matrix.c
+++ b/converter/ps2_usb/matrix.c
@@ -19,6 +19,7 @@ along with this program. If not, see .
#include
#include
#include
+#include "action.h"
#include "print.h"
#include "util.h"
#include "debug.h"
@@ -185,8 +186,8 @@ uint8_t matrix_scan(void)
matrix_break(PAUSE);
}
- uint8_t code;
- while ((code = ps2_host_recv())) {
+ uint8_t code = ps2_host_recv();
+ if (!ps2_error) {
switch (state) {
case INIT:
switch (code) {
@@ -207,11 +208,17 @@ uint8_t matrix_scan(void)
matrix_make(PRINT_SCREEN);
state = INIT;
break;
+ case 0x00: // Overrun [3]p.25
+ print("Overrun\n");
+ clear_keyboard();
+ state = INIT;
+ break;
default: // normal key make
if (code < 0x80) {
matrix_make(code);
} else {
- debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n");
+ printf("unexpected scan code at INIT: %02X\n", code);
+ clear_keyboard();
}
state = INIT;
}
@@ -232,7 +239,8 @@ uint8_t matrix_scan(void)
if (code < 0x80) {
matrix_make(code|0x80);
} else {
- debug("unexpected scan code at E0: "); debug_hex(code); debug("\n");
+ printf("unexpected scan code at E0: %02X\n", code);
+ clear_keyboard();
}
state = INIT;
}
@@ -251,7 +259,8 @@ uint8_t matrix_scan(void)
if (code < 0x80) {
matrix_break(code);
} else {
- debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
+ printf("unexpected scan code at F0: %02X\n", code);
+ clear_keyboard();
}
state = INIT;
}
@@ -266,7 +275,8 @@ uint8_t matrix_scan(void)
if (code < 0x80) {
matrix_break(code|0x80);
} else {
- debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n");
+ printf("unexpected scan code at E0_F0: %02X\n", code);
+ clear_keyboard();
}
state = INIT;
}
@@ -357,7 +367,11 @@ uint8_t matrix_scan(void)
default:
state = INIT;
}
- phex(code);
+ }
+
+ if (ps2_error > PS2_ERR_STARTBIT3) {
+ uint8_t ret = ps2_host_send(PS2_RESEND);
+ printf("Resend: %02X\n", ret);
}
return 1;
}
diff --git a/protocol.mk b/protocol.mk
index 0d5f06c7e..e33200873 100644
--- a/protocol.mk
+++ b/protocol.mk
@@ -8,7 +8,7 @@ ifdef PS2_MOUSE_ENABLE
endif
ifdef PS2_USE_BUSYWAIT
- SRC += protocol/ps2.c
+ SRC += protocol/ps2_busywait.c
OPT_DEFS += -DPS2_USE_BUSYWAIT
endif
diff --git a/protocol/ps2.c b/protocol/ps2.c
index e5873a9bf..4886b16d0 100644
--- a/protocol/ps2.c
+++ b/protocol/ps2.c
@@ -91,6 +91,9 @@ uint8_t ps2_error = PS2_ERR_NONE;
void ps2_host_init(void)
{
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ _delay_ms(2500);
+
#ifdef PS2_USE_INT
PS2_INT_INIT();
PS2_INT_ON();
@@ -163,23 +166,11 @@ ERROR:
/* receive data when host want else inhibit communication */
uint8_t ps2_host_recv_response(void)
{
+ // Command might take 20ms to response([3]p.21)
+ // TrackPoint might take 25ms ([5]2.7)
uint8_t data = 0;
-
-#ifdef PS2_USE_INT
- PS2_INT_OFF();
-#endif
- /* terminate a transmission if we have */
- inhibit();
- _delay_us(100);
-
- /* release lines(idle state) */
- idle();
-
- /* wait start bit */
- wait_clock_lo(25000); // command response may take 20 ms at most
- data = recv_data();
-
- inhibit();
+ uint8_t try = 200;
+ while (try-- && (data = ps2_host_recv())) ;
return data;
}
#endif
@@ -187,7 +178,17 @@ uint8_t ps2_host_recv_response(void)
#ifndef PS2_USE_INT
uint8_t ps2_host_recv(void)
{
- return ps2_host_recv_response();
+ uint8_t data = 0;
+
+ /* release lines(idle state) */
+ idle();
+
+ /* wait start bit */
+ wait_clock_lo(100); // TODO: this is enough?
+ data = recv_data();
+
+ inhibit();
+ return data;
}
#else
/* ring buffer to store ps/2 key data */
@@ -241,13 +242,6 @@ static inline void pbuf_clear(void)
/* get data received by interrupt */
uint8_t ps2_host_recv(void)
{
- if (ps2_error) {
- print("x");
- phex(ps2_error);
- ps2_host_send(0xFE); // request to resend
- ps2_error = PS2_ERR_NONE;
- }
- idle();
return pbuf_dequeue();
}
@@ -450,3 +444,26 @@ static inline void inhibit(void)
clock_lo();
data_hi();
}
+
+
+/* PS/2 Resources
+ *
+ * [1] The PS/2 Mouse/Keyboard Protocol
+ * http://www.computer-engineering.org/ps2protocol/
+ * Concise and thorough primer of PS/2 protocol.
+ *
+ * [2] Keyboard and Auxiliary Device Controller
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Signal Timing and Format
+ *
+ * [3] Keyboards(101- and 102-key)
+ * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
+ * Keyboard Layout, Scan Code Set, POR, and Commands.
+ *
+ * [4] PS/2 Reference Manuals
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Collection of IBM Personal System/2 documents.
+ *
+ * [5] TrackPoint Engineering Specifications for version 3E
+ * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
+ */
diff --git a/protocol/ps2.h b/protocol/ps2.h
index 834165356..b780d01a2 100644
--- a/protocol/ps2.h
+++ b/protocol/ps2.h
@@ -1,5 +1,5 @@
/*
-Copyright 2010,2011 Jun WAKO
+Copyright 2010,2011,2012,2013 Jun WAKO
This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -37,12 +37,60 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef PS2_H
#define PS2_H
+
+#include
+#include
+#include
+
/*
* Primitive PS/2 Library for AVR
+ *
+ * PS/2 Resources
+ * --------------
+ * [1] The PS/2 Mouse/Keyboard Protocol
+ * http://www.computer-engineering.org/ps2protocol/
+ * Concise and thorough primer of PS/2 protocol.
+ *
+ * [2] Keyboard and Auxiliary Device Controller
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Signal Timing and Format
+ *
+ * [3] Keyboards(101- and 102-key)
+ * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
+ * Keyboard Layout, Scan Code Set, POR, and Commands.
+ *
+ * [4] PS/2 Reference Manuals
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Collection of IBM Personal System/2 documents.
+ *
+ * [5] TrackPoint Engineering Specifications for version 3E
+ * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
*/
+#define PS2_ACK 0xFA
+#define PS2_RESEND 0xFE
+#define PS2_SET_LED 0xED
+
+#define PS2_ERR_NONE 0
+#define PS2_ERR_STARTBIT1 1
+#define PS2_ERR_STARTBIT2 2
+#define PS2_ERR_STARTBIT3 3
+#define PS2_ERR_PARITY 0x10
+
+#define PS2_LED_SCROLL_LOCK 0
+#define PS2_LED_NUM_LOCK 1
+#define PS2_LED_CAPS_LOCK 2
-/* port settings for clock and data line */
+extern uint8_t ps2_error;
+
+void ps2_host_init(void);
+uint8_t ps2_host_send(uint8_t data);
+uint8_t ps2_host_recv_response(void);
+uint8_t ps2_host_recv(void);
+void ps2_host_set_led(uint8_t usb_led);
+
+
+/* Check port settings for clock and data line */
#if !(defined(PS2_CLOCK_PORT) && \
defined(PS2_CLOCK_PIN) && \
defined(PS2_CLOCK_DDR) && \
@@ -57,27 +105,79 @@ POSSIBILITY OF SUCH DAMAGE.
# error "PS/2 data port setting is required in config.h"
#endif
-#define PS2_ACK 0xFA
-#define PS2_RESEND 0xFE
-#define PS2_SET_LED 0xED
+/*--------------------------------------------------------------------
+ * static functions
+ *------------------------------------------------------------------*/
+static inline void clock_lo(void)
+{
+ PS2_CLOCK_PORT &= ~(1<
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include
+#include
+#include "ps2.h"
+#include "debug.h"
+
+
+/*
+ * PS/2 protocol busywait version
+ */
+
+#define WAIT(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ ps2_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+uint8_t ps2_error = PS2_ERR_NONE;
+
+
+void ps2_host_init(void)
+{
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ _delay_ms(2500);
+
+ inhibit();
+}
+
+uint8_t ps2_host_send(uint8_t data)
+{
+ uint8_t res = 0;
+ bool parity = true;
+ ps2_error = PS2_ERR_NONE;
+ /* terminate a transmission if we have */
+ inhibit();
+ _delay_us(200); // at least 100us
+
+ /* start bit [1] */
+ data_lo();
+ clock_hi();
+ WAIT(clock_lo, 20000, 10); // may take 15ms at most until device starts clocking
+ /* data [2-9] */
+ for (uint8_t i = 0; i < 8; i++) {
+ _delay_us(15);
+ if (data&(1< PS2_ERR_STARTBIT3) {
+ printf("x%02X\n", ps2_error);
+ }
+ inhibit();
+ return 0;
+}