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 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. // keyboard report.
  8. static usb_keyboard_report_t _report0 = { {0}, 0 };
  9. static usb_keyboard_report_t _report1 = { {0}, 0 };
  10. usb_keyboard_report_t *usb_keyboard_report = &_report0;
  11. usb_keyboard_report_t *usb_keyboard_report_prev = &_report1;
  12. // protocol setting from the host. We use exactly the same report
  13. // either way, so this variable only stores the setting since we
  14. // are required to be able to report which setting is in use.
  15. uint8_t usb_keyboard_protocol=1;
  16. // the idle configuration, how often we send the report to the
  17. // host (ms * 4) even when it hasn't changed
  18. uint8_t usb_keyboard_idle_config=125;
  19. // count until idle timeout
  20. uint8_t usb_keyboard_idle_count=0;
  21. // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
  22. volatile uint8_t usb_keyboard_leds=0;
  23. int8_t usb_keyboard_send(void)
  24. {
  25. return usb_keyboard_send_report(usb_keyboard_report);
  26. }
  27. int8_t usb_keyboard_send_report(usb_keyboard_report_t *report)
  28. {
  29. uint8_t i, intr_state, timeout;
  30. if (!usb_configured()) return -1;
  31. intr_state = SREG;
  32. cli();
  33. UENUM = KEYBOARD_ENDPOINT;
  34. timeout = UDFNUML + 50;
  35. while (1) {
  36. // are we ready to transmit?
  37. if (UEINTX & (1<<RWAL)) break;
  38. SREG = intr_state;
  39. // has the USB gone offline?
  40. if (!usb_configured()) return -1;
  41. // have we waited too long?
  42. if (UDFNUML == timeout) return -1;
  43. // get ready to try checking again
  44. intr_state = SREG;
  45. cli();
  46. UENUM = KEYBOARD_ENDPOINT;
  47. }
  48. UEDATX = report->mods;
  49. UEDATX = 0;
  50. for (i = 0; i < 6; i++) {
  51. UEDATX = report->keys[i];
  52. }
  53. UEINTX = 0x3A;
  54. SREG = intr_state;
  55. #ifdef USB_12KRO
  56. if (!usb_configured()) return -1;
  57. intr_state = SREG;
  58. cli();
  59. UENUM = KEYBOARD_ENDPOINT2;
  60. timeout = UDFNUML + 50;
  61. while (1) {
  62. // are we ready to transmit?
  63. if (UEINTX & (1<<RWAL)) break;
  64. SREG = intr_state;
  65. // has the USB gone offline?
  66. if (!usb_configured()) return -1;
  67. // have we waited too long?
  68. if (UDFNUML == timeout) return -1;
  69. // get ready to try checking again
  70. intr_state = SREG;
  71. cli();
  72. UENUM = KEYBOARD_ENDPOINT2;
  73. }
  74. UEDATX = report->mods;
  75. UEDATX = 0;
  76. for (i = 6; i < 12; i++) {
  77. UEDATX = report->keys[i];
  78. }
  79. UEINTX = 0x3A;
  80. SREG = intr_state;
  81. #endif
  82. usb_keyboard_idle_count = 0;
  83. report->is_sent =true;
  84. usb_keyboard_print_report(report);
  85. return 0;
  86. }
  87. void usb_keyboard_swap_report(void) {
  88. usb_keyboard_report_t *tmp = usb_keyboard_report_prev;
  89. usb_keyboard_report_prev = usb_keyboard_report;
  90. usb_keyboard_report = tmp;
  91. }
  92. void usb_keyboard_clear_report(void) {
  93. usb_keyboard_clear_keys();
  94. usb_keyboard_clear_mods();
  95. usb_keyboard_report->is_sent = false;
  96. }
  97. void usb_keyboard_clear_keys(void) {
  98. for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) usb_keyboard_report->keys[i] = 0;
  99. }
  100. void usb_keyboard_clear_mods(void)
  101. {
  102. usb_keyboard_report->mods = 0;
  103. }
  104. void usb_keyboard_add_code(uint8_t code)
  105. {
  106. if (IS_MOD(code)) {
  107. usb_keyboard_add_mod(code);
  108. } else {
  109. usb_keyboard_add_key(code);
  110. }
  111. }
  112. void usb_keyboard_add_key(uint8_t code)
  113. {
  114. for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) {
  115. if (!usb_keyboard_report->keys[i]) {
  116. usb_keyboard_report->keys[i] = code;
  117. return;
  118. }
  119. }
  120. }
  121. void usb_keyboard_set_keys(uint8_t *keys)
  122. {
  123. for (int i = 0; i < KEYBOARD_REPORT_MAX; i++)
  124. usb_keyboard_report->keys[i] = keys[i];
  125. }
  126. void usb_keyboard_set_mods(uint8_t mods)
  127. {
  128. usb_keyboard_report->mods = mods;
  129. }
  130. void usb_keyboard_add_mod(uint8_t code)
  131. {
  132. usb_keyboard_report->mods |= MOD_BIT(code);
  133. }
  134. void usb_keyboard_del_code(uint8_t code)
  135. {
  136. if (IS_MOD(code)) {
  137. usb_keyboard_del_mod(code);
  138. } else {
  139. usb_keyboard_del_key(code);
  140. }
  141. }
  142. void usb_keyboard_del_key(uint8_t code)
  143. {
  144. for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) {
  145. if (usb_keyboard_report->keys[i] == code) {
  146. usb_keyboard_report->keys[i] = KB_NO;
  147. return;
  148. }
  149. }
  150. }
  151. void usb_keyboard_del_mod(uint8_t code)
  152. {
  153. usb_keyboard_report->mods &= ~MOD_BIT(code);
  154. }
  155. bool usb_keyboard_is_sent(void)
  156. {
  157. return usb_keyboard_report->is_sent;
  158. }
  159. bool usb_keyboard_has_key(void)
  160. {
  161. uint8_t keys = 0;
  162. for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) keys |= usb_keyboard_report->keys[i];
  163. return keys ? true : false;
  164. }
  165. bool usb_keyboard_has_mod(void)
  166. {
  167. return usb_keyboard_report->mods ? true : false;
  168. }
  169. void usb_keyboard_print_report(usb_keyboard_report_t *report)
  170. {
  171. if (!debug_keyboard) return;
  172. print("keys: ");
  173. for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { phex(report->keys[i]); print(" "); }
  174. print(" mods: "); phex(report->mods); print("\n");
  175. }