]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/host.c
Initial version of new code for layer switch is added.
[tmk_firmware.git] / common / host.c
1 /*
2 Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stdint.h>
19 #include <avr/interrupt.h>
20 #include "usb_keycodes.h"
21 #include "host.h"
22 #include "util.h"
23 #include "debug.h"
24
25
26 #ifdef NKRO_ENABLE
27 bool keyboard_nkro = false;
28 #endif
29
30 static host_driver_t *driver;
31 static report_keyboard_t report0;
32 static report_keyboard_t report1;
33 report_keyboard_t *keyboard_report = &report0;
34 report_keyboard_t *keyboard_report_prev = &report1;
35
36
37 static inline void add_key_byte(uint8_t code);
38 static inline void del_key_byte(uint8_t code);
39 static inline void add_key_bit(uint8_t code);
40 static inline void del_key_bit(uint8_t code);
41
42
43 void host_set_driver(host_driver_t *d)
44 {
45     driver = d;
46 }
47
48 host_driver_t *host_get_driver(void)
49 {
50     return driver;
51 }
52
53 uint8_t host_keyboard_leds(void)
54 {
55     if (!driver) return 0;
56     return (*driver->keyboard_leds)();
57 }
58
59 /* new interface */
60 void host_register_key(uint8_t key)
61 {
62     host_add_key(key);
63     host_send_keyboard_report();
64 }
65
66 void host_unregister_key(uint8_t key)
67 {
68     host_del_key(key);
69     host_send_keyboard_report();
70 }
71
72 /* keyboard report operations */
73 void host_add_key(uint8_t key)
74 {
75 #ifdef NKRO_ENABLE
76     if (keyboard_nkro) {
77         add_key_bit(key);
78         return;
79     }
80 #endif
81     add_key_byte(key);
82 }
83
84 void host_del_key(uint8_t key)
85 {
86 #ifdef NKRO_ENABLE
87     if (keyboard_nkro) {
88         del_key_bit(key);
89         return;
90     }
91 #endif
92     del_key_byte(key);
93 }
94
95 void host_add_mod_bit(uint8_t mod)
96 {
97     keyboard_report->mods |= mod;
98 }
99
100 void host_del_mod_bit(uint8_t mod)
101 {
102     keyboard_report->mods &= ~mod;
103 }
104
105 void host_set_mods(uint8_t mods)
106 {
107     keyboard_report->mods = mods;
108 }
109
110 void host_add_code(uint8_t code)
111 {
112     if (IS_MOD(code)) {
113         host_add_mod_bit(MOD_BIT(code));
114     } else {
115         host_add_key(code);
116     }
117 }
118
119 void host_del_code(uint8_t code)
120 {
121     if (IS_MOD(code)) {
122         host_del_mod_bit(MOD_BIT(code));
123     } else {
124         host_del_key(code);
125     }
126 }
127
128 void host_swap_keyboard_report(void)
129 {
130     uint8_t sreg = SREG;
131     cli();
132     report_keyboard_t *tmp = keyboard_report_prev;
133     keyboard_report_prev = keyboard_report;
134     keyboard_report = tmp;
135     SREG = sreg;
136 }
137
138 void host_clear_keyboard_report(void)
139 {
140     keyboard_report->mods = 0;
141     for (int8_t i = 0; i < REPORT_KEYS; i++) {
142         keyboard_report->keys[i] = 0;
143     }
144 }
145
146 uint8_t host_has_anykey(void)
147 {
148     uint8_t cnt = 0;
149     for (int i = 0; i < REPORT_KEYS; i++) {
150         if (keyboard_report->keys[i])
151             cnt++;
152     }
153     return cnt;
154 }
155
156 uint8_t host_get_first_key(void)
157 {
158 #ifdef NKRO_ENABLE
159     if (keyboard_nkro) {
160         uint8_t i = 0;
161         for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++)
162             ;
163         return i<<3 | biton(keyboard_report->keys[i]);
164     }
165 #endif
166     return keyboard_report->keys[0];
167 }
168
169
170 void host_send_keyboard_report(void)
171 {
172     if (!driver) return;
173     (*driver->send_keyboard)(keyboard_report);
174
175     if (debug_keyboard) {
176         print("keys: ");
177         for (int i = 0; i < REPORT_KEYS; i++) {
178             phex(keyboard_report->keys[i]); print(" ");
179         }
180         print(" mods: "); phex(keyboard_report->mods); print("\n");
181     }
182 }
183
184 void host_mouse_send(report_mouse_t *report)
185 {
186     if (!driver) return;
187     (*driver->send_mouse)(report);
188 }
189
190 void host_system_send(uint16_t data)
191 {
192     static uint16_t last_data = 0;
193     if (data == last_data) return;
194     last_data = data;
195
196     if (!driver) return;
197     (*driver->send_system)(data);
198 }
199
200 void host_consumer_send(uint16_t data)
201 {
202     static uint16_t last_data = 0;
203     if (data == last_data) return;
204     last_data = data;
205
206     if (!driver) return;
207     (*driver->send_consumer)(data);
208 }
209
210
211 static inline void add_key_byte(uint8_t code)
212 {
213     // TODO: fix ugly code
214     int8_t i = 0;
215     int8_t empty = -1;
216     for (; i < REPORT_KEYS; i++) {
217         if (keyboard_report_prev->keys[i] == code) {
218             keyboard_report->keys[i] = code;
219             break;
220         }
221         if (empty == -1 &&
222                 keyboard_report_prev->keys[i] == 0 &&
223                 keyboard_report->keys[i] == 0) {
224             empty = i;
225         }
226     }
227     if (i == REPORT_KEYS) {
228         if (empty != -1) {
229             keyboard_report->keys[empty] = code;
230         }
231     }
232 }
233
234 static inline void del_key_byte(uint8_t code)
235 {
236     int i = 0;
237     for (; i < REPORT_KEYS; i++) {
238         if (keyboard_report->keys[i] == code) {
239             keyboard_report->keys[i] = 0;
240         }
241     }
242 }
243
244 static inline void add_key_bit(uint8_t code)
245 {
246     if ((code>>3) < REPORT_KEYS) {
247         keyboard_report->keys[code>>3] |= 1<<(code&7);
248     } else {
249         debug("add_key_bit: can't add: "); phex(code); debug("\n");
250     }
251 }
252
253 static inline void del_key_bit(uint8_t code)
254 {
255     if ((code>>3) < REPORT_KEYS) {
256         keyboard_report->keys[code>>3] &= ~(1<<(code&7));
257     } else {
258         debug("del_key_bit: can't del: "); phex(code); debug("\n");
259     }
260 }