]> git.donarmstrong.com Git - qmk_firmware.git/blob - usb_keyboard.c
ADD: macway/doc
[qmk_firmware.git] / usb_keyboard.c
1 #include <avr/interrupt.h>
2 #include <avr/pgmspace.h>
3 #include "usb_keyboard.h"
4 #include "print.h"
5 #include "debug.h"
6
7
8 static bool is_sent = false;
9
10 // which modifier keys are currently pressed
11 // 1=left ctrl,    2=left shift,   4=left alt,    8=left gui
12 // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
13 uint8_t keyboard_modifier_keys=0;
14
15 // which keys are currently pressed, up to 6 keys may be down at once
16 uint8_t keyboard_keys[6]={0,0,0,0,0,0};
17
18 // protocol setting from the host.  We use exactly the same report
19 // either way, so this variable only stores the setting since we
20 // are required to be able to report which setting is in use.
21 uint8_t keyboard_protocol=1;
22
23 // the idle configuration, how often we send the report to the
24 // host (ms * 4) even when it hasn't changed
25 uint8_t keyboard_idle_config=125;
26
27 // count until idle timeout
28 uint8_t keyboard_idle_count=0;
29
30 // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
31 volatile uint8_t keyboard_leds=0;
32
33
34 // perform a single keystroke
35 int8_t usb_keyboard_press(uint8_t key, uint8_t modifier)
36 {
37         int8_t r;
38
39         keyboard_modifier_keys = modifier;
40         keyboard_keys[0] = key;
41         r = usb_keyboard_send();
42         if (r) return r;
43         keyboard_modifier_keys = 0;
44         keyboard_keys[0] = 0;
45         return usb_keyboard_send();
46 }
47
48 // send the contents of keyboard_keys and keyboard_modifier_keys
49 int8_t usb_keyboard_send(void)
50 {
51         uint8_t i, intr_state, timeout;
52
53         if (!usb_configured()) return -1;
54         intr_state = SREG;
55         cli();
56         UENUM = KEYBOARD_ENDPOINT;
57         timeout = UDFNUML + 50;
58         while (1) {
59                 // are we ready to transmit?
60                 if (UEINTX & (1<<RWAL)) break;
61                 SREG = intr_state;
62                 // has the USB gone offline?
63                 if (!usb_configured()) return -1;
64                 // have we waited too long?
65                 if (UDFNUML == timeout) return -1;
66                 // get ready to try checking again
67                 intr_state = SREG;
68                 cli();
69                 UENUM = KEYBOARD_ENDPOINT;
70         }
71         UEDATX = keyboard_modifier_keys;
72         UEDATX = 0;
73         for (i=0; i<6; i++) {
74                 UEDATX = keyboard_keys[i];
75         }
76         UEINTX = 0x3A;
77         keyboard_idle_count = 0;
78         SREG = intr_state;
79         is_sent = true;
80         return 0;
81 }
82
83 void usb_keyboard_init(void) {
84     usb_keyboard_clear();
85     is_sent = false;
86 }
87
88 void usb_keyboard_clear(void) {
89     usb_keyboard_clear_key();
90     usb_keyboard_clear_mod();
91 }
92
93 void usb_keyboard_clear_key(void) {
94     for (int i = 0; i < 6; i++) keyboard_keys[i] = 0;
95 }
96
97 void usb_keyboard_clear_mod(void) {
98     keyboard_modifier_keys = 0;
99 }
100
101 bool usb_keyboard_is_sent(void) {
102     return is_sent;
103 }
104
105 bool usb_keyboard_has_key(void) {
106     uint8_t keys = 0;    
107     for (int i = 0; i < 6; i++) keys |= keyboard_keys[i];
108     return keys ? true : false;
109 }
110
111 bool usb_keyboard_has_mod(void) {
112     return keyboard_modifier_keys ? true : false;
113 }
114
115 void usb_keyboard_print(void) {
116     if (!debug_keyboard) return;
117     print("\nkeys: ");
118     for (int i = 0; i < 6; i++) { phex(keyboard_keys[i]); print(" "); }
119     print("\n");
120     print("mods: "); phex(keyboard_modifier_keys); print("\n");
121 }