upload
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.

action_util.c 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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 "action_layer.h"
  19. #include "timer.h"
  20. static inline void add_key_byte(uint8_t code);
  21. static inline void del_key_byte(uint8_t code);
  22. #ifdef NKRO_ENABLE
  23. static inline void add_key_bit(uint8_t code);
  24. static inline void del_key_bit(uint8_t code);
  25. #endif
  26. static uint8_t real_mods = 0;
  27. static uint8_t weak_mods = 0;
  28. static uint8_t macro_mods = 0;
  29. #ifdef USB_6KRO_ENABLE
  30. #define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
  31. #define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
  32. #define RO_INC(a) RO_ADD(a, 1)
  33. #define RO_DEC(a) RO_SUB(a, 1)
  34. static int8_t cb_head = 0;
  35. static int8_t cb_tail = 0;
  36. static int8_t cb_count = 0;
  37. #endif
  38. // TODO: pointer variable is not needed
  39. //report_keyboard_t keyboard_report = {};
  40. report_keyboard_t *keyboard_report = &(report_keyboard_t){};
  41. #ifndef NO_ACTION_ONESHOT
  42. static int8_t oneshot_mods = 0;
  43. static int8_t oneshot_locked_mods = 0;
  44. int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
  45. void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; }
  46. void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; }
  47. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  48. static int16_t oneshot_time = 0;
  49. inline bool has_oneshot_mods_timed_out() {
  50. return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT;
  51. }
  52. #endif
  53. #endif
  54. /* oneshot layer */
  55. #ifndef NO_ACTION_ONESHOT
  56. /* oneshot_layer_data bits
  57. * LLLL LSSS
  58. * where:
  59. * L => are layer bits
  60. * S => oneshot state bits
  61. */
  62. static int8_t oneshot_layer_data = 0;
  63. inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
  64. inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }
  65. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  66. static int16_t oneshot_layer_time = 0;
  67. inline bool has_oneshot_layer_timed_out() {
  68. return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT &&
  69. !(get_oneshot_layer_state() & ONESHOT_TOGGLED);
  70. }
  71. #endif
  72. /* Oneshot layer */
  73. void set_oneshot_layer(uint8_t layer, uint8_t state)
  74. {
  75. oneshot_layer_data = layer << 3 | state;
  76. layer_on(layer);
  77. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  78. oneshot_layer_time = timer_read();
  79. #endif
  80. }
  81. void reset_oneshot_layer(void) {
  82. oneshot_layer_data = 0;
  83. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  84. oneshot_layer_time = 0;
  85. #endif
  86. }
  87. void clear_oneshot_layer_state(oneshot_fullfillment_t state)
  88. {
  89. uint8_t start_state = oneshot_layer_data;
  90. oneshot_layer_data &= ~state;
  91. if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) {
  92. layer_off(get_oneshot_layer());
  93. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  94. oneshot_layer_time = 0;
  95. #endif
  96. }
  97. }
  98. bool is_oneshot_layer_active(void)
  99. {
  100. return get_oneshot_layer_state();
  101. }
  102. #endif
  103. void send_keyboard_report(void) {
  104. keyboard_report->mods = real_mods;
  105. keyboard_report->mods |= weak_mods;
  106. keyboard_report->mods |= macro_mods;
  107. #ifndef NO_ACTION_ONESHOT
  108. if (oneshot_mods) {
  109. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  110. if (has_oneshot_mods_timed_out()) {
  111. dprintf("Oneshot: timeout\n");
  112. clear_oneshot_mods();
  113. }
  114. #endif
  115. keyboard_report->mods |= oneshot_mods;
  116. if (has_anykey()) {
  117. clear_oneshot_mods();
  118. }
  119. }
  120. #endif
  121. host_keyboard_send(keyboard_report);
  122. }
  123. /* key */
  124. void add_key(uint8_t key)
  125. {
  126. #ifdef NKRO_ENABLE
  127. if (keyboard_protocol && keyboard_nkro) {
  128. add_key_bit(key);
  129. return;
  130. }
  131. #endif
  132. add_key_byte(key);
  133. }
  134. void del_key(uint8_t key)
  135. {
  136. #ifdef NKRO_ENABLE
  137. if (keyboard_protocol && keyboard_nkro) {
  138. del_key_bit(key);
  139. return;
  140. }
  141. #endif
  142. del_key_byte(key);
  143. }
  144. void clear_keys(void)
  145. {
  146. // not clear mods
  147. for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
  148. keyboard_report->raw[i] = 0;
  149. }
  150. }
  151. /* modifier */
  152. uint8_t get_mods(void) { return real_mods; }
  153. void add_mods(uint8_t mods) { real_mods |= mods; }
  154. void del_mods(uint8_t mods) { real_mods &= ~mods; }
  155. void set_mods(uint8_t mods) { real_mods = mods; }
  156. void clear_mods(void) { real_mods = 0; }
  157. /* weak modifier */
  158. uint8_t get_weak_mods(void) { return weak_mods; }
  159. void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
  160. void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
  161. void set_weak_mods(uint8_t mods) { weak_mods = mods; }
  162. void clear_weak_mods(void) { weak_mods = 0; }
  163. /* macro modifier */
  164. uint8_t get_macro_mods(void) { return macro_mods; }
  165. void add_macro_mods(uint8_t mods) { macro_mods |= mods; }
  166. void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; }
  167. void set_macro_mods(uint8_t mods) { macro_mods = mods; }
  168. void clear_macro_mods(void) { macro_mods = 0; }
  169. /* Oneshot modifier */
  170. #ifndef NO_ACTION_ONESHOT
  171. void set_oneshot_mods(uint8_t mods)
  172. {
  173. oneshot_mods = mods;
  174. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  175. oneshot_time = timer_read();
  176. #endif
  177. }
  178. void clear_oneshot_mods(void)
  179. {
  180. oneshot_mods = 0;
  181. #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
  182. oneshot_time = 0;
  183. #endif
  184. }
  185. uint8_t get_oneshot_mods(void)
  186. {
  187. return oneshot_mods;
  188. }
  189. #endif
  190. /*
  191. * inspect keyboard state
  192. */
  193. uint8_t has_anykey(void)
  194. {
  195. uint8_t cnt = 0;
  196. for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
  197. if (keyboard_report->raw[i])
  198. cnt++;
  199. }
  200. return cnt;
  201. }
  202. uint8_t has_anymod(void)
  203. {
  204. return bitpop(real_mods);
  205. }
  206. uint8_t get_first_key(void)
  207. {
  208. #ifdef NKRO_ENABLE
  209. if (keyboard_protocol && keyboard_nkro) {
  210. uint8_t i = 0;
  211. for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
  212. ;
  213. return i<<3 | biton(keyboard_report->nkro.bits[i]);
  214. }
  215. #endif
  216. #ifdef USB_6KRO_ENABLE
  217. uint8_t i = cb_head;
  218. do {
  219. if (keyboard_report->keys[i] != 0) {
  220. break;
  221. }
  222. i = RO_INC(i);
  223. } while (i != cb_tail);
  224. return keyboard_report->keys[i];
  225. #else
  226. return keyboard_report->keys[0];
  227. #endif
  228. }
  229. /* local functions */
  230. static inline void add_key_byte(uint8_t code)
  231. {
  232. #ifdef USB_6KRO_ENABLE
  233. int8_t i = cb_head;
  234. int8_t empty = -1;
  235. if (cb_count) {
  236. do {
  237. if (keyboard_report->keys[i] == code) {
  238. return;
  239. }
  240. if (empty == -1 && keyboard_report->keys[i] == 0) {
  241. empty = i;
  242. }
  243. i = RO_INC(i);
  244. } while (i != cb_tail);
  245. if (i == cb_tail) {
  246. if (cb_tail == cb_head) {
  247. // buffer is full
  248. if (empty == -1) {
  249. // pop head when has no empty space
  250. cb_head = RO_INC(cb_head);
  251. cb_count--;
  252. }
  253. else {
  254. // left shift when has empty space
  255. uint8_t offset = 1;
  256. i = RO_INC(empty);
  257. do {
  258. if (keyboard_report->keys[i] != 0) {
  259. keyboard_report->keys[empty] = keyboard_report->keys[i];
  260. keyboard_report->keys[i] = 0;
  261. empty = RO_INC(empty);
  262. }
  263. else {
  264. offset++;
  265. }
  266. i = RO_INC(i);
  267. } while (i != cb_tail);
  268. cb_tail = RO_SUB(cb_tail, offset);
  269. }
  270. }
  271. }
  272. }
  273. // add to tail
  274. keyboard_report->keys[cb_tail] = code;
  275. cb_tail = RO_INC(cb_tail);
  276. cb_count++;
  277. #else
  278. int8_t i = 0;
  279. int8_t empty = -1;
  280. for (; i < KEYBOARD_REPORT_KEYS; i++) {
  281. if (keyboard_report->keys[i] == code) {
  282. break;
  283. }
  284. if (empty == -1 && keyboard_report->keys[i] == 0) {
  285. empty = i;
  286. }
  287. }
  288. if (i == KEYBOARD_REPORT_KEYS) {
  289. if (empty != -1) {
  290. keyboard_report->keys[empty] = code;
  291. }
  292. }
  293. #endif
  294. }
  295. static inline void del_key_byte(uint8_t code)
  296. {
  297. #ifdef USB_6KRO_ENABLE
  298. uint8_t i = cb_head;
  299. if (cb_count) {
  300. do {
  301. if (keyboard_report->keys[i] == code) {
  302. keyboard_report->keys[i] = 0;
  303. cb_count--;
  304. if (cb_count == 0) {
  305. // reset head and tail
  306. cb_tail = cb_head = 0;
  307. }
  308. if (i == RO_DEC(cb_tail)) {
  309. // left shift when next to tail
  310. do {
  311. cb_tail = RO_DEC(cb_tail);
  312. if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
  313. break;
  314. }
  315. } while (cb_tail != cb_head);
  316. }
  317. break;
  318. }
  319. i = RO_INC(i);
  320. } while (i != cb_tail);
  321. }
  322. #else
  323. for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
  324. if (keyboard_report->keys[i] == code) {
  325. keyboard_report->keys[i] = 0;
  326. }
  327. }
  328. #endif
  329. }
  330. #ifdef NKRO_ENABLE
  331. static inline void add_key_bit(uint8_t code)
  332. {
  333. if ((code>>3) < KEYBOARD_REPORT_BITS) {
  334. keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
  335. } else {
  336. dprintf("add_key_bit: can't add: %02X\n", code);
  337. }
  338. }
  339. static inline void del_key_bit(uint8_t code)
  340. {
  341. if ((code>>3) < KEYBOARD_REPORT_BITS) {
  342. keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
  343. } else {
  344. dprintf("del_key_bit: can't del: %02X\n", code);
  345. }
  346. }
  347. #endif