|
|
1.1 root 1: // Code for handling USB Human Interface Devices (HID).
2: //
3: // Copyright (C) 2009 Kevin O'Connor <[email protected]>
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
1.1.1.3 root 12: #include "ps2port.h" // ATKBD_CMD_GETID
1.1 root 13:
14: struct usb_pipe *keyboard_pipe VAR16VISIBLE;
1.1.1.3 root 15: struct usb_pipe *mouse_pipe VAR16VISIBLE;
1.1 root 16:
17:
18: /****************************************************************
19: * Setup
20: ****************************************************************/
21:
1.1.1.3 root 22: // Send USB HID protocol message.
1.1 root 23: static int
1.1.1.3 root 24: set_protocol(struct usb_pipe *pipe, u16 val)
1.1 root 25: {
26: struct usb_ctrlrequest req;
27: req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
28: req.bRequest = HID_REQ_SET_PROTOCOL;
29: req.wValue = val;
30: req.wIndex = 0;
31: req.wLength = 0;
1.1.1.3 root 32: return send_default_control(pipe, &req, NULL);
1.1 root 33: }
34:
1.1.1.3 root 35: // Send USB HID SetIdle request.
1.1 root 36: static int
1.1.1.3 root 37: set_idle(struct usb_pipe *pipe, int ms)
1.1 root 38: {
39: struct usb_ctrlrequest req;
40: req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
41: req.bRequest = HID_REQ_SET_IDLE;
1.1.1.3 root 42: req.wValue = (ms/4)<<8;
1.1 root 43: req.wIndex = 0;
44: req.wLength = 0;
1.1.1.3 root 45: return send_default_control(pipe, &req, NULL);
1.1 root 46: }
47:
1.1.1.3 root 48: #define KEYREPEATWAITMS 500
49: #define KEYREPEATMS 33
50:
51: static int
52: usb_kbd_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc)
1.1 root 53: {
54: if (! CONFIG_USB_KEYBOARD)
55: return -1;
56: if (keyboard_pipe)
57: // XXX - this enables the first found keyboard (could be random)
58: return -1;
59:
1.1.1.3 root 60: if (epdesc->wMaxPacketSize != 8)
61: return -1;
1.1 root 62:
63: // Enable "boot" protocol.
1.1.1.3 root 64: int ret = set_protocol(pipe, 0);
1.1 root 65: if (ret)
66: return -1;
1.1.1.3 root 67: // Periodically send reports to enable key repeat.
68: ret = set_idle(pipe, KEYREPEATMS);
1.1 root 69: if (ret)
70: return -1;
71:
1.1.1.3 root 72: keyboard_pipe = alloc_intr_pipe(pipe, epdesc);
73: if (!keyboard_pipe)
74: return -1;
75:
76: dprintf(1, "USB keyboard initialized\n");
77: return 0;
78: }
79:
80: static int
81: usb_mouse_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc)
82: {
83: if (! CONFIG_USB_MOUSE)
84: return -1;
85: if (mouse_pipe)
86: // XXX - this enables the first found mouse (could be random)
87: return -1;
88:
89: if (epdesc->wMaxPacketSize < 3 || epdesc->wMaxPacketSize > 8)
90: return -1;
91:
92: // Enable "boot" protocol.
93: int ret = set_protocol(pipe, 0);
94: if (ret)
95: return -1;
96:
97: mouse_pipe = alloc_intr_pipe(pipe, epdesc);
98: if (!mouse_pipe)
1.1 root 99: return -1;
100:
1.1.1.3 root 101: dprintf(1, "USB mouse initialized\n");
1.1 root 102: return 0;
103: }
104:
1.1.1.3 root 105: // Initialize a found USB HID device (if applicable).
106: int
107: usb_hid_init(struct usb_pipe *pipe
108: , struct usb_interface_descriptor *iface, int imax)
109: {
110: if (! CONFIG_USB_KEYBOARD || ! CONFIG_USB_MOUSE)
111: return -1;
112: dprintf(2, "usb_hid_init %p\n", pipe);
113:
114: if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT)
115: // Doesn't support boot protocol.
116: return -1;
117:
118: // Find intr in endpoint.
119: struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
120: iface, imax, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
121: if (!epdesc) {
122: dprintf(1, "No usb hid intr in?\n");
123: return -1;
124: }
125:
126: if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD)
127: return usb_kbd_init(pipe, epdesc);
128: if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
129: return usb_mouse_init(pipe, epdesc);
130: return -1;
131: }
132:
1.1 root 133:
134: /****************************************************************
135: * Keyboard events
136: ****************************************************************/
137:
1.1.1.3 root 138: // Mapping from USB key id to ps2 key sequence.
1.1 root 139: static u16 KeyToScanCode[] VAR16 = {
140: 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
141: 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
142: 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
143: 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
144: 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
145: 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
146: 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
147: 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
148: 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
149: 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
150: 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
151: 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
152: 0x0048, 0x0049, 0x0052, 0x0053
153: };
154:
1.1.1.3 root 155: // Mapping from USB modifier id to ps2 key sequence.
1.1 root 156: static u16 ModifierToScanCode[] VAR16 = {
157: //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
158: 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
159: };
160:
1.1.1.3 root 161: #define RELEASEBIT 0x80
162:
163: // Format of USB keyboard event data
1.1 root 164: struct keyevent {
165: u8 modifiers;
166: u8 reserved;
167: u8 keys[6];
168: };
169:
1.1.1.3 root 170: // Translate data from KeyToScanCode[] to calls to process_key().
1.1 root 171: static void
172: prockeys(u16 keys)
173: {
174: if (keys > 0xff) {
175: u8 key = keys>>8;
176: if (key == 0xe1) {
177: // Pause key
178: process_key(0xe1);
1.1.1.3 root 179: process_key(0x1d | (keys & RELEASEBIT));
180: process_key(0x45 | (keys & RELEASEBIT));
1.1 root 181: return;
182: }
183: process_key(key);
184: }
185: process_key(keys);
186: }
187:
1.1.1.3 root 188: // Handle a USB key press/release event.
189: static void
190: procscankey(u8 key, u8 flags)
191: {
192: if (key >= ARRAY_SIZE(KeyToScanCode))
193: return;
194: u16 keys = GET_GLOBAL(KeyToScanCode[key]);
195: if (keys)
196: prockeys(keys | flags);
197: }
198:
199: // Handle a USB modifier press/release event.
1.1 root 200: static void
1.1.1.3 root 201: procmodkey(u8 mods, u8 flags)
202: {
203: int i;
204: for (i=0; mods; i++)
205: if (mods & (1<<i)) {
206: // Modifier key change.
207: prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
208: mods &= ~(1<<i);
209: }
210: }
211:
212: // Process USB keyboard data.
213: static void noinline
1.1 root 214: handle_key(struct keyevent *data)
215: {
1.1.1.3 root 216: dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
217:
218: // Load old keys.
219: u16 ebda_seg = get_ebda_seg();
220: struct usbkeyinfo old;
221: old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
222:
223: // Check for keys no longer pressed.
224: int addpos = 0;
1.1 root 225: int i;
1.1.1.3 root 226: for (i=0; i<ARRAY_SIZE(old.keys); i++) {
227: u8 key = old.keys[i];
228: if (!key)
229: break;
230: int j;
231: for (j=0;; j++) {
232: if (j>=ARRAY_SIZE(data->keys)) {
233: // Key released.
234: procscankey(key, RELEASEBIT);
235: if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
236: // Last pressed key released - disable repeat.
237: old.repeatcount = 0xff;
238: break;
239: }
240: if (data->keys[j] == key) {
241: // Key still pressed.
242: data->keys[j] = 0;
243: old.keys[addpos++] = key;
244: break;
245: }
246: }
247: }
248: procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
249:
250: // Process new keys
251: procmodkey(data->modifiers & ~old.modifiers, 0);
252: old.modifiers = data->modifiers;
1.1 root 253: for (i=0; i<ARRAY_SIZE(data->keys); i++) {
254: u8 key = data->keys[i];
255: if (!key)
256: continue;
1.1.1.3 root 257: // New key pressed.
258: procscankey(key, 0);
259: old.keys[addpos++] = key;
260: old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
261: }
262: if (addpos < ARRAY_SIZE(old.keys))
263: old.keys[addpos] = 0;
264:
265: // Check for key repeat event.
266: if (addpos) {
267: if (!old.repeatcount)
268: procscankey(old.keys[addpos-1], 0);
269: else if (old.repeatcount != 0xff)
270: old.repeatcount--;
1.1 root 271: }
1.1.1.3 root 272:
273: // Update old keys
274: SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
1.1 root 275: }
276:
1.1.1.3 root 277: // Check if a USB keyboard event is pending and process it if so.
278: static void
1.1.1.2 root 279: usb_check_key(void)
1.1 root 280: {
281: if (! CONFIG_USB_KEYBOARD)
282: return;
283: struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
284: if (!pipe)
285: return;
286:
287: for (;;) {
288: struct keyevent data;
289: int ret = usb_poll_intr(pipe, &data);
290: if (ret)
291: break;
292: handle_key(&data);
293: }
294: }
1.1.1.3 root 295:
296: // Test if USB keyboard is active.
297: inline int
298: usb_kbd_active(void)
299: {
300: if (! CONFIG_USB_KEYBOARD)
301: return 0;
302: return GET_GLOBAL(keyboard_pipe) != NULL;
303: }
304:
305: // Handle a ps2 style keyboard command.
306: inline int
307: usb_kbd_command(int command, u8 *param)
308: {
309: if (! CONFIG_USB_KEYBOARD)
310: return -1;
311: dprintf(9, "usb keyboard cmd=%x\n", command);
312: switch (command) {
313: case ATKBD_CMD_GETID:
314: // Return the id of a standard AT keyboard.
315: param[0] = 0xab;
316: param[1] = 0x83;
317: return 0;
318: default:
319: return -1;
320: }
321: }
322:
323:
324: /****************************************************************
325: * Mouse events
326: ****************************************************************/
327:
328: // Format of USB mouse event data
329: struct mouseevent {
330: u8 buttons;
331: u8 x, y;
332: u8 reserved[5];
333: };
334:
335: // Process USB mouse data.
336: static void
337: handle_mouse(struct mouseevent *data)
338: {
339: dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y);
340:
341: s8 x = data->x, y = -data->y;
342: u8 flag = ((data->buttons & 0x7) | (1<<3)
343: | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0));
344: process_mouse(flag);
345: process_mouse(x);
346: process_mouse(y);
347: }
348:
349: // Check if a USB mouse event is pending and process it if so.
350: static void
351: usb_check_mouse(void)
352: {
353: if (! CONFIG_USB_MOUSE)
354: return;
355: struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe);
356: if (!pipe)
357: return;
358:
359: for (;;) {
360: struct mouseevent data;
361: int ret = usb_poll_intr(pipe, &data);
362: if (ret)
363: break;
364: handle_mouse(&data);
365: }
366: }
367:
368: // Test if USB mouse is active.
369: inline int
370: usb_mouse_active(void)
371: {
372: if (! CONFIG_USB_MOUSE)
373: return 0;
374: return GET_GLOBAL(mouse_pipe) != NULL;
375: }
376:
377: // Handle a ps2 style mouse command.
378: inline int
379: usb_mouse_command(int command, u8 *param)
380: {
381: if (! CONFIG_USB_MOUSE)
382: return -1;
383: dprintf(9, "usb mouse cmd=%x\n", command);
384: switch (command) {
385: case PSMOUSE_CMD_ENABLE:
386: case PSMOUSE_CMD_DISABLE:
387: case PSMOUSE_CMD_SETSCALE11:
388: return 0;
389: case PSMOUSE_CMD_SETSCALE21:
390: case PSMOUSE_CMD_SETRATE:
391: case PSMOUSE_CMD_SETRES:
392: // XXX
393: return 0;
394: case PSMOUSE_CMD_RESET_BAT:
395: case PSMOUSE_CMD_GETID:
396: // Return the id of a standard AT mouse.
397: param[0] = 0xaa;
398: param[1] = 0x00;
399: return 0;
400:
401: case PSMOUSE_CMD_GETINFO:
402: param[0] = 0x00;
403: param[1] = 4;
404: param[2] = 100;
405: return 0;
406:
407: default:
408: return -1;
409: }
410: }
411:
412: // Check for USB events pending - called periodically from timer interrupt.
413: void
414: usb_check_event(void)
415: {
416: usb_check_key();
417: usb_check_mouse();
418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.