usb_usb: Add multiple keyboard support
authortmk <hasu@tmk-kbd.com>
Tue, 21 Jun 2016 04:49:06 +0000 (13:49 +0900)
committertmk <hasu@tmk-kbd.com>
Tue, 21 Jun 2016 04:49:06 +0000 (13:49 +0900)
it supports four keyboards and two cascaded hubs

converter/usb_usb/Makefile
converter/usb_usb/main.cpp
converter/usb_usb/matrix.c [deleted file]
converter/usb_usb/usb_usb.cpp [new file with mode: 0644]
tmk_core/common/util.h
tmk_core/protocol/usb_hid/parser.cpp
tmk_core/protocol/usb_hid/parser.h

index 0f25232b2599ca93350cdae2f2cc1a02000b40c1..5abb49d79fc7fc8c9383b77073c17b34093e08ea 100644 (file)
@@ -110,7 +110,7 @@ OPT_DEFS += -DBOOTLOADER_SIZE=4096
 
 SRC =  \
        keymap_common.c \
-       matrix.c \
+       usb_usb.cpp \
        main.cpp
 
 ifdef KEYMAP
index 652c80573466b3498d29b41b2dfbef72a35d0c33..5b542a75c10c055055bb19556bc153761f7053f8 100644 (file)
@@ -3,17 +3,9 @@
 #include <avr/power.h>
 #include <util/delay.h>
 
-// USB HID host
-#include "Usb.h"
-#include "usbhub.h"
-#include "hid.h"
-#include "hidboot.h"
-#include "parser.h"
-
 // LUFA
 #include "lufa.h"
 
-#include "timer.h"
 #include "sendchar.h"
 #include "debug.h"
 #include "keyboard.h"
@@ -64,22 +56,6 @@ static void LUFA_setup(void)
 
 
 
