You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

usb_usb.cpp 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. Copyright 2016 Jun Wako <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #include <stdint.h>
  15. #include <stdbool.h>
  16. // USB HID host
  17. #include "Usb.h"
  18. #include "usbhub.h"
  19. #include "hid.h"
  20. #include "hidboot.h"
  21. #include "parser.h"
  22. #include "keycode.h"
  23. #include "util.h"
  24. #include "print.h"
  25. #include "debug.h"
  26. #include "timer.h"
  27. #include "matrix.h"
  28. #include "led.h"
  29. #include "action.h"
  30. #include "host.h"
  31. #define HID_MOUSE_ENABLE
  32. #define HID_COMPOSITE_ENABLE
  33. #define HID_KEYBOARD_COUNT 2
  34. #define USB_HUB_COUNT 1
  35. /* KEY CODE to Matrix
  36. *
  37. * HID keycode(1 byte):
  38. * Higher 5 bits indicates ROW and lower 3 bits COL.
  39. *
  40. * 7 6 5 4 3 2 1 0
  41. * +---------------+
  42. * | ROW | COL |
  43. * +---------------+
  44. *
  45. * Matrix space(16 * 16):
  46. * r\c0123456789ABCDEF
  47. * 0 +----------------+
  48. * : | |
  49. * : | |
  50. * 16 +----------------+
  51. */
  52. #define ROW_MASK 0xF0
  53. #define COL_MASK 0x0F
  54. #define CODE(row, col) (((row) << 4) | (col))
  55. #define ROW(code) (((code) & ROW_MASK) >> 4)
  56. #define COL(code) ((code) & COL_MASK)
  57. #define ROW_BITS(code) (1 << COL(code))
  58. // Integrated key state of all keyboards
  59. static report_keyboard_t keyboard_report;
  60. #ifdef HID_MOUSE_ENABLE
  61. extern report_mouse_t mouse_report;
  62. static uint8_t mouse_button;
  63. #endif
  64. static bool matrix_is_mod = false;
  65. /*
  66. * USB Host Shield HID keyboards
  67. * This supports two cascaded hubs and four keyboards
  68. */
  69. USB usb_host;
  70. #ifdef USB_HUB_COUNT > 0
  71. USBHub hub1(&usb_host);
  72. #ifdef USB_HUB_COUNT > 1
  73. USBHub hub2(&usb_host);
  74. #endif
  75. #endif
  76. #ifdef HID_COMPOSITE_ENABLE
  77. HIDBoot<HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE> composite(&usb_host);
  78. #else
  79. HIDBoot<HID_PROTOCOL_KEYBOARD> kbd1(&usb_host);
  80. #endif
  81. #if HID_KEYBOARD_COUNT > 1
  82. HIDBoot<HID_PROTOCOL_KEYBOARD> kbd2(&usb_host);
  83. #if HID_KEYBOARD_COUNT > 2
  84. HIDBoot<HID_PROTOCOL_KEYBOARD> kbd3(&usb_host);
  85. #if HID_KEYBOARD_COUNT > 3
  86. HIDBoot<HID_PROTOCOL_KEYBOARD> kbd4(&usb_host);
  87. #endif
  88. #endif
  89. #endif
  90. KBDReportParser kbd_parser1;
  91. #if HID_KEYBOARD_COUNT > 1
  92. KBDReportParser kbd_parser2;
  93. #if HID_KEYBOARD_COUNT > 1
  94. KBDReportParser kbd_parser3;
  95. #if HID_KEYBOARD_COUNT > 1
  96. KBDReportParser kbd_parser4;
  97. #endif
  98. #endif
  99. #endif
  100. #ifdef HID_MOUSE_ENABLE
  101. HIDBoot<HID_PROTOCOL_MOUSE> mouse1(&usb_host);
  102. MOUSEReportParser mouse_parser1;
  103. #endif
  104. uint8_t matrix_rows(void) { return MATRIX_ROWS; }
  105. uint8_t matrix_cols(void) { return MATRIX_COLS; }
  106. bool matrix_has_ghost(void) { return false; }
  107. void matrix_init(void) {
  108. // USB Host Shield setup
  109. usb_host.Init();
  110. #ifdef HID_COMPOSITE_ENABLE
  111. composite.SetReportParser(0, (HIDReportParser*)&kbd_parser1);
  112. composite.SetReportParser(1, (HIDReportParser*)&mouse_parser1);
  113. #else
  114. kbd1.SetReportParser(0, (HIDReportParser*)&kbd_parser1);
  115. #endif
  116. #if HID_KEYBOARD_COUNT > 1
  117. kbd2.SetReportParser(0, (HIDReportParser*)&kbd_parser2);
  118. #if HID_KEYBOARD_COUNT > 2
  119. kbd3.SetReportParser(0, (HIDReportParser*)&kbd_parser3);
  120. #if HID_KEYBOARD_COUNT > 3
  121. kbd4.SetReportParser(0, (HIDReportParser*)&kbd_parser4);
  122. #endif
  123. #endif
  124. #endif
  125. #ifdef HID_MOUSE_ENABLE
  126. mouse1.SetReportParser(0, (HIDReportParser*)&mouse_parser1);
  127. #endif
  128. }
  129. static void or_report(report_keyboard_t report) {
  130. // integrate reports into keyboard_report
  131. keyboard_report.mods |= report.mods;
  132. for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
  133. if (IS_ANY(report.keys[i])) {
  134. for (uint8_t j = 0; j < KEYBOARD_REPORT_KEYS; j++) {
  135. if (! keyboard_report.keys[j]) {
  136. keyboard_report.keys[j] = report.keys[i];
  137. break;
  138. }
  139. }
  140. }
  141. }
  142. }
  143. uint8_t matrix_scan(void) {
  144. static uint16_t last_time_stamp1 = 0;
  145. #if HID_KEYBOARD_COUNT > 1
  146. static uint16_t last_time_stamp2 = 0;
  147. #if HID_KEYBOARD_COUNT > 2
  148. static uint16_t last_time_stamp3 = 0;
  149. #if HID_KEYBOARD_COUNT > 3
  150. static uint16_t last_time_stamp4 = 0;
  151. #endif
  152. #endif
  153. #endif
  154. // check report came from keyboards
  155. if (kbd_parser1.time_stamp != last_time_stamp1
  156. #if HID_KEYBOARD_COUNT > 1
  157. || kbd_parser2.time_stamp != last_time_stamp2
  158. #if HID_KEYBOARD_COUNT > 2
  159. || kbd_parser3.time_stamp != last_time_stamp3
  160. #if HID_KEYBOARD_COUNT > 3
  161. || kbd_parser4.time_stamp != last_time_stamp4
  162. #endif
  163. #endif
  164. #endif
  165. ) {
  166. last_time_stamp1 = kbd_parser1.time_stamp;
  167. #if HID_KEYBOARD_COUNT > 1
  168. last_time_stamp2 = kbd_parser2.time_stamp;
  169. #if HID_KEYBOARD_COUNT > 2
  170. last_time_stamp3 = kbd_parser3.time_stamp;
  171. #if HID_KEYBOARD_COUNT > 3
  172. last_time_stamp4 = kbd_parser4.time_stamp;
  173. #endif
  174. #endif
  175. #endif
  176. // clear and integrate all reports
  177. keyboard_report = {};
  178. or_report(kbd_parser1.report);
  179. #if HID_KEYBOARD_COUNT > 1
  180. or_report(kbd_parser2.report);
  181. #if HID_KEYBOARD_COUNT > 2
  182. or_report(kbd_parser3.report);
  183. #if HID_KEYBOARD_COUNT > 3
  184. or_report(kbd_parser4.report);
  185. #endif
  186. #endif
  187. #endif
  188. matrix_is_mod = true;
  189. dprintf("state: %02X %02X", keyboard_report.mods, keyboard_report.reserved);
  190. for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
  191. dprintf(" %02X", keyboard_report.keys[i]);
  192. }
  193. dprint("\r\n");
  194. } else {
  195. matrix_is_mod = false;
  196. }
  197. #ifdef HID_MOUSE_ENABLE
  198. static uint16_t last_mouse_time_stamp = 0;
  199. if (last_mouse_time_stamp != mouse_parser1.time_stamp) {
  200. last_mouse_time_stamp = mouse_parser1.time_stamp;
  201. if (mouse_parser1.report.x || mouse_parser1.report.y) {
  202. int8_t x = mouse_report.x;
  203. int8_t y = mouse_report.y;
  204. mouse_report.x = mouse_parser1.report.x;
  205. mouse_report.y = mouse_parser1.report.y;
  206. host_mouse_send(&mouse_report);
  207. mouse_report.x = x;
  208. mouse_report.y = y;
  209. }
  210. if (mouse_parser1.report.v) {
  211. uint8_t code = 0;
  212. if (mouse_parser1.report.v == 1) code = KC_MS_WH_UP;
  213. else if (mouse_parser1.report.v == -1) code = KC_MS_WH_DOWN;
  214. if (code) {
  215. keyevent_t e;
  216. e.key.row = ROW(code);
  217. e.key.col = COL(code);
  218. e.pressed = 1;
  219. e.time = (timer_read() | 1); /* time should not be 0 */
  220. action_exec(e);
  221. e.pressed = 0;
  222. e.time = (timer_read() | 1); /* time should not be 0 */
  223. action_exec(e);
  224. }
  225. }
  226. if (mouse_button != mouse_parser1.report.buttons) {
  227. mouse_button = mouse_parser1.report.buttons;
  228. matrix_is_mod |= true;
  229. }
  230. }
  231. #endif
  232. uint16_t timer;
  233. timer = timer_read();
  234. usb_host.Task();
  235. timer = timer_elapsed(timer);
  236. if (timer > 100) {
  237. dprintf("host.Task: %d\n", timer);
  238. }
  239. return 1;
  240. }
  241. bool matrix_is_modified(void) {
  242. return matrix_is_mod;
  243. }
  244. bool matrix_is_on(uint8_t row, uint8_t col) {
  245. uint8_t code = CODE(row, col);
  246. if (IS_MOD(code)) {
  247. if (keyboard_report.mods & ROW_BITS(code)) {
  248. return true;
  249. }
  250. }
  251. for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
  252. if (keyboard_report.keys[i] == code) {
  253. return true;
  254. }
  255. }
  256. return false;
  257. }
  258. matrix_row_t matrix_get_row(uint8_t row) {
  259. uint16_t row_bits = 0;
  260. if (IS_MOD(CODE(row, 0)) && keyboard_report.mods) {
  261. row_bits |= keyboard_report.mods;
  262. }
  263. #ifdef HID_MOUSE_ENABLE
  264. if (IS_MOUSEKEY(CODE(row, 0)) && mouse_button) {
  265. if (mouse_button & (1<<0)) row_bits |= (1<<(KC_MS_BTN1 - KC_MS_UP));
  266. if (mouse_button & (1<<1)) row_bits |= (1<<(KC_MS_BTN2 - KC_MS_UP));
  267. if (mouse_button & (1<<2)) row_bits |= (1<<(KC_MS_BTN3 - KC_MS_UP));
  268. if (mouse_button & (1<<3)) row_bits |= (1<<(KC_MS_BTN4 - KC_MS_UP));
  269. if (mouse_button & (1<<4)) row_bits |= (1<<(KC_MS_BTN5 - KC_MS_UP));
  270. }
  271. #endif
  272. for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
  273. if (IS_ANY(keyboard_report.keys[i])) {
  274. if (row == ROW(keyboard_report.keys[i])) {
  275. row_bits |= ROW_BITS(keyboard_report.keys[i]);
  276. }
  277. }
  278. }
  279. return row_bits;
  280. }
  281. uint8_t matrix_key_count(void) {
  282. uint8_t count = 0;
  283. count += bitpop(keyboard_report.mods);
  284. for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
  285. if (IS_ANY(keyboard_report.keys[i])) {
  286. count++;
  287. }
  288. }
  289. return count;
  290. }
  291. void matrix_print(void) {
  292. print("\nr/c 0123456789ABCDEF\n");
  293. for (uint8_t row = 0; row < matrix_rows(); row++) {
  294. xprintf("%02d: ", row);
  295. print_bin_reverse16(matrix_get_row(row));
  296. print("\n");
  297. }
  298. }
  299. void led_set(uint8_t usb_led)
  300. {
  301. #ifdef HID_COMPOSITE_ENABLE
  302. composite.SetReport(0, 0, 2, 0, 1, &usb_led);
  303. #else
  304. kbd1.SetReport(0, 0, 2, 0, 1, &usb_led);
  305. #endif
  306. #if HID_KEYBOARD_COUNT > 1
  307. kbd2.SetReport(0, 0, 2, 0, 1, &usb_led);
  308. #if HID_KEYBOARD_COUNT > 2
  309. kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
  310. #if HID_KEYBOARD_COUNT > 3
  311. kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
  312. #endif
  313. #endif
  314. #endif
  315. }
  316. extern bool kbd_init;
  317. #ifdef __cplusplus
  318. extern "C" {
  319. void kbd_led_set(uint8_t usb_led)
  320. {
  321. if (kbd_init) {
  322. dprintf("USB LED: %d\n", usb_led);
  323. led_set(usb_led);
  324. }
  325. }
  326. }
  327. #endif