Keyboard firmwares for Atmel AVR and Cortex-M
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.

usb_keyboard.c 6.0KB

13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include <avr/interrupt.h>
  2. #include <avr/pgmspace.h>
  3. #include "usb_keycodes.h"
  4. #include "usb_keyboard.h"
  5. #include "print.h"
  6. #include "debug.h"
  7. #include "util.h"
  8. // keyboard report.
  9. static usb_keyboard_report_t _report0 = { {0}, 0, false };
  10. static usb_keyboard_report_t _report1 = { {0}, 0, false };
  11. usb_keyboard_report_t *usb_keyboard_report = &_report0;
  12. usb_keyboard_report_t *usb_keyboard_report_prev = &_report1;
  13. // protocol setting from the host. We use exactly the same report
  14. // either way, so this variable only stores the setting since we
  15. // are required to be able to report which setting is in use.
  16. uint8_t usb_keyboard_protocol=1;
  17. // the idle configuration, how often we send the report to the
  18. // host (ms * 4) even when it hasn't changed
  19. uint8_t usb_keyboard_idle_config=125;
  20. // count until idle timeout
  21. uint8_t usb_keyboard_idle_count=0;
  22. // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
  23. volatile uint8_t usb_keyboard_leds=0;
  24. // enable USB NKRO
  25. bool usb_keyboard_nkro = false;
  26. int8_t usb_keyboard_send(void)
  27. {
  28. return usb_keyboard_send_report(usb_keyboard_report);
  29. }
  30. static inline int8_t _send_report(usb_keyboard_report_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end);
  31. int8_t usb_keyboard_send_report(usb_keyboard_report_t *report)
  32. {
  33. int8_t result = 0;
  34. #ifdef USB_NKRO_ENABLE
  35. if (usb_keyboard_nkro)
  36. result = _send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS);
  37. else
  38. #endif
  39. {
  40. if (usb_keyboard_protocol)
  41. result = _send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS);
  42. else
  43. result = _send_report(report, KBD_ENDPOINT, 0, 6);
  44. }
  45. if (result) return result;
  46. usb_keyboard_idle_count = 0;
  47. report->is_sent =true;
  48. usb_keyboard_print_report(report);
  49. return 0;
  50. }
  51. void usb_keyboard_swap_report(void) {
  52. usb_keyboard_report_t *tmp = usb_keyboard_report_prev;
  53. usb_keyboard_report_prev = usb_keyboard_report;
  54. usb_keyboard_report = tmp;
  55. }
  56. void usb_keyboard_clear_report(void) {
  57. usb_keyboard_clear_keys();
  58. usb_keyboard_clear_mods();
  59. usb_keyboard_report->is_sent = false;
  60. }
  61. void usb_keyboard_clear_keys(void) {
  62. for (int i = 0; i < KEYS_MAX; i++) usb_keyboard_report->keys[i] = 0;
  63. }
  64. void usb_keyboard_clear_mods(void)
  65. {
  66. usb_keyboard_report->mods = 0;
  67. }
  68. void usb_keyboard_set_keys(uint8_t *keys)
  69. {
  70. for (int i = 0; i < KEYS_MAX; i++)
  71. usb_keyboard_report->keys[i] = keys[i];
  72. }
  73. void usb_keyboard_set_mods(uint8_t mods)
  74. {
  75. usb_keyboard_report->mods = mods;
  76. }
  77. void usb_keyboard_add_code(uint8_t code)
  78. {
  79. if (IS_MOD(code)) {
  80. usb_keyboard_add_mod(code);
  81. } else {
  82. usb_keyboard_add_key(code);
  83. }
  84. }
  85. static inline void _add_key_byte(uint8_t code);
  86. static inline void _add_key_bit(uint8_t code);
  87. void usb_keyboard_add_key(uint8_t code)
  88. {
  89. #ifdef USB_NKRO_ENABLE
  90. if (usb_keyboard_nkro) {
  91. _add_key_bit(code);
  92. return;
  93. }
  94. #endif
  95. _add_key_byte(code);
  96. }
  97. void usb_keyboard_add_mod(uint8_t code)
  98. {
  99. usb_keyboard_report->mods |= MOD_BIT(code);
  100. }
  101. void usb_keyboard_del_code(uint8_t code)
  102. {
  103. if (IS_MOD(code)) {
  104. usb_keyboard_del_mod(code);
  105. } else {
  106. usb_keyboard_del_key(code);
  107. }
  108. }
  109. void usb_keyboard_del_key(uint8_t code)
  110. {
  111. #ifdef USB_NKRO_ENABLE
  112. if ((code>>3) < KEYS_MAX) {
  113. usb_keyboard_keys[code>>3] &= ~(1<<(code&7));
  114. }
  115. #else
  116. for (int i = 0; i < KEYS_MAX; i++) {
  117. if (usb_keyboard_report->keys[i] == code) {
  118. usb_keyboard_report->keys[i] = KB_NO;
  119. return;
  120. }
  121. }
  122. #endif
  123. }
  124. void usb_keyboard_del_mod(uint8_t code)
  125. {
  126. usb_keyboard_report->mods &= ~MOD_BIT(code);
  127. }
  128. bool usb_keyboard_is_sent(void)
  129. {
  130. return usb_keyboard_report->is_sent;
  131. }
  132. bool usb_keyboard_has_key(void)
  133. {
  134. uint8_t keys = 0;
  135. for (int i = 0; i < KEYS_MAX; i++) keys |= usb_keyboard_report->keys[i];
  136. return keys ? true : false;
  137. }
  138. bool usb_keyboard_has_mod(void)
  139. {
  140. return usb_keyboard_report->mods ? true : false;
  141. }
  142. uint8_t usb_keyboard_get_key(void)
  143. {
  144. #ifdef USB_NKRO_ENABLE
  145. if (usb_keyboard_nkro) {
  146. uint8_t i = 0;
  147. for (; i < KEYS_MAX && !usb_keyboard_keys[i]; i++);
  148. return i<<3 | biton(usb_keyboard_keys[i]);
  149. }
  150. #endif
  151. return usb_keyboard_keys[0];
  152. }
  153. void usb_keyboard_print_report(usb_keyboard_report_t *report)
  154. {
  155. if (!debug_keyboard) return;
  156. print("keys: ");
  157. for (int i = 0; i < KEYS_MAX; i++) { phex(report->keys[i]); print(" "); }
  158. print(" mods: "); phex(report->mods); print("\n");
  159. }
  160. static inline int8_t _send_report(usb_keyboard_report_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end)
  161. {
  162. uint8_t intr_state, timeout;
  163. if (!usb_configured()) return -1;
  164. intr_state = SREG;
  165. cli();
  166. UENUM = endpoint;
  167. timeout = UDFNUML + 50;
  168. while (1) {
  169. // are we ready to transmit?
  170. if (UEINTX & (1<<RWAL)) break;
  171. SREG = intr_state;
  172. // has the USB gone offline?
  173. if (!usb_configured()) return -1;
  174. // have we waited too long?
  175. if (UDFNUML == timeout) return -1;
  176. // get ready to try checking again
  177. intr_state = SREG;
  178. cli();
  179. UENUM = endpoint;
  180. }
  181. UEDATX = report->mods;
  182. if (!usb_keyboard_nkro)
  183. UEDATX = 0;
  184. for (uint8_t i = keys_start; i < keys_end; i++) {
  185. UEDATX = report->keys[i];
  186. }
  187. UEINTX = 0x3A;
  188. SREG = intr_state;
  189. return 0;
  190. }
  191. static inline void _add_key_byte(uint8_t code)
  192. {
  193. // TODO: fix ugly code
  194. int8_t i = 0;
  195. int8_t empty = -1;
  196. for (; i < KEYS_MAX; i++) {
  197. if (usb_keyboard_keys_prev[i] == code) {
  198. usb_keyboard_keys[i] = code;
  199. break;
  200. }
  201. if (empty == -1 &&
  202. usb_keyboard_keys_prev[i] == 0 &&
  203. usb_keyboard_keys[i] == 0) {
  204. empty = i;
  205. }
  206. }
  207. if (i == KEYS_MAX) {
  208. if (empty != -1) {
  209. usb_keyboard_keys[empty] = code;
  210. }
  211. }
  212. }
  213. static inline void _add_key_bit(uint8_t code)
  214. {
  215. if ((code>>3) < KEYS_MAX) {
  216. usb_keyboard_keys[code>>3] |= 1<<(code&7);
  217. }
  218. }