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