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