action_util.c 10 KB

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