-/*
- * USB Host Shield HID keyboard
- */
-USB usb_host;
-USBHub hub1(&usb_host);
-HIDBoot<HID_PROTOCOL_KEYBOARD>    kbd(&usb_host);
-KBDReportParser kbd_parser;
-
-
-void led_set(uint8_t usb_led)
-{
-    kbd.SetReport(0, 0, 2, 0, 1, &usb_led);
-}
-
-
-
 int main(void)
 {
     // LED for debug
@@ -94,10 +70,6 @@ int main(void)
 
     LUFA_setup();
 
-    // USB Host Shield setup
-    usb_host.Init();
-    kbd.SetReportParser(0, (HIDReportParser*)&kbd_parser);
-
     /* NOTE: Don't insert time consuming job here.
      * It'll cause unclear initialization failure when DFU reset(worm start).
      */
@@ -111,17 +83,9 @@ int main(void)
 
     debug("init: done\n");
 
-uint16_t timer;
     for (;;) {
         keyboard_task();
 
-timer = timer_read();
-        usb_host.Task();
-timer = timer_elapsed(timer);
-if (timer > 100) {
-    debug("host.Task: "); debug_hex16(timer);  debug("\n");
-}
-
 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
         // LUFA Task for control request
         USB_USBTask();
diff --git a/converter/usb_usb/matrix.c b/converter/usb_usb/matrix.c
deleted file mode 100644 (file)
index 184933a..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-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 "usb_hid.h"
-#include "keycode.h"
-#include "util.h"
-#include "print.h"
-#include "debug.h"
-#include "matrix.h"
-
-/* KEY CODE to Matrix
- *
- * HID keycode(1 byte):
- * Higher 5 bits indicates ROW and lower 3 bits COL.
- *
- *  7 6 5 4 3 2 1 0
- * +---------------+
- * |  ROW  |  COL  |
- * +---------------+
- *
- * Matrix space(16 * 16):
- *   r\c0123456789ABCDEF
- *   0 +----------------+
- *   : |                |
- *   : |                |
- *  16 +----------------+
- */
-#define ROW_MASK 0xF0
-#define COL_MASK 0x0F
-#define CODE(row, col)  (((row) << 4) | (col))
-#define ROW(code)       (((code) & ROW_MASK) >> 4)
-#define COL(code)       ((code) & COL_MASK)
-#define ROW_BITS(code)  (1 << COL(code))
-
-
-uint8_t matrix_rows(void) { return MATRIX_ROWS; }
-uint8_t matrix_cols(void) { return MATRIX_COLS; }
-void matrix_init(void) {}
-bool matrix_has_ghost(void) { return false; }
-
-static bool matrix_is_mod =false;
-
-uint8_t matrix_scan(void) {
-    static uint16_t last_time_stamp = 0;
-
-    if (last_time_stamp != usb_hid_time_stamp) {
-        last_time_stamp = usb_hid_time_stamp;
-        matrix_is_mod = true;
-    } else {
-        matrix_is_mod = false;
-    }
-    return 1;
-}
-
-bool matrix_is_modified(void) {
-
-    return matrix_is_mod;
-}
-
-bool matrix_is_on(uint8_t row, uint8_t col) {
-    uint8_t code = CODE(row, col);
-
-    if (IS_MOD(code)) {
-        if (usb_hid_keyboard_report.mods & ROW_BITS(code)) {
-            return true;
-        }
-    }
-    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
-        if (usb_hid_keyboard_report.keys[i] == code) {
-            return true;
-        }
-    }
-    return false;
-}
-
-matrix_row_t matrix_get_row(uint8_t row) {
-    uint16_t row_bits = 0;
-
-    if (IS_MOD(CODE(row, 0)) && usb_hid_keyboard_report.mods) {
-        row_bits |= usb_hid_keyboard_report.mods;
-    }
-
-    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
-        if (IS_ANY(usb_hid_keyboard_report.keys[i])) {
-            if (row == ROW(usb_hid_keyboard_report.keys[i])) {
-                row_bits |= ROW_BITS(usb_hid_keyboard_report.keys[i]);
-            }
-        }
-    }
-    return row_bits;
-}
-
-uint8_t matrix_key_count(void) {
-    uint8_t count = 0;
-
-    count += bitpop(usb_hid_keyboard_report.mods);
-    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
-        if (IS_ANY(usb_hid_keyboard_report.keys[i])) {
-            count++;
-        }
-    }
-    return count;
-}
-
-void matrix_print(void) {
-    print("\nr/c 01234567\n");
-    for (uint8_t row = 0; row < matrix_rows(); row++) {
-        phex(row); print(": ");
-        pbin_reverse(matrix_get_row(row));
-#ifdef MATRIX_HAS_GHOST
-        if (matrix_has_ghost_in_row(row)) {
-            print(" <ghost");
-        }
-#endif
-        print("\n");
-    }
-}
diff --git a/converter/usb_usb/usb_usb.cpp b/converter/usb_usb/usb_usb.cpp
new file mode 100644 (file)
index 0000000..969e89f
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+Copyright 2016 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>
+
+// USB HID host
+#include "Usb.h"
+#include "usbhub.h"
+#include "hid.h"
+#include "hidboot.h"
+#include "parser.h"
+
+#include "keycode.h"
+#include "util.h"
+#include "print.h"
+#include "debug.h"
+#include "timer.h"
+#include "matrix.h"
+#include "led.h"
+
+
+/* KEY CODE to Matrix
+ *
+ * HID keycode(1 byte):
+ * Higher 5 bits indicates ROW and lower 3 bits COL.
+ *
+ *  7 6 5 4 3 2 1 0
+ * +---------------+
+ * |  ROW  |  COL  |
+ * +---------------+
+ *
+ * Matrix space(16 * 16):
+ *   r\c0123456789ABCDEF
+ *   0 +----------------+
+ *   : |                |
+ *   : |                |
+ *  16 +----------------+
+ */
+#define ROW_MASK 0xF0
+#define COL_MASK 0x0F
+#define CODE(row, col)  (((row) << 4) | (col))
+#define ROW(code)       (((code) & ROW_MASK) >> 4)
+#define COL(code)       ((code) & COL_MASK)
+#define ROW_BITS(code)  (1 << COL(code))
+
+
+// Integrated key state of all keyboards
+static report_keyboard_t keyboard_report;
+
+static bool matrix_is_mod =false;
+
+/*
+ * USB Host Shield HID keyboards
+ * This supports two cascaded hubs and four keyboards
+ */
+USB usb_host;
+USBHub hub1(&usb_host);
+USBHub hub2(&usb_host);
+HIDBoot<HID_PROTOCOL_KEYBOARD>    kbd1(&usb_host);
+HIDBoot<HID_PROTOCOL_KEYBOARD>    kbd2(&usb_host);
+HIDBoot<HID_PROTOCOL_KEYBOARD>    kbd3(&usb_host);
+HIDBoot<HID_PROTOCOL_KEYBOARD>    kbd4(&usb_host);
+KBDReportParser kbd_parser1;
+KBDReportParser kbd_parser2;
+KBDReportParser kbd_parser3;
+KBDReportParser kbd_parser4;
+
+
+uint8_t matrix_rows(void) { return MATRIX_ROWS; }
+uint8_t matrix_cols(void) { return MATRIX_COLS; }
+bool matrix_has_ghost(void) { return false; }
+void matrix_init(void) {
+    // USB Host Shield setup
+    usb_host.Init();
+    kbd1.SetReportParser(0, (HIDReportParser*)&kbd_parser1);
+    kbd2.SetReportParser(0, (HIDReportParser*)&kbd_parser2);
+    kbd3.SetReportParser(0, (HIDReportParser*)&kbd_parser3);
+    kbd4.SetReportParser(0, (HIDReportParser*)&kbd_parser4);
+}
+
+static void or_report(report_keyboard_t report) {
+    // integrate reports into keyboard_report
+    keyboard_report.mods |= report.mods;
+    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+        if (IS_ANY(report.keys[i])) {
+            for (uint8_t j = 0; j < KEYBOARD_REPORT_KEYS; j++) {
+                if (! keyboard_report.keys[j]) {
+                    keyboard_report.keys[j] = report.keys[i];
+                    break;
+                }
+            }
+        }
+    }
+}
+
+uint8_t matrix_scan(void) {
+    static uint16_t last_time_stamp1 = 0;
+    static uint16_t last_time_stamp2 = 0;
+    static uint16_t last_time_stamp3 = 0;
+    static uint16_t last_time_stamp4 = 0;
+
+    // check report came from keyboards
+    if (kbd_parser1.time_stamp != last_time_stamp1 ||
+        kbd_parser2.time_stamp != last_time_stamp2 ||
+        kbd_parser3.time_stamp != last_time_stamp3 ||
+        kbd_parser4.time_stamp != last_time_stamp4) {
+
+        last_time_stamp1 = kbd_parser1.time_stamp;
+        last_time_stamp2 = kbd_parser2.time_stamp;
+        last_time_stamp3 = kbd_parser3.time_stamp;
+        last_time_stamp4 = kbd_parser4.time_stamp;
+
+        // clear and integrate all reports
+        keyboard_report = {};
+        or_report(kbd_parser1.report);
+        or_report(kbd_parser2.report);
+        or_report(kbd_parser3.report);
+        or_report(kbd_parser4.report);
+
+        matrix_is_mod = true;
+
+        dprintf("state:  %02X %02X", keyboard_report.mods, keyboard_report.reserved);
+        for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+            dprintf(" %02X", keyboard_report.keys[i]);
+        }
+        dprint("\r\n");
+    } else {
+        matrix_is_mod = false;
+    }
+
+    uint16_t timer;
+    timer = timer_read();
+    usb_host.Task();
+    timer = timer_elapsed(timer);
+    if (timer > 100) {
+        dprintf("host.Task: %d\n", timer);
+    }
+
+    return 1;
+}
+
+bool matrix_is_modified(void) {
+    return matrix_is_mod;
+}
+
+bool matrix_is_on(uint8_t row, uint8_t col) {
+    uint8_t code = CODE(row, col);
+
+    if (IS_MOD(code)) {
+        if (keyboard_report.mods & ROW_BITS(code)) {
+            return true;
+        }
+    }
+    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+        if (keyboard_report.keys[i] == code) {
+            return true;
+        }
+    }
+    return false;
+}
+
+matrix_row_t matrix_get_row(uint8_t row) {
+    uint16_t row_bits = 0;
+
+    if (IS_MOD(CODE(row, 0)) && keyboard_report.mods) {
+        row_bits |= keyboard_report.mods;
+    }
+
+    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+        if (IS_ANY(keyboard_report.keys[i])) {
+            if (row == ROW(keyboard_report.keys[i])) {
+                row_bits |= ROW_BITS(keyboard_report.keys[i]);
+            }
+        }
+    }
+    return row_bits;
+}
+
+uint8_t matrix_key_count(void) {
+    uint8_t count = 0;
+
+    count += bitpop(keyboard_report.mods);
+    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+        if (IS_ANY(keyboard_report.keys[i])) {
+            count++;
+        }
+    }
+    return count;
+}
+
+void matrix_print(void) {
+    print("\nr/c 0123456789ABCDEF\n");
+    for (uint8_t row = 0; row < matrix_rows(); row++) {
+        xprintf("%02d: ", row);
+        print_bin_reverse16(matrix_get_row(row));
+        print("\n");
+    }
+}
+
+void led_set(uint8_t usb_led)
+{
+    kbd1.SetReport(0, 0, 2, 0, 1, &usb_led);
+    kbd2.SetReport(0, 0, 2, 0, 1, &usb_led);
+    kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
+    kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
+}
index 7451cc084da9e4483977411dc1ed19eb99475d5a..3e01a93dd92980bfe918faf4f4e1e850789cd91a 100644 (file)
@@ -28,6 +28,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define XSTR(s) #s
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 uint8_t bitpop(uint8_t bits);
 uint8_t bitpop16(uint16_t bits);
 uint8_t bitpop32(uint32_t bits);
