Keyboard firmwares for Atmel AVR and Cortex-M
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. Copyright 2013 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 "host.h"
  15. #include "report.h"
  16. #include "debug.h"
  17. #include "action_util.h"
  18. #include "timer.h"
  19. static inline void add_key_byte(uint8_t code);
  20. static inline void del_key_byte(uint8_t code);
  21. #ifdef NKRO_ENABLE
  22. static inline void add_key_bit(uint8_t code);
  23. static inline void del_key_bit(uint8_t code);
  24. #endif
  25. static uint8_t real_mods = 0;
  26. static uint8_t weak_mods = 0;
  27. #ifdef USB_6KRO_ENABLE
  28. #define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
  29. #define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
  30. #define RO_INC(a) RO_ADD(a, 1)
  31. #define RO_DEC(a) RO_SUB(a, 1)
  32. static int8_t cb_head = 0;
  33. static int8_t cb_tail = 0;
  34. static int8_t cb_count = 0;
  35. #endif
  36. // TODO: pointer variable is not needed
  37. //report_keyboard_t keyboard_report = {};
  38. report_keyboard_t *keyboard_report = &(report_keyboard_t){};
  39. #ifndef NO_ACTION_ONESHOT
  40. static int8_t oneshot_mods = 0;
  41. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  42. static int16_t oneshot_time = 0;
  43. #endif
  44. #endif
  45. void send_keyboard_report(void) {
  46. keyboard_report->mods = real_mods;
  47. keyboard_report->mods |= weak_mods;
  48. #ifndef NO_ACTION_ONESHOT
  49. if (oneshot_mods) {
  50. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  51. if (TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT) {
  52. dprintf("Oneshot: timeout\n");
  53. clear_oneshot_mods();
  54. }
  55. #endif
  56. keyboard_report->mods |= oneshot_mods;
  57. if (has_anykey()) {
  58. clear_oneshot_mods();
  59. }
  60. }
  61. #endif
  62. host_keyboard_send(keyboard_report);
  63. }
  64. /* key */
  65. void add_key(uint8_t key)
  66. {
  67. #ifdef NKRO_ENABLE
  68. if (keyboard_nkro) {
  69. add_key_bit(key);
  70. return;
  71. }
  72. #endif
  73. add_key_byte(key);
  74. }
  75. void del_key(uint8_t key)
  76. {
  77. #ifdef NKRO_ENABLE
  78. if (keyboard_nkro) {
  79. del_key_bit(key);
  80. return;
  81. }
  82. #endif
  83. del_key_byte(key);
  84. }
  85. void clear_keys(void)
  86. {
  87. // not clear mods
  88. for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
  89. keyboard_report->raw[i] = 0;
  90. }
  91. }
  92. /* modifier */
  93. uint8_t get_mods(void) { return real_mods; }
  94. void add_mods(uint8_t mods) { real_mods |= mods; }
  95. void del_mods(uint8_t mods) { real_mods &= ~mods; }
  96. void set_mods(uint8_t mods) { real_mods = mods; }
  97. void clear_mods(void) { real_mods = 0; }
  98. /* weak modifier */
  99. uint8_t get_weak_mods(void) { return weak_mods; }
  100. void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
  101. void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
  102. void set_weak_mods(uint8_t mods) { weak_mods = mods; }
  103. void clear_weak_mods(void) { weak_mods = 0; }
  104. /* Oneshot modifier */
  105. #ifndef NO_ACTION_ONESHOT
  106. void set_oneshot_mods(uint8_t mods)
  107. {
  108. oneshot_mods = mods;
  109. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  110. oneshot_time = timer_read();
  111. #endif
  112. }
  113. void clear_oneshot_mods(void)
  114. {
  115. oneshot_mods = 0;
  116. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  117. oneshot_time = 0;
  118. #endif
  119. }
  120. #endif
  121. /*
  122. * inspect keyboard state
  123. */
  124. uint8_t has_anykey(void)
  125. {
  126. uint8_t cnt = 0;
  127. for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
  128. if (keyboard_report->raw[i])
  129. cnt++;
  130. }
  131. return cnt;
  132. }
  133. uint8_t has_anymod(void)
  134. {
  135. return bitpop(real_mods);
  136. }
  137. uint8_t get_first_key(void)
  138. {
  139. #ifdef NKRO_ENABLE
  140. if (keyboard_nkro) {
  141. uint8_t i = 0;
  142. for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
  143. ;
  144. return i<<3 | biton(keyboard_report->nkro.bits[i]);
  145. }
  146. #endif
  147. #ifdef USB_6KRO_ENABLE
  148. uint8_t i = cb_head;
  149. do {
  150. if (keyboard_report->keys[i] != 0) {
  151. break;
  152. }
  153. i = RO_INC(i);
  154. } while (i != cb_tail);
  155. return keyboard_report->keys[i];
  156. #else
  157. return keyboard_report->keys[0];
  158. #endif
  159. }
  160. /* local functions */
  161. static inline void add_key_byte(uint8_t code)
  162. {
  163. #ifdef USB_6KRO_ENABLE
  164. int8_t i = cb_head;
  165. int8_t empty = -1;
  166. if (cb_count) {
  167. do {
  168. if (keyboard_report->keys[i] == code) {
  169. return;
  170. }
  171. if (empty == -1 && keyboard_report->keys[i] == 0) {
  172. empty = i;
  173. }
  174. i = RO_INC(i);
  175. } while (i != cb_tail);
  176. if (i == cb_tail) {
  177. if (cb_tail == cb_head) {
  178. // buffer is full
  179. if (empty == -1) {
  180. // pop head when has no empty space
  181. cb_head = RO_INC(cb_head);
  182. cb_count--;
  183. }
  184. else {
  185. // left shift when has empty space
  186. uint8_t offset = 1;
  187. i = RO_INC(empty);
  188. do {
  189. if (keyboard_report->keys[i] != 0) {
  190. keyboard_report->keys[empty] = keyboard_report->keys[i];
  191. keyboard_report->keys[i] = 0;
  192. empty = RO_INC(empty);
  193. }
  194. else {
  195. offset++;
  196. }
  197. i = RO_INC(i);
  198. } while (i != cb_tail);
  199. cb_tail = RO_SUB(cb_tail, offset);
  200. }
  201. }
  202. }
  203. }
  204. // add to tail
  205. keyboard_report->keys[cb_tail] = code;
  206. cb_tail = RO_INC(cb_tail);
  207. cb_count++;
  208. #else
  209. int8_t i = 0;
  210. int8_t empty = -1;
  211. for (; i < KEYBOARD_REPORT_KEYS; i++) {
  212. if (keyboard_report->keys[i] == code) {
  213. break;
  214. }
  215. if (empty == -1 && keyboard_report->keys[i] == 0) {
  216. empty = i;
  217. }
  218. }
  219. if (i == KEYBOARD_REPORT_KEYS) {
  220. if (empty != -1) {
  221. keyboard_report->keys[empty] = code;
  222. }
  223. }
  224. #endif
  225. }
  226. static inline void del_key_byte(uint8_t code)
  227. {
  228. #ifdef USB_6KRO_ENABLE
  229. uint8_t i = cb_head;
  230. if (cb_count) {
  231. do {
  232. if (keyboard_report->keys[i] == code) {
  233. keyboard_report->keys[i] = 0;
  234. cb_count--;
  235. if (cb_count == 0) {
  236. // reset head and tail
  237. cb_tail = cb_head = 0;
  238. }
  239. if (i == RO_DEC(cb_tail)) {
  240. // left shift when next to tail
  241. do {
  242. cb_tail = RO_DEC(cb_tail);
  243. if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
  244. break;
  245. }
  246. } while (cb_tail != cb_head);
  247. }
  248. break;
  249. }
  250. i = RO_INC(i);
  251. } while (i != cb_tail);
  252. }
  253. #else
  254. for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
  255. if (keyboard_report->keys[i] == code) {
  256. keyboard_report->keys[i] = 0;
  257. }
  258. }
  259. #endif
  260. }
  261. #ifdef NKRO_ENABLE
  262. static inline void add_key_bit(uint8_t code)
  263. {
  264. if ((code>>3) < KEYBOARD_REPORT_BITS) {
  265. keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
  266. } else {
  267. dprintf("add_key_bit: can't add: %02X\n", code);
  268. }
  269. }
  270. static inline void del_key_bit(uint8_t code)
  271. {
  272. if ((code>>3) < KEYBOARD_REPORT_BITS) {
  273. keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
  274. } else {
  275. dprintf("del_key_bit: can't del: %02X\n", code);
  276. }
  277. }
  278. #endif