Lines 109-135
Link Here
|
109 |
|
109 |
|
110 |
#define UKBD_EMULATE_ATSCANCODE 1 |
110 |
#define UKBD_EMULATE_ATSCANCODE 1 |
111 |
#define UKBD_DRIVER_NAME "ukbd" |
111 |
#define UKBD_DRIVER_NAME "ukbd" |
112 |
#define UKBD_NMOD 8 /* units */ |
112 |
#define UKBD_NKEYCODE 256 /* units */ |
113 |
#define UKBD_NKEYCODE 6 /* units */ |
113 |
#define UKBD_IN_BUF_SIZE (4 * UKBD_NKEYCODE) /* scancodes */ |
114 |
#define UKBD_IN_BUF_SIZE (2*(UKBD_NMOD + (2*UKBD_NKEYCODE))) /* bytes */ |
114 |
#define UKBD_IN_BUF_FULL ((UKBD_IN_BUF_SIZE / 2) - 1) /* scancodes */ |
115 |
#define UKBD_IN_BUF_FULL ((UKBD_IN_BUF_SIZE / 2) - 1) /* bytes */ |
|
|
116 |
#define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ |
115 |
#define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ |
117 |
#define UKBD_BUFFER_SIZE 64 /* bytes */ |
116 |
#define UKBD_BUFFER_SIZE 64 /* bytes */ |
|
|
117 |
#define UKBD_KEY_PRESSED(map, key) \ |
118 |
((map)[(key) / 64] & (1ULL << ((key) % 64))) |
118 |
|
119 |
|
|
|
120 |
#define MOD_EJECT 0x01 |
121 |
#define MOD_FN 0x02 |
122 |
|
119 |
struct ukbd_data { |
123 |
struct ukbd_data { |
120 |
uint16_t modifiers; |
124 |
uint64_t bitmap[howmany(UKBD_NKEYCODE, 64)]; |
121 |
#define MOD_CONTROL_L 0x01 |
|
|
122 |
#define MOD_CONTROL_R 0x10 |
123 |
#define MOD_SHIFT_L 0x02 |
124 |
#define MOD_SHIFT_R 0x20 |
125 |
#define MOD_ALT_L 0x04 |
126 |
#define MOD_ALT_R 0x40 |
127 |
#define MOD_WIN_L 0x08 |
128 |
#define MOD_WIN_R 0x80 |
129 |
/* internal */ |
130 |
#define MOD_EJECT 0x0100 |
131 |
#define MOD_FN 0x0200 |
132 |
uint8_t keycode[UKBD_NKEYCODE]; |
133 |
}; |
125 |
}; |
134 |
|
126 |
|
135 |
enum { |
127 |
enum { |
Lines 144-160
Link Here
|
144 |
keymap_t sc_keymap; |
136 |
keymap_t sc_keymap; |
145 |
accentmap_t sc_accmap; |
137 |
accentmap_t sc_accmap; |
146 |
fkeytab_t sc_fkeymap[UKBD_NFKEY]; |
138 |
fkeytab_t sc_fkeymap[UKBD_NFKEY]; |
|
|
139 |
uint64_t sc_loc_key_valid[howmany(UKBD_NKEYCODE, 64)]; |
147 |
struct hid_location sc_loc_apple_eject; |
140 |
struct hid_location sc_loc_apple_eject; |
148 |
struct hid_location sc_loc_apple_fn; |
141 |
struct hid_location sc_loc_apple_fn; |
149 |
struct hid_location sc_loc_ctrl_l; |
142 |
struct hid_location sc_loc_key[UKBD_NKEYCODE]; |
150 |
struct hid_location sc_loc_ctrl_r; |
|
|
151 |
struct hid_location sc_loc_shift_l; |
152 |
struct hid_location sc_loc_shift_r; |
153 |
struct hid_location sc_loc_alt_l; |
154 |
struct hid_location sc_loc_alt_r; |
155 |
struct hid_location sc_loc_win_l; |
156 |
struct hid_location sc_loc_win_r; |
157 |
struct hid_location sc_loc_events; |
158 |
struct hid_location sc_loc_numlock; |
143 |
struct hid_location sc_loc_numlock; |
159 |
struct hid_location sc_loc_capslock; |
144 |
struct hid_location sc_loc_capslock; |
160 |
struct hid_location sc_loc_scrolllock; |
145 |
struct hid_location sc_loc_scrolllock; |
Lines 172-179
Link Here
|
172 |
|
157 |
|
173 |
sbintime_t sc_co_basetime; |
158 |
sbintime_t sc_co_basetime; |
174 |
int sc_delay; |
159 |
int sc_delay; |
175 |
uint32_t sc_ntime[UKBD_NKEYCODE]; |
160 |
uint32_t sc_repeat_time; |
176 |
uint32_t sc_otime[UKBD_NKEYCODE]; |
|
|
177 |
uint32_t sc_input[UKBD_IN_BUF_SIZE]; /* input buffer */ |
161 |
uint32_t sc_input[UKBD_IN_BUF_SIZE]; /* input buffer */ |
178 |
uint32_t sc_time_ms; |
162 |
uint32_t sc_time_ms; |
179 |
uint32_t sc_composed_char; /* composed char code, if non-zero */ |
163 |
uint32_t sc_composed_char; /* composed char code, if non-zero */ |
Lines 191-205
Link Here
|
191 |
#define UKBD_FLAG_APPLE_EJECT 0x00000040 |
175 |
#define UKBD_FLAG_APPLE_EJECT 0x00000040 |
192 |
#define UKBD_FLAG_APPLE_FN 0x00000080 |
176 |
#define UKBD_FLAG_APPLE_FN 0x00000080 |
193 |
#define UKBD_FLAG_APPLE_SWAP 0x00000100 |
177 |
#define UKBD_FLAG_APPLE_SWAP 0x00000100 |
194 |
#define UKBD_FLAG_CTRL_L 0x00000400 |
|
|
195 |
#define UKBD_FLAG_CTRL_R 0x00000800 |
196 |
#define UKBD_FLAG_SHIFT_L 0x00001000 |
197 |
#define UKBD_FLAG_SHIFT_R 0x00002000 |
198 |
#define UKBD_FLAG_ALT_L 0x00004000 |
199 |
#define UKBD_FLAG_ALT_R 0x00008000 |
200 |
#define UKBD_FLAG_WIN_L 0x00010000 |
201 |
#define UKBD_FLAG_WIN_R 0x00020000 |
202 |
#define UKBD_FLAG_EVENTS 0x00040000 |
203 |
#define UKBD_FLAG_NUMLOCK 0x00080000 |
178 |
#define UKBD_FLAG_NUMLOCK 0x00080000 |
204 |
#define UKBD_FLAG_CAPSLOCK 0x00100000 |
179 |
#define UKBD_FLAG_CAPSLOCK 0x00100000 |
205 |
#define UKBD_FLAG_SCROLLLOCK 0x00200000 |
180 |
#define UKBD_FLAG_SCROLLLOCK 0x00200000 |
Lines 214-220
Link Here
|
214 |
uint16_t sc_inputs; |
189 |
uint16_t sc_inputs; |
215 |
uint16_t sc_inputhead; |
190 |
uint16_t sc_inputhead; |
216 |
uint16_t sc_inputtail; |
191 |
uint16_t sc_inputtail; |
217 |
uint16_t sc_modifiers; |
|
|
218 |
|
192 |
|
219 |
uint8_t sc_leds; /* store for async led requests */ |
193 |
uint8_t sc_leds; /* store for async led requests */ |
220 |
uint8_t sc_iface_index; |
194 |
uint8_t sc_iface_index; |
Lines 221-244
Link Here
|
221 |
uint8_t sc_iface_no; |
195 |
uint8_t sc_iface_no; |
222 |
uint8_t sc_id_apple_eject; |
196 |
uint8_t sc_id_apple_eject; |
223 |
uint8_t sc_id_apple_fn; |
197 |
uint8_t sc_id_apple_fn; |
224 |
uint8_t sc_id_ctrl_l; |
198 |
uint8_t sc_id_loc_key[UKBD_NKEYCODE]; |
225 |
uint8_t sc_id_ctrl_r; |
|
|
226 |
uint8_t sc_id_shift_l; |
227 |
uint8_t sc_id_shift_r; |
228 |
uint8_t sc_id_alt_l; |
229 |
uint8_t sc_id_alt_r; |
230 |
uint8_t sc_id_win_l; |
231 |
uint8_t sc_id_win_r; |
232 |
uint8_t sc_id_event; |
233 |
uint8_t sc_id_numlock; |
199 |
uint8_t sc_id_numlock; |
234 |
uint8_t sc_id_capslock; |
200 |
uint8_t sc_id_capslock; |
235 |
uint8_t sc_id_scrolllock; |
201 |
uint8_t sc_id_scrolllock; |
236 |
uint8_t sc_id_events; |
|
|
237 |
uint8_t sc_kbd_id; |
202 |
uint8_t sc_kbd_id; |
|
|
203 |
uint8_t sc_repeat_key; |
238 |
|
204 |
|
239 |
uint8_t sc_buffer[UKBD_BUFFER_SIZE]; |
205 |
uint8_t sc_buffer[UKBD_BUFFER_SIZE]; |
240 |
}; |
206 |
}; |
241 |
|
207 |
|
|
|
208 |
#define KEY_NONE 0x00 |
242 |
#define KEY_ERROR 0x01 |
209 |
#define KEY_ERROR 0x01 |
243 |
|
210 |
|
244 |
#define KEY_PRESS 0 |
211 |
#define KEY_PRESS 0 |
Lines 259-280
Link Here
|
259 |
#define UKBD_UNLOCK() USB_MTX_UNLOCK(&Giant) |
226 |
#define UKBD_UNLOCK() USB_MTX_UNLOCK(&Giant) |
260 |
#define UKBD_LOCK_ASSERT() USB_MTX_ASSERT(&Giant, MA_OWNED) |
227 |
#define UKBD_LOCK_ASSERT() USB_MTX_ASSERT(&Giant, MA_OWNED) |
261 |
|
228 |
|
262 |
struct ukbd_mods { |
229 |
#define NN 0 /* no translation */ |
263 |
uint32_t mask, key; |
|
|
264 |
}; |
265 |
|
230 |
|
266 |
static const struct ukbd_mods ukbd_mods[UKBD_NMOD] = { |
|
|
267 |
{MOD_CONTROL_L, 0xe0}, |
268 |
{MOD_CONTROL_R, 0xe4}, |
269 |
{MOD_SHIFT_L, 0xe1}, |
270 |
{MOD_SHIFT_R, 0xe5}, |
271 |
{MOD_ALT_L, 0xe2}, |
272 |
{MOD_ALT_R, 0xe6}, |
273 |
{MOD_WIN_L, 0xe3}, |
274 |
{MOD_WIN_R, 0xe7}, |
275 |
}; |
276 |
|
277 |
#define NN 0 /* no translation */ |
278 |
/* |
231 |
/* |
279 |
* Translate USB keycodes to AT keyboard scancodes. |
232 |
* Translate USB keycodes to AT keyboard scancodes. |
280 |
*/ |
233 |
*/ |
Lines 347-354
Link Here
|
347 |
static void ukbd_set_leds(struct ukbd_softc *, uint8_t); |
300 |
static void ukbd_set_leds(struct ukbd_softc *, uint8_t); |
348 |
static int ukbd_set_typematic(keyboard_t *, int); |
301 |
static int ukbd_set_typematic(keyboard_t *, int); |
349 |
#ifdef UKBD_EMULATE_ATSCANCODE |
302 |
#ifdef UKBD_EMULATE_ATSCANCODE |
350 |
static uint32_t ukbd_atkeycode(int, int); |
303 |
static uint32_t ukbd_atkeycode(int, const uint64_t *); |
351 |
static int ukbd_key2scan(struct ukbd_softc *, int, int, int); |
304 |
static int ukbd_key2scan(struct ukbd_softc *, int, const uint64_t *, int); |
352 |
#endif |
305 |
#endif |
353 |
static uint32_t ukbd_read_char(keyboard_t *, int); |
306 |
static uint32_t ukbd_read_char(keyboard_t *, int); |
354 |
static void ukbd_clear_state(keyboard_t *); |
307 |
static void ukbd_clear_state(keyboard_t *); |
Lines 371-386
Link Here
|
371 |
}; |
324 |
}; |
372 |
#endif |
325 |
#endif |
373 |
|
326 |
|
374 |
static uint8_t |
327 |
static bool |
375 |
ukbd_any_key_pressed(struct ukbd_softc *sc) |
328 |
ukbd_any_key_pressed(struct ukbd_softc *sc) |
376 |
{ |
329 |
{ |
377 |
uint8_t i; |
330 |
bool ret = false; |
378 |
uint8_t j; |
331 |
unsigned i; |
379 |
|
332 |
|
380 |
for (j = i = 0; i < UKBD_NKEYCODE; i++) |
333 |
for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) |
381 |
j |= sc->sc_odata.keycode[i]; |
334 |
ret |= (sc->sc_odata.bitmap[i] != 0); |
|
|
335 |
return (ret); |
336 |
} |
382 |
|
337 |
|
383 |
return (j ? 1 : 0); |
338 |
static bool |
|
|
339 |
ukbd_any_key_valid(struct ukbd_softc *sc) |
340 |
{ |
341 |
bool ret = false; |
342 |
unsigned i; |
343 |
|
344 |
for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) |
345 |
ret |= (sc->sc_loc_key_valid[i] != 0); |
346 |
return (ret); |
384 |
} |
347 |
} |
385 |
|
348 |
|
386 |
static void |
349 |
static void |
Lines 522-620
Link Here
|
522 |
static void |
485 |
static void |
523 |
ukbd_interrupt(struct ukbd_softc *sc) |
486 |
ukbd_interrupt(struct ukbd_softc *sc) |
524 |
{ |
487 |
{ |
525 |
uint32_t n_mod; |
488 |
const uint32_t now = sc->sc_time_ms; |
526 |
uint32_t o_mod; |
489 |
unsigned key; |
527 |
uint32_t now = sc->sc_time_ms; |
490 |
bool old_keys; |
528 |
int32_t dtime; |
|
|
529 |
uint8_t key; |
530 |
uint8_t i; |
531 |
uint8_t j; |
532 |
|
491 |
|
533 |
UKBD_LOCK_ASSERT(); |
492 |
UKBD_LOCK_ASSERT(); |
534 |
|
493 |
|
535 |
if (sc->sc_ndata.keycode[0] == KEY_ERROR) |
494 |
old_keys = ukbd_any_key_pressed(sc); |
536 |
return; |
|
|
537 |
|
495 |
|
538 |
n_mod = sc->sc_ndata.modifiers; |
496 |
/* Check for key changes */ |
539 |
o_mod = sc->sc_odata.modifiers; |
497 |
for (key = 0; key < UKBD_NKEYCODE; key++) { |
540 |
if (n_mod != o_mod) { |
498 |
const uint64_t delta = |
541 |
for (i = 0; i < UKBD_NMOD; i++) { |
499 |
sc->sc_odata.bitmap[key / 64] ^ |
542 |
if ((n_mod & ukbd_mods[i].mask) != |
500 |
sc->sc_ndata.bitmap[key / 64]; |
543 |
(o_mod & ukbd_mods[i].mask)) { |
501 |
const uint64_t mask = |
544 |
ukbd_put_key(sc, ukbd_mods[i].key | |
502 |
1ULL << (key % 64); |
545 |
((n_mod & ukbd_mods[i].mask) ? |
|
|
546 |
KEY_PRESS : KEY_RELEASE)); |
547 |
} |
548 |
} |
549 |
} |
550 |
/* Check for released keys. */ |
551 |
for (i = 0; i < UKBD_NKEYCODE; i++) { |
552 |
key = sc->sc_odata.keycode[i]; |
553 |
if (key == 0) { |
554 |
continue; |
555 |
} |
556 |
for (j = 0; j < UKBD_NKEYCODE; j++) { |
557 |
if (sc->sc_ndata.keycode[j] == 0) { |
558 |
continue; |
559 |
} |
560 |
if (key == sc->sc_ndata.keycode[j]) { |
561 |
goto rfound; |
562 |
} |
563 |
} |
564 |
ukbd_put_key(sc, key | KEY_RELEASE); |
565 |
rfound: ; |
566 |
} |
567 |
|
503 |
|
568 |
/* Check for pressed keys. */ |
504 |
if (mask == 1 && delta == 0) { |
569 |
for (i = 0; i < UKBD_NKEYCODE; i++) { |
505 |
key += 63; |
570 |
key = sc->sc_ndata.keycode[i]; |
506 |
continue; /* skip empty areas */ |
571 |
if (key == 0) { |
507 |
} else if (delta & mask) { |
572 |
continue; |
508 |
if (sc->sc_odata.bitmap[key / 64] & mask) { |
573 |
} |
509 |
ukbd_put_key(sc, key | KEY_RELEASE); |
574 |
sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay1; |
|
|
575 |
for (j = 0; j < UKBD_NKEYCODE; j++) { |
576 |
if (sc->sc_odata.keycode[j] == 0) { |
577 |
continue; |
578 |
} |
579 |
if (key == sc->sc_odata.keycode[j]) { |
580 |
|
510 |
|
581 |
/* key is still pressed */ |
511 |
/* clear repeating key, if any */ |
|
|
512 |
if (sc->sc_repeat_key == key) |
513 |
sc->sc_repeat_key = 0; |
514 |
} else { |
515 |
ukbd_put_key(sc, key | KEY_PRESS); |
582 |
|
516 |
|
583 |
sc->sc_ntime[i] = sc->sc_otime[j]; |
517 |
/* set repeat time for last key */ |
584 |
dtime = (sc->sc_otime[j] - now); |
518 |
sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; |
585 |
|
519 |
sc->sc_repeat_key = key; |
586 |
if (dtime > 0) { |
|
|
587 |
/* time has not elapsed */ |
588 |
goto pfound; |
589 |
} |
590 |
sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay2; |
591 |
break; |
592 |
} |
520 |
} |
593 |
} |
521 |
} |
594 |
if (j == UKBD_NKEYCODE) { |
522 |
} |
595 |
/* New key - set initial delay and [re]start timer */ |
|
|
596 |
sc->sc_co_basetime = sbinuptime(); |
597 |
sc->sc_delay = sc->sc_kbd.kb_delay1; |
598 |
ukbd_start_timer(sc); |
599 |
} |
600 |
ukbd_put_key(sc, key | KEY_PRESS); |
601 |
|
523 |
|
602 |
/* |
524 |
/* synchronize old data with new data */ |
603 |
* If any other key is presently down, force its repeat to be |
525 |
sc->sc_odata = sc->sc_ndata; |
604 |
* well in the future (100s). This makes the last key to be |
526 |
|
605 |
* pressed do the autorepeat. |
527 |
/* check if last key is still pressed */ |
606 |
*/ |
528 |
if (sc->sc_repeat_key != 0) { |
607 |
for (j = 0; j != UKBD_NKEYCODE; j++) { |
529 |
const int32_t dtime = (sc->sc_repeat_time - now); |
608 |
if (j != i) |
530 |
|
609 |
sc->sc_ntime[j] = now + (100 * 1000); |
531 |
/* check if time has elapsed */ |
|
|
532 |
if (dtime < 0) { |
533 |
ukbd_put_key(sc, sc->sc_repeat_key | KEY_PRESS); |
534 |
sc->sc_repeat_time = now + sc->sc_kbd.kb_delay2; |
610 |
} |
535 |
} |
611 |
pfound: ; |
|
|
612 |
} |
536 |
} |
613 |
|
537 |
|
614 |
sc->sc_odata = sc->sc_ndata; |
538 |
/* check for first new key and set initial delay and [re]start timer */ |
|
|
539 |
if (old_keys == false && ukbd_any_key_pressed(sc) == true) { |
540 |
sc->sc_co_basetime = sbinuptime(); |
541 |
sc->sc_delay = sc->sc_kbd.kb_delay1; |
542 |
ukbd_start_timer(sc); |
543 |
} |
615 |
|
544 |
|
616 |
memcpy(sc->sc_otime, sc->sc_ntime, sizeof(sc->sc_otime)); |
545 |
/* wakeup keyboard system */ |
617 |
|
|
|
618 |
ukbd_event_keyinput(sc); |
546 |
ukbd_event_keyinput(sc); |
619 |
} |
547 |
} |
620 |
|
548 |
|
Lines 664-671
Link Here
|
664 |
} |
592 |
} |
665 |
} |
593 |
} |
666 |
|
594 |
|
667 |
static uint8_t |
595 |
static uint32_t |
668 |
ukbd_apple_fn(uint8_t keycode) { |
596 |
ukbd_apple_fn(uint32_t keycode) |
|
|
597 |
{ |
669 |
switch (keycode) { |
598 |
switch (keycode) { |
670 |
case 0x28: return 0x49; /* RETURN -> INSERT */ |
599 |
case 0x28: return 0x49; /* RETURN -> INSERT */ |
671 |
case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ |
600 |
case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ |
Lines 677-684
Link Here
|
677 |
} |
606 |
} |
678 |
} |
607 |
} |
679 |
|
608 |
|
680 |
static uint8_t |
609 |
static uint32_t |
681 |
ukbd_apple_swap(uint8_t keycode) { |
610 |
ukbd_apple_swap(uint32_t keycode) |
|
|
611 |
{ |
682 |
switch (keycode) { |
612 |
switch (keycode) { |
683 |
case 0x35: return 0x64; |
613 |
case 0x35: return 0x64; |
684 |
case 0x64: return 0x35; |
614 |
case 0x64: return 0x35; |
Lines 691-699
Link Here
|
691 |
{ |
621 |
{ |
692 |
struct ukbd_softc *sc = usbd_xfer_softc(xfer); |
622 |
struct ukbd_softc *sc = usbd_xfer_softc(xfer); |
693 |
struct usb_page_cache *pc; |
623 |
struct usb_page_cache *pc; |
694 |
uint8_t i; |
624 |
uint32_t i; |
695 |
uint8_t offset; |
|
|
696 |
uint8_t id; |
625 |
uint8_t id; |
|
|
626 |
uint8_t modifiers; |
627 |
int offset; |
697 |
int len; |
628 |
int len; |
698 |
|
629 |
|
699 |
UKBD_LOCK_ASSERT(); |
630 |
UKBD_LOCK_ASSERT(); |
Lines 733-849
Link Here
|
733 |
/* clear temporary storage */ |
664 |
/* clear temporary storage */ |
734 |
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); |
665 |
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); |
735 |
|
666 |
|
|
|
667 |
/* clear modifiers */ |
668 |
modifiers = 0; |
669 |
|
736 |
/* scan through HID data */ |
670 |
/* scan through HID data */ |
737 |
if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && |
671 |
if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && |
738 |
(id == sc->sc_id_apple_eject)) { |
672 |
(id == sc->sc_id_apple_eject)) { |
739 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) |
673 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) |
740 |
sc->sc_modifiers |= MOD_EJECT; |
674 |
modifiers |= MOD_EJECT; |
741 |
else |
|
|
742 |
sc->sc_modifiers &= ~MOD_EJECT; |
743 |
} |
675 |
} |
744 |
if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && |
676 |
if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && |
745 |
(id == sc->sc_id_apple_fn)) { |
677 |
(id == sc->sc_id_apple_fn)) { |
746 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) |
678 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) |
747 |
sc->sc_modifiers |= MOD_FN; |
679 |
modifiers |= MOD_FN; |
748 |
else |
|
|
749 |
sc->sc_modifiers &= ~MOD_FN; |
750 |
} |
680 |
} |
751 |
if ((sc->sc_flags & UKBD_FLAG_CTRL_L) && |
|
|
752 |
(id == sc->sc_id_ctrl_l)) { |
753 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_ctrl_l)) |
754 |
sc-> sc_modifiers |= MOD_CONTROL_L; |
755 |
else |
756 |
sc-> sc_modifiers &= ~MOD_CONTROL_L; |
757 |
} |
758 |
if ((sc->sc_flags & UKBD_FLAG_CTRL_R) && |
759 |
(id == sc->sc_id_ctrl_r)) { |
760 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_ctrl_r)) |
761 |
sc->sc_modifiers |= MOD_CONTROL_R; |
762 |
else |
763 |
sc->sc_modifiers &= ~MOD_CONTROL_R; |
764 |
} |
765 |
if ((sc->sc_flags & UKBD_FLAG_SHIFT_L) && |
766 |
(id == sc->sc_id_shift_l)) { |
767 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_shift_l)) |
768 |
sc->sc_modifiers |= MOD_SHIFT_L; |
769 |
else |
770 |
sc->sc_modifiers &= ~MOD_SHIFT_L; |
771 |
} |
772 |
if ((sc->sc_flags & UKBD_FLAG_SHIFT_R) && |
773 |
(id == sc->sc_id_shift_r)) { |
774 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_shift_r)) |
775 |
sc->sc_modifiers |= MOD_SHIFT_R; |
776 |
else |
777 |
sc->sc_modifiers &= ~MOD_SHIFT_R; |
778 |
} |
779 |
if ((sc->sc_flags & UKBD_FLAG_ALT_L) && |
780 |
(id == sc->sc_id_alt_l)) { |
781 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_alt_l)) |
782 |
sc->sc_modifiers |= MOD_ALT_L; |
783 |
else |
784 |
sc->sc_modifiers &= ~MOD_ALT_L; |
785 |
} |
786 |
if ((sc->sc_flags & UKBD_FLAG_ALT_R) && |
787 |
(id == sc->sc_id_alt_r)) { |
788 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_alt_r)) |
789 |
sc->sc_modifiers |= MOD_ALT_R; |
790 |
else |
791 |
sc->sc_modifiers &= ~MOD_ALT_R; |
792 |
} |
793 |
if ((sc->sc_flags & UKBD_FLAG_WIN_L) && |
794 |
(id == sc->sc_id_win_l)) { |
795 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_win_l)) |
796 |
sc->sc_modifiers |= MOD_WIN_L; |
797 |
else |
798 |
sc->sc_modifiers &= ~MOD_WIN_L; |
799 |
} |
800 |
if ((sc->sc_flags & UKBD_FLAG_WIN_R) && |
801 |
(id == sc->sc_id_win_r)) { |
802 |
if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_win_r)) |
803 |
sc->sc_modifiers |= MOD_WIN_R; |
804 |
else |
805 |
sc->sc_modifiers &= ~MOD_WIN_R; |
806 |
} |
807 |
|
681 |
|
808 |
sc->sc_ndata.modifiers = sc->sc_modifiers; |
682 |
for (i = 0; i < UKBD_NKEYCODE; i++) { |
|
|
683 |
const uint64_t valid = sc->sc_loc_key_valid[i / 64]; |
684 |
const uint64_t mask = 1ULL << (i % 64); |
809 |
|
685 |
|
810 |
if ((sc->sc_flags & UKBD_FLAG_EVENTS) && |
686 |
if (mask == 1 && valid == 0) { |
811 |
(id == sc->sc_id_events)) { |
687 |
i += 63; |
812 |
i = sc->sc_loc_events.count; |
688 |
continue; /* skip empty areas */ |
813 |
if (i > UKBD_NKEYCODE) |
689 |
} else if (id != sc->sc_id_loc_key[i]) { |
814 |
i = UKBD_NKEYCODE; |
690 |
continue; /* invalid HID ID */ |
815 |
if (i > len) |
691 |
} else if (~valid & mask) { |
816 |
i = len; |
692 |
continue; /* location is not valid */ |
817 |
while (i--) { |
693 |
} else if (i == 0) { |
818 |
sc->sc_ndata.keycode[i] = |
694 |
offset = sc->sc_loc_key[0].count; |
819 |
hid_get_data(sc->sc_buffer + i, len - i, |
695 |
if (offset < 0 || offset > len) |
820 |
&sc->sc_loc_events); |
696 |
offset = len; |
|
|
697 |
while (offset--) { |
698 |
uint32_t key = |
699 |
hid_get_data(sc->sc_buffer + offset, len - offset, |
700 |
&sc->sc_loc_key[i]); |
701 |
if (modifiers & MOD_FN) |
702 |
key = ukbd_apple_fn(key); |
703 |
if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) |
704 |
key = ukbd_apple_swap(key); |
705 |
if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) |
706 |
continue; |
707 |
/* set key in bitmap */ |
708 |
sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64); |
709 |
} |
710 |
} else if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_key[i])) { |
711 |
uint32_t key = i; |
712 |
|
713 |
if (modifiers & MOD_FN) |
714 |
key = ukbd_apple_fn(key); |
715 |
if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) |
716 |
key = ukbd_apple_swap(key); |
717 |
if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) |
718 |
continue; |
719 |
/* set key in bitmap */ |
720 |
sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64); |
821 |
} |
721 |
} |
822 |
} |
722 |
} |
823 |
|
|
|
824 |
#ifdef USB_DEBUG |
723 |
#ifdef USB_DEBUG |
825 |
DPRINTF("modifiers = 0x%04x\n", (int)sc->sc_modifiers); |
724 |
DPRINTF("modifiers = 0x%04x\n", modifiers); |
826 |
for (i = 0; i < UKBD_NKEYCODE; i++) { |
725 |
for (i = 0; i < UKBD_NKEYCODE; i++) { |
827 |
if (sc->sc_ndata.keycode[i]) { |
726 |
const uint64_t valid = sc->sc_ndata.bitmap[i / 64]; |
828 |
DPRINTF("[%d] = 0x%02x\n", |
727 |
const uint64_t mask = 1ULL << (i % 64); |
829 |
(int)i, (int)sc->sc_ndata.keycode[i]); |
728 |
|
830 |
} |
729 |
if (valid & mask) |
|
|
730 |
DPRINTF("Key 0x%02x pressed\n", i); |
831 |
} |
731 |
} |
832 |
#endif |
732 |
#endif |
833 |
if (sc->sc_modifiers & MOD_FN) { |
|
|
834 |
for (i = 0; i < UKBD_NKEYCODE; i++) { |
835 |
sc->sc_ndata.keycode[i] = |
836 |
ukbd_apple_fn(sc->sc_ndata.keycode[i]); |
837 |
} |
838 |
} |
839 |
|
840 |
if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) { |
841 |
for (i = 0; i < UKBD_NKEYCODE; i++) { |
842 |
sc->sc_ndata.keycode[i] = |
843 |
ukbd_apple_swap(sc->sc_ndata.keycode[i]); |
844 |
} |
845 |
} |
846 |
|
847 |
ukbd_interrupt(sc); |
733 |
ukbd_interrupt(sc); |
848 |
|
734 |
|
849 |
case USB_ST_SETUP: |
735 |
case USB_ST_SETUP: |
Lines 1072-1081
Link Here
|
1072 |
ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) |
958 |
ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) |
1073 |
{ |
959 |
{ |
1074 |
uint32_t flags; |
960 |
uint32_t flags; |
|
|
961 |
uint32_t key; |
1075 |
|
962 |
|
1076 |
/* reset detected bits */ |
963 |
/* reset detected bits */ |
1077 |
sc->sc_flags &= ~UKBD_FLAG_HID_MASK; |
964 |
sc->sc_flags &= ~UKBD_FLAG_HID_MASK; |
1078 |
|
965 |
|
|
|
966 |
/* reset detected keys */ |
967 |
memset(sc->sc_loc_key_valid, 0, sizeof(sc->sc_loc_key_valid)); |
968 |
|
1079 |
/* check if there is an ID byte */ |
969 |
/* check if there is an ID byte */ |
1080 |
sc->sc_kbd_size = hid_report_size(ptr, len, |
970 |
sc->sc_kbd_size = hid_report_size(ptr, len, |
1081 |
hid_input, &sc->sc_kbd_id); |
971 |
hid_input, &sc->sc_kbd_id); |
Lines 1098-1181
Link Here
|
1098 |
sc->sc_flags |= UKBD_FLAG_APPLE_FN; |
988 |
sc->sc_flags |= UKBD_FLAG_APPLE_FN; |
1099 |
DPRINTFN(1, "Found Apple FN-key\n"); |
989 |
DPRINTFN(1, "Found Apple FN-key\n"); |
1100 |
} |
990 |
} |
1101 |
/* figure out some keys */ |
991 |
|
1102 |
if (hid_locate(ptr, len, |
|
|
1103 |
HID_USAGE2(HUP_KEYBOARD, 0xE0), |
1104 |
hid_input, 0, &sc->sc_loc_ctrl_l, &flags, |
1105 |
&sc->sc_id_ctrl_l)) { |
1106 |
if (flags & HIO_VARIABLE) |
1107 |
sc->sc_flags |= UKBD_FLAG_CTRL_L; |
1108 |
DPRINTFN(1, "Found left control\n"); |
1109 |
} |
1110 |
if (hid_locate(ptr, len, |
1111 |
HID_USAGE2(HUP_KEYBOARD, 0xE4), |
1112 |
hid_input, 0, &sc->sc_loc_ctrl_r, &flags, |
1113 |
&sc->sc_id_ctrl_r)) { |
1114 |
if (flags & HIO_VARIABLE) |
1115 |
sc->sc_flags |= UKBD_FLAG_CTRL_R; |
1116 |
DPRINTFN(1, "Found right control\n"); |
1117 |
} |
1118 |
if (hid_locate(ptr, len, |
1119 |
HID_USAGE2(HUP_KEYBOARD, 0xE1), |
1120 |
hid_input, 0, &sc->sc_loc_shift_l, &flags, |
1121 |
&sc->sc_id_shift_l)) { |
1122 |
if (flags & HIO_VARIABLE) |
1123 |
sc->sc_flags |= UKBD_FLAG_SHIFT_L; |
1124 |
DPRINTFN(1, "Found left shift\n"); |
1125 |
} |
1126 |
if (hid_locate(ptr, len, |
1127 |
HID_USAGE2(HUP_KEYBOARD, 0xE5), |
1128 |
hid_input, 0, &sc->sc_loc_shift_r, &flags, |
1129 |
&sc->sc_id_shift_r)) { |
1130 |
if (flags & HIO_VARIABLE) |
1131 |
sc->sc_flags |= UKBD_FLAG_SHIFT_R; |
1132 |
DPRINTFN(1, "Found right shift\n"); |
1133 |
} |
1134 |
if (hid_locate(ptr, len, |
1135 |
HID_USAGE2(HUP_KEYBOARD, 0xE2), |
1136 |
hid_input, 0, &sc->sc_loc_alt_l, &flags, |
1137 |
&sc->sc_id_alt_l)) { |
1138 |
if (flags & HIO_VARIABLE) |
1139 |
sc->sc_flags |= UKBD_FLAG_ALT_L; |
1140 |
DPRINTFN(1, "Found left alt\n"); |
1141 |
} |
1142 |
if (hid_locate(ptr, len, |
1143 |
HID_USAGE2(HUP_KEYBOARD, 0xE6), |
1144 |
hid_input, 0, &sc->sc_loc_alt_r, &flags, |
1145 |
&sc->sc_id_alt_r)) { |
1146 |
if (flags & HIO_VARIABLE) |
1147 |
sc->sc_flags |= UKBD_FLAG_ALT_R; |
1148 |
DPRINTFN(1, "Found right alt\n"); |
1149 |
} |
1150 |
if (hid_locate(ptr, len, |
1151 |
HID_USAGE2(HUP_KEYBOARD, 0xE3), |
1152 |
hid_input, 0, &sc->sc_loc_win_l, &flags, |
1153 |
&sc->sc_id_win_l)) { |
1154 |
if (flags & HIO_VARIABLE) |
1155 |
sc->sc_flags |= UKBD_FLAG_WIN_L; |
1156 |
DPRINTFN(1, "Found left GUI\n"); |
1157 |
} |
1158 |
if (hid_locate(ptr, len, |
1159 |
HID_USAGE2(HUP_KEYBOARD, 0xE7), |
1160 |
hid_input, 0, &sc->sc_loc_win_r, &flags, |
1161 |
&sc->sc_id_win_r)) { |
1162 |
if (flags & HIO_VARIABLE) |
1163 |
sc->sc_flags |= UKBD_FLAG_WIN_R; |
1164 |
DPRINTFN(1, "Found right GUI\n"); |
1165 |
} |
1166 |
/* figure out event buffer */ |
992 |
/* figure out event buffer */ |
1167 |
if (hid_locate(ptr, len, |
993 |
if (hid_locate(ptr, len, |
1168 |
HID_USAGE2(HUP_KEYBOARD, 0x00), |
994 |
HID_USAGE2(HUP_KEYBOARD, 0x00), |
1169 |
hid_input, 0, &sc->sc_loc_events, &flags, |
995 |
hid_input, 0, &sc->sc_loc_key[0], &flags, |
1170 |
&sc->sc_id_events)) { |
996 |
&sc->sc_id_loc_key[0])) { |
1171 |
if (flags & HIO_VARIABLE) { |
997 |
if (flags & HIO_VARIABLE) { |
1172 |
DPRINTFN(1, "Ignoring keyboard event control\n"); |
998 |
DPRINTFN(1, "Ignoring keyboard event control\n"); |
1173 |
} else { |
999 |
} else { |
1174 |
sc->sc_flags |= UKBD_FLAG_EVENTS; |
1000 |
sc->sc_loc_key_valid[0] |= 1; |
1175 |
DPRINTFN(1, "Found keyboard event array\n"); |
1001 |
DPRINTFN(1, "Found keyboard event array\n"); |
1176 |
} |
1002 |
} |
1177 |
} |
1003 |
} |
1178 |
|
1004 |
|
|
|
1005 |
/* figure out the keys */ |
1006 |
for (key = 1; key != UKBD_NKEYCODE; key++) { |
1007 |
if (hid_locate(ptr, len, |
1008 |
HID_USAGE2(HUP_KEYBOARD, key), |
1009 |
hid_input, 0, &sc->sc_loc_key[key], &flags, |
1010 |
&sc->sc_id_loc_key[key])) { |
1011 |
if (flags & HIO_VARIABLE) { |
1012 |
sc->sc_loc_key_valid[key / 64] |= |
1013 |
1ULL << (key % 64); |
1014 |
DPRINTFN(1, "Found key 0x%02x\n", key); |
1015 |
} |
1016 |
} |
1017 |
} |
1018 |
|
1179 |
/* figure out leds on keyboard */ |
1019 |
/* figure out leds on keyboard */ |
1180 |
sc->sc_led_size = hid_report_size(ptr, len, |
1020 |
sc->sc_led_size = hid_report_size(ptr, len, |
1181 |
hid_output, NULL); |
1021 |
hid_output, NULL); |
Lines 1301-1307
Link Here
|
1301 |
|
1141 |
|
1302 |
/* check if we should use the boot protocol */ |
1142 |
/* check if we should use the boot protocol */ |
1303 |
if (usb_test_quirk(uaa, UQ_KBD_BOOTPROTO) || |
1143 |
if (usb_test_quirk(uaa, UQ_KBD_BOOTPROTO) || |
1304 |
(err != 0) || (!(sc->sc_flags & UKBD_FLAG_EVENTS))) { |
1144 |
(err != 0) || ukbd_any_key_valid(sc) == false) { |
1305 |
|
1145 |
|
1306 |
DPRINTF("Forcing boot protocol\n"); |
1146 |
DPRINTF("Forcing boot protocol\n"); |
1307 |
|
1147 |
|
Lines 1660-1670
Link Here
|
1660 |
++(kbd->kb_count); |
1500 |
++(kbd->kb_count); |
1661 |
|
1501 |
|
1662 |
#ifdef UKBD_EMULATE_ATSCANCODE |
1502 |
#ifdef UKBD_EMULATE_ATSCANCODE |
1663 |
keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.modifiers); |
1503 |
keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap); |
1664 |
if (keycode == NN) { |
1504 |
if (keycode == NN) { |
1665 |
return -1; |
1505 |
return -1; |
1666 |
} |
1506 |
} |
1667 |
return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers, |
1507 |
return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap, |
1668 |
(usbcode & KEY_RELEASE))); |
1508 |
(usbcode & KEY_RELEASE))); |
1669 |
#else /* !UKBD_EMULATE_ATSCANCODE */ |
1509 |
#else /* !UKBD_EMULATE_ATSCANCODE */ |
1670 |
return (usbcode); |
1510 |
return (usbcode); |
Lines 1731-1743
Link Here
|
1731 |
|
1571 |
|
1732 |
#ifdef UKBD_EMULATE_ATSCANCODE |
1572 |
#ifdef UKBD_EMULATE_ATSCANCODE |
1733 |
/* USB key index -> key code -> AT scan code */ |
1573 |
/* USB key index -> key code -> AT scan code */ |
1734 |
keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.modifiers); |
1574 |
keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap); |
1735 |
if (keycode == NN) { |
1575 |
if (keycode == NN) { |
1736 |
return (NOKEY); |
1576 |
return (NOKEY); |
1737 |
} |
1577 |
} |
1738 |
/* return an AT scan code for the K_RAW mode */ |
1578 |
/* return an AT scan code for the K_RAW mode */ |
1739 |
if (sc->sc_mode == K_RAW) { |
1579 |
if (sc->sc_mode == K_RAW) { |
1740 |
return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers, |
1580 |
return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap, |
1741 |
(usbcode & KEY_RELEASE))); |
1581 |
(usbcode & KEY_RELEASE))); |
1742 |
} |
1582 |
} |
1743 |
#else /* !UKBD_EMULATE_ATSCANCODE */ |
1583 |
#else /* !UKBD_EMULATE_ATSCANCODE */ |
Lines 2061-2068
Link Here
|
2061 |
#endif |
1901 |
#endif |
2062 |
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); |
1902 |
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); |
2063 |
memset(&sc->sc_odata, 0, sizeof(sc->sc_odata)); |
1903 |
memset(&sc->sc_odata, 0, sizeof(sc->sc_odata)); |
2064 |
memset(&sc->sc_ntime, 0, sizeof(sc->sc_ntime)); |
1904 |
sc->sc_repeat_time = 0; |
2065 |
memset(&sc->sc_otime, 0, sizeof(sc->sc_otime)); |
1905 |
sc->sc_repeat_key = 0; |
2066 |
} |
1906 |
} |
2067 |
|
1907 |
|
2068 |
/* save the internal state, not used */ |
1908 |
/* save the internal state, not used */ |
Lines 2149-2159
Link Here
|
2149 |
|
1989 |
|
2150 |
#ifdef UKBD_EMULATE_ATSCANCODE |
1990 |
#ifdef UKBD_EMULATE_ATSCANCODE |
2151 |
static uint32_t |
1991 |
static uint32_t |
2152 |
ukbd_atkeycode(int usbcode, int shift) |
1992 |
ukbd_atkeycode(int usbcode, const uint64_t *bitmap) |
2153 |
{ |
1993 |
{ |
2154 |
uint32_t keycode; |
1994 |
uint32_t keycode; |
2155 |
|
1995 |
|
2156 |
keycode = ukbd_trtab[KEY_INDEX(usbcode)]; |
1996 |
keycode = ukbd_trtab[KEY_INDEX(usbcode)]; |
|
|
1997 |
|
2157 |
/* |
1998 |
/* |
2158 |
* Translate Alt-PrintScreen to SysRq. |
1999 |
* Translate Alt-PrintScreen to SysRq. |
2159 |
* |
2000 |
* |
Lines 2168-2180
Link Here
|
2168 |
* is routine. |
2009 |
* is routine. |
2169 |
*/ |
2010 |
*/ |
2170 |
if ((keycode == 0x5c || keycode == 0x7e) && |
2011 |
if ((keycode == 0x5c || keycode == 0x7e) && |
2171 |
shift & (MOD_ALT_L | MOD_ALT_R)) |
2012 |
(UKBD_KEY_PRESSED(bitmap, 0xe2 /* ALT-L */) || |
|
|
2013 |
UKBD_KEY_PRESSED(bitmap, 0xe6 /* ALT-R */))) |
2172 |
return (0x54); |
2014 |
return (0x54); |
2173 |
return (keycode); |
2015 |
return (keycode); |
2174 |
} |
2016 |
} |
2175 |
|
2017 |
|
2176 |
static int |
2018 |
static int |
2177 |
ukbd_key2scan(struct ukbd_softc *sc, int code, int shift, int up) |
2019 |
ukbd_key2scan(struct ukbd_softc *sc, int code, const uint64_t *bitmap, int up) |
2178 |
{ |
2020 |
{ |
2179 |
static const int scan[] = { |
2021 |
static const int scan[] = { |
2180 |
/* 89 */ |
2022 |
/* 89 */ |
Lines 2234-2245
Link Here
|
2234 |
code = scan[code - 89]; |
2076 |
code = scan[code - 89]; |
2235 |
} |
2077 |
} |
2236 |
/* PrintScreen */ |
2078 |
/* PrintScreen */ |
2237 |
if (code == 0x137 && (!(shift & (MOD_CONTROL_L | MOD_CONTROL_R | |
2079 |
if (code == 0x137 && (!( |
2238 |
MOD_SHIFT_L | MOD_SHIFT_R)))) { |
2080 |
UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) || |
|
|
2081 |
UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */) || |
2082 |
UKBD_KEY_PRESSED(bitmap, 0xe1 /* SHIFT-L */) || |
2083 |
UKBD_KEY_PRESSED(bitmap, 0xe5 /* SHIFT-R */)))) { |
2239 |
code |= SCAN_PREFIX_SHIFT; |
2084 |
code |= SCAN_PREFIX_SHIFT; |
2240 |
} |
2085 |
} |
2241 |
/* Pause/Break */ |
2086 |
/* Pause/Break */ |
2242 |
if ((code == 0x146) && (!(shift & (MOD_CONTROL_L | MOD_CONTROL_R)))) { |
2087 |
if ((code == 0x146) && (!( |
|
|
2088 |
UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) || |
2089 |
UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */)))) { |
2243 |
code = (0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL); |
2090 |
code = (0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL); |
2244 |
} |
2091 |
} |
2245 |
code |= (up ? SCAN_RELEASE : SCAN_PRESS); |
2092 |
code |= (up ? SCAN_RELEASE : SCAN_PRESS); |