@@ -40,4 +44,8 @@ uint8_t  bitrev(uint8_t bits);
 uint16_t bitrev16(uint16_t bits);
 uint32_t bitrev32(uint32_t bits);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index fe002c0d961d75fb72da070e5b8d959ca8ebd967..94e747ca4b8313f9e17a3a523c531b103151aef7 100644 (file)
@@ -4,30 +4,14 @@
 #include "debug.h"
 
 
-report_keyboard_t usb_hid_keyboard_report;
-uint16_t usb_hid_time_stamp;
-
-
 void KBDReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
 {
-    bool is_error = false;
-    report_keyboard_t *report = (report_keyboard_t *)buf;
+    ::memcpy(&report, buf, sizeof(report_keyboard_t));
+    time_stamp = millis();
 
-    dprintf("keyboard input:  %02X %02X", report->mods, report->reserved);
+    dprintf("input %d:  %02X %02X", hid->GetAddress(), report.mods, report.reserved);
     for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
-        if (IS_ERROR(report->keys[i])) {
-            is_error = true;
-        }
-        dprintf(" %02X", report->keys[i]);
+        dprintf(" %02X", report.keys[i]);
     }
     dprint("\r\n");
-
-    // ignore error and not send report to computer
-    if (is_error) {
-        dprint("Error usage! \r\n");
-        return;
-    }
-
-    ::memcpy(&usb_hid_keyboard_report, buf, sizeof(report_keyboard_t));
-    usb_hid_time_stamp = millis();
 }
index 703eb1ed4ce6f4499b7dc1ae680d03089bb5a74e..036281fa661342b43fa89a6fe1a7440072a7f8e4 100644 (file)
@@ -2,11 +2,14 @@
 #define PARSER_H
 
 #include "hid.h"
+#include "report.h"
 
 class KBDReportParser : public HIDReportParser
 {
 public:
-       virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+    report_keyboard_t report;
+    uint16_t time_stamp;
+    virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
 };
 
 #endif
Imprint / Impressum