Prefer passing a USB "pipe" structure over a USB endp encoding.
[seabios.git] / src / usb-hid.c
1 // Code for handling USB Human Interface Devices (HID).
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "util.h" // dprintf
8 #include "usb-hid.h" // usb_keyboard_setup
9 #include "config.h" // CONFIG_*
10 #include "usb.h" // usb_ctrlrequest
11 #include "biosvar.h" // GET_GLOBAL
12
13 struct usb_pipe *keyboard_pipe VAR16VISIBLE;
14
15
16 /****************************************************************
17  * Setup
18  ****************************************************************/
19
20 static int
21 set_protocol(struct usb_pipe *pipe, u16 val)
22 {
23     struct usb_ctrlrequest req;
24     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
25     req.bRequest = HID_REQ_SET_PROTOCOL;
26     req.wValue = val;
27     req.wIndex = 0;
28     req.wLength = 0;
29     return send_default_control(pipe, &req, NULL);
30 }
31
32 static int
33 set_idle(struct usb_pipe *pipe, int ms)
34 {
35     struct usb_ctrlrequest req;
36     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
37     req.bRequest = HID_REQ_SET_IDLE;
38     req.wValue = (ms/4)<<8;
39     req.wIndex = 0;
40     req.wLength = 0;
41     return send_default_control(pipe, &req, NULL);
42 }
43
44 #define KEYREPEATWAITMS 500
45 #define KEYREPEATMS 33
46
47 int
48 usb_keyboard_init(struct usb_pipe *pipe
49                   , struct usb_interface_descriptor *iface, int imax)
50 {
51     if (! CONFIG_USB_KEYBOARD)
52         return -1;
53     if (keyboard_pipe)
54         // XXX - this enables the first found keyboard (could be random)
55         return -1;
56     dprintf(2, "usb_keyboard_setup %x\n", pipe->endp);
57
58     // Find intr in endpoint.
59     struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
60         iface, imax, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
61     if (!epdesc || epdesc->wMaxPacketSize != 8) {
62         dprintf(1, "No keyboard intr in?\n");
63         return -1;
64     }
65
66     // Enable "boot" protocol.
67     int ret = set_protocol(pipe, 1);
68     if (ret)
69         return -1;
70     // Periodically send reports to enable key repeat.
71     ret = set_idle(pipe, KEYREPEATMS);
72     if (ret)
73         return -1;
74
75     u32 inendp = mkendpFromDesc(pipe, epdesc);
76     keyboard_pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
77     if (!keyboard_pipe)
78         return -1;
79
80     dprintf(1, "USB keyboard initialized\n");
81     return 0;
82 }
83
84 void
85 usb_keyboard_setup(void)
86 {
87     if (! CONFIG_USB_KEYBOARD)
88         return;
89     keyboard_pipe = NULL;
90 }
91
92
93 /****************************************************************
94  * Keyboard events
95  ****************************************************************/
96
97 static u16 KeyToScanCode[] VAR16 = {
98     0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
99     0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
100     0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
101     0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
102     0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
103     0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
104     0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
105     0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
106     0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
107     0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
108     0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
109     0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
110     0x0048, 0x0049, 0x0052, 0x0053
111 };
112
113 static u16 ModifierToScanCode[] VAR16 = {
114     //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
115     0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
116 };
117
118 #define RELEASEBIT 0x80
119
120 struct keyevent {
121     u8 modifiers;
122     u8 reserved;
123     u8 keys[6];
124 };
125
126 static void
127 prockeys(u16 keys)
128 {
129     if (keys > 0xff) {
130         u8 key = keys>>8;
131         if (key == 0xe1) {
132             // Pause key
133             process_key(0xe1);
134             process_key(0x1d | (keys & RELEASEBIT));
135             process_key(0x45 | (keys & RELEASEBIT));
136             return;
137         }
138         process_key(key);
139     }
140     process_key(keys);
141 }
142
143 static void
144 procscankey(u8 key, u8 flags)
145 {
146     if (key >= ARRAY_SIZE(KeyToScanCode))
147         return;
148     u16 keys = GET_GLOBAL(KeyToScanCode[key]);
149     if (keys)
150         prockeys(keys | flags);
151 }
152
153 static void
154 procmodkey(u8 mods, u8 flags)
155 {
156     int i;
157     for (i=0; mods; i++)
158         if (mods & (1<<i)) {
159             // Modifier key change.
160             prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
161             mods &= ~(1<<i);
162         }
163 }
164
165 static void noinline
166 handle_key(struct keyevent *data)
167 {
168     dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
169
170     // Load old keys.
171     u16 ebda_seg = get_ebda_seg();
172     struct usbkeyinfo old;
173     old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
174
175     // Check for keys no longer pressed.
176     int addpos = 0;
177     int i;
178     for (i=0; i<ARRAY_SIZE(old.keys); i++) {
179         u8 key = old.keys[i];
180         if (!key)
181             break;
182         int j;
183         for (j=0;; j++) {
184             if (j>=ARRAY_SIZE(data->keys)) {
185                 // Key released.
186                 procscankey(key, RELEASEBIT);
187                 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
188                     // Last pressed key released - disable repeat.
189                     old.repeatcount = 0xff;
190                 break;
191             }
192             if (data->keys[j] == key) {
193                 // Key still pressed.
194                 data->keys[j] = 0;
195                 old.keys[addpos++] = key;
196                 break;
197             }
198         }
199     }
200     procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
201
202     // Process new keys
203     procmodkey(data->modifiers & ~old.modifiers, 0);
204     old.modifiers = data->modifiers;
205     for (i=0; i<ARRAY_SIZE(data->keys); i++) {
206         u8 key = data->keys[i];
207         if (!key)
208             continue;
209         // New key pressed.
210         procscankey(key, 0);
211         old.keys[addpos++] = key;
212         old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
213     }
214     if (addpos < ARRAY_SIZE(old.keys))
215         old.keys[addpos] = 0;
216
217     // Check for key repeat event.
218     if (addpos) {
219         if (!old.repeatcount)
220             procscankey(old.keys[addpos-1], 0);
221         else if (old.repeatcount != 0xff)
222             old.repeatcount--;
223     }
224
225     // Update old keys
226     SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
227 }
228
229 void
230 usb_check_key(void)
231 {
232     if (! CONFIG_USB_KEYBOARD)
233         return;
234     struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
235     if (!pipe)
236         return;
237
238     for (;;) {
239         struct keyevent data;
240         int ret = usb_poll_intr(pipe, &data);
241         if (ret)
242             break;
243         handle_key(&data);
244     }
245 }