]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/report.c
4b25f4428c17252c87ed8e80ef3a1e67fcc93ce0
[qmk_firmware.git] / tmk_core / common / report.c
1 /* Copyright 2017 Fred Sundvik
2  *
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  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include "report.h"
18 #include "host.h"
19 #include "keycode_config.h"
20 #include "debug.h"
21 #include "util.h"
22
23 uint8_t has_anykey(report_keyboard_t* keyboard_report)
24 {
25     uint8_t cnt = 0;
26     for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
27         if (keyboard_report->raw[i])
28             cnt++;
29     }
30     return cnt;
31 }
32
33 uint8_t get_first_key(report_keyboard_t* keyboard_report)
34 {
35 #ifdef NKRO_ENABLE
36     if (keyboard_protocol && keymap_config.nkro) {
37         uint8_t i = 0;
38         for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
39             ;
40         return i<<3 | biton(keyboard_report->nkro.bits[i]);
41     }
42 #endif
43 #ifdef USB_6KRO_ENABLE
44     uint8_t i = cb_head;
45     do {
46         if (keyboard_report->keys[i] != 0) {
47             break;
48         }
49         i = RO_INC(i);
50     } while (i != cb_tail);
51     return keyboard_report->keys[i];
52 #else
53     return keyboard_report->keys[0];
54 #endif
55 }
56
57 void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code)
58 {
59 #ifdef USB_6KRO_ENABLE
60     int8_t i = cb_head;
61     int8_t empty = -1;
62     if (cb_count) {
63         do {
64             if (keyboard_report->keys[i] == code) {
65                 return;
66             }
67             if (empty == -1 && keyboard_report->keys[i] == 0) {
68                 empty = i;
69             }
70             i = RO_INC(i);
71         } while (i != cb_tail);
72         if (i == cb_tail) {
73             if (cb_tail == cb_head) {
74                 // buffer is full
75                 if (empty == -1) {
76                     // pop head when has no empty space
77                     cb_head = RO_INC(cb_head);
78                     cb_count--;
79                 }
80                 else {
81                     // left shift when has empty space
82                     uint8_t offset = 1;
83                     i = RO_INC(empty);
84                     do {
85                         if (keyboard_report->keys[i] != 0) {
86                             keyboard_report->keys[empty] = keyboard_report->keys[i];
87                             keyboard_report->keys[i] = 0;
88                             empty = RO_INC(empty);
89                         }
90                         else {
91                             offset++;
92                         }
93                         i = RO_INC(i);
94                     } while (i != cb_tail);
95                     cb_tail = RO_SUB(cb_tail, offset);
96                 }
97             }
98         }
99     }
100     // add to tail
101     keyboard_report->keys[cb_tail] = code;
102     cb_tail = RO_INC(cb_tail);
103     cb_count++;
104 #else
105     int8_t i = 0;
106     int8_t empty = -1;
107     for (; i < KEYBOARD_REPORT_KEYS; i++) {
108         if (keyboard_report->keys[i] == code) {
109             break;
110         }
111         if (empty == -1 && keyboard_report->keys[i] == 0) {
112             empty = i;
113         }
114     }
115     if (i == KEYBOARD_REPORT_KEYS) {
116         if (empty != -1) {
117             keyboard_report->keys[empty] = code;
118         }
119     }
120 #endif
121 }
122
123 void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code)
124 {
125 #ifdef USB_6KRO_ENABLE
126     uint8_t i = cb_head;
127     if (cb_count) {
128         do {
129             if (keyboard_report->keys[i] == code) {
130                 keyboard_report->keys[i] = 0;
131                 cb_count--;
132                 if (cb_count == 0) {
133                     // reset head and tail
134                     cb_tail = cb_head = 0;
135                 }
136                 if (i == RO_DEC(cb_tail)) {
137                     // left shift when next to tail
138                     do {
139                         cb_tail = RO_DEC(cb_tail);
140                         if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
141                             break;
142                         }
143                     } while (cb_tail != cb_head);
144                 }
145                 break;
146             }
147             i = RO_INC(i);
148         } while (i != cb_tail);
149     }
150 #else
151     for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
152         if (keyboard_report->keys[i] == code) {
153             keyboard_report->keys[i] = 0;
154         }
155     }
156 #endif
157 }
158
159 #ifdef NKRO_ENABLE
160 void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code)
161 {
162     if ((code>>3) < KEYBOARD_REPORT_BITS) {
163         keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
164     } else {
165         dprintf("add_key_bit: can't add: %02X\n", code);
166     }
167 }
168
169 void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code)
170 {
171     if ((code>>3) < KEYBOARD_REPORT_BITS) {
172         keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
173     } else {
174         dprintf("del_key_bit: can't del: %02X\n", code);
175     }
176 }
177 #endif
178
179 void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key)
180 {
181 #ifdef NKRO_ENABLE
182     if (keyboard_protocol && keymap_config.nkro) {
183         add_key_bit(keyboard_report, key);
184         return;
185     }
186 #endif
187     add_key_byte(keyboard_report, key);
188 }
189
190 void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key)
191 {
192 #ifdef NKRO_ENABLE
193     if (keyboard_protocol && keymap_config.nkro) {
194         del_key_bit(keyboard_report, key);
195         return;
196     }
197 #endif
198     del_key_byte(keyboard_report, key);
199 }
200
201 void clear_keys_from_report(report_keyboard_t* keyboard_report)
202 {
203     // not clear mods
204     for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
205         keyboard_report->raw[i] = 0;
206     }
207 }