blob: a22765b04d44a90a3d2f15d3eb9f115b09a5036f [file] [log] [blame]
Kevin O'Connor114592f2009-09-28 21:32:08 -04001// 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
Kevin O'Connor114592f2009-09-28 21:32:08 -04007#include "biosvar.h" // GET_GLOBAL
Kevin O'Connor2d2fa312013-09-14 21:55:26 -04008#include "config.h" // CONFIG_*
9#include "output.h" // dprintf
Kevin O'Connordd5a8a62010-05-01 19:59:34 -040010#include "ps2port.h" // ATKBD_CMD_GETID
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040011#include "usb.h" // usb_ctrlrequest
12#include "usb-hid.h" // usb_keyboard_setup
13#include "util.h" // process_key
Kevin O'Connor114592f2009-09-28 21:32:08 -040014
Kevin O'Connor89a2f962013-02-18 23:36:03 -050015struct usb_pipe *keyboard_pipe VARFSEG;
16struct usb_pipe *mouse_pipe VARFSEG;
Kevin O'Connor114592f2009-09-28 21:32:08 -040017
18
19/****************************************************************
20 * Setup
21 ****************************************************************/
22
Kevin O'Connor5718d562010-05-01 19:25:41 -040023// Send USB HID protocol message.
Kevin O'Connor114592f2009-09-28 21:32:08 -040024static int
Kevin O'Connor357bdfa2010-02-26 08:57:13 -050025set_protocol(struct usb_pipe *pipe, u16 val)
Kevin O'Connor114592f2009-09-28 21:32:08 -040026{
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;
Kevin O'Connor222bad42014-10-16 12:11:12 -040033 return usb_send_default_control(pipe, &req, NULL);
Kevin O'Connor114592f2009-09-28 21:32:08 -040034}
35
Kevin O'Connor5718d562010-05-01 19:25:41 -040036// Send USB HID SetIdle request.
Kevin O'Connor114592f2009-09-28 21:32:08 -040037static int
Kevin O'Connor357bdfa2010-02-26 08:57:13 -050038set_idle(struct usb_pipe *pipe, int ms)
Kevin O'Connor114592f2009-09-28 21:32:08 -040039{
40 struct usb_ctrlrequest req;
41 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
42 req.bRequest = HID_REQ_SET_IDLE;
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -050043 req.wValue = (ms/4)<<8;
Kevin O'Connor114592f2009-09-28 21:32:08 -040044 req.wIndex = 0;
45 req.wLength = 0;
Kevin O'Connor222bad42014-10-16 12:11:12 -040046 return usb_send_default_control(pipe, &req, NULL);
Kevin O'Connor114592f2009-09-28 21:32:08 -040047}
48
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -050049#define KEYREPEATWAITMS 500
50#define KEYREPEATMS 33
51
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -050052// Format of USB keyboard event data
53struct keyevent {
54 u8 modifiers;
55 u8 reserved;
56 u8 keys[6];
57};
58
59#define MAX_KBD_EVENT 10
60
Kevin O'Connor0e885762010-05-01 22:14:40 -040061static int
Kevin O'Connord83c87b2013-01-21 01:14:12 -050062usb_kbd_setup(struct usbdevice_s *usbdev
63 , struct usb_endpoint_descriptor *epdesc)
Kevin O'Connor114592f2009-09-28 21:32:08 -040064{
65 if (! CONFIG_USB_KEYBOARD)
66 return -1;
67 if (keyboard_pipe)
Kevin O'Connora5826b52009-10-24 17:57:29 -040068 // XXX - this enables the first found keyboard (could be random)
Kevin O'Connor114592f2009-09-28 21:32:08 -040069 return -1;
Kevin O'Connor114592f2009-09-28 21:32:08 -040070
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -050071 if (epdesc->wMaxPacketSize < sizeof(struct keyevent)
72 || epdesc->wMaxPacketSize > MAX_KBD_EVENT) {
73 dprintf(1, "USB keyboard wMaxPacketSize=%d; aborting\n"
74 , epdesc->wMaxPacketSize);
Kevin O'Connor3c160dd2010-02-17 23:06:52 -050075 return -1;
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -050076 }
Kevin O'Connor114592f2009-09-28 21:32:08 -040077
78 // Enable "boot" protocol.
Kevin O'Connor6a8e8952012-03-08 07:20:30 -050079 int ret = set_protocol(usbdev->defpipe, 0);
Kevin O'Connor114592f2009-09-28 21:32:08 -040080 if (ret)
81 return -1;
Kevin O'Connor3c160dd2010-02-17 23:06:52 -050082 // Periodically send reports to enable key repeat.
Kevin O'Connor6a8e8952012-03-08 07:20:30 -050083 ret = set_idle(usbdev->defpipe, KEYREPEATMS);
Kevin O'Connor114592f2009-09-28 21:32:08 -040084 if (ret)
Matt DeVillier24d39382019-12-12 21:51:19 -060085 dprintf(3, "Warning: Failed to set key repeat rate\n");
Kevin O'Connor114592f2009-09-28 21:32:08 -040086
Kevin O'Connorc3d96c22012-03-10 09:03:25 -050087 keyboard_pipe = usb_alloc_pipe(usbdev, epdesc);
Kevin O'Connor357bdfa2010-02-26 08:57:13 -050088 if (!keyboard_pipe)
Kevin O'Connor114592f2009-09-28 21:32:08 -040089 return -1;
Kevin O'Connor114592f2009-09-28 21:32:08 -040090
Kevin O'Connor357bdfa2010-02-26 08:57:13 -050091 dprintf(1, "USB keyboard initialized\n");
Kevin O'Connor114592f2009-09-28 21:32:08 -040092 return 0;
93}
94
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -050095// Format of USB mouse event data
96struct mouseevent {
97 u8 buttons;
98 u8 x, y;
99};
100
101#define MAX_MOUSE_EVENT 8
102
Kevin O'Connor0e885762010-05-01 22:14:40 -0400103static int
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500104usb_mouse_setup(struct usbdevice_s *usbdev
105 , struct usb_endpoint_descriptor *epdesc)
Kevin O'Connor114592f2009-09-28 21:32:08 -0400106{
Kevin O'Connor0e885762010-05-01 22:14:40 -0400107 if (! CONFIG_USB_MOUSE)
108 return -1;
109 if (mouse_pipe)
110 // XXX - this enables the first found mouse (could be random)
111 return -1;
112
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -0500113 if (epdesc->wMaxPacketSize < sizeof(struct mouseevent)
114 || epdesc->wMaxPacketSize > MAX_MOUSE_EVENT) {
115 dprintf(1, "USB mouse wMaxPacketSize=%d; aborting\n"
116 , epdesc->wMaxPacketSize);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400117 return -1;
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -0500118 }
Kevin O'Connor0e885762010-05-01 22:14:40 -0400119
120 // Enable "boot" protocol.
Kevin O'Connor6a8e8952012-03-08 07:20:30 -0500121 int ret = set_protocol(usbdev->defpipe, 0);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400122 if (ret)
123 return -1;
124
Kevin O'Connorc3d96c22012-03-10 09:03:25 -0500125 mouse_pipe = usb_alloc_pipe(usbdev, epdesc);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400126 if (!mouse_pipe)
127 return -1;
128
129 dprintf(1, "USB mouse initialized\n");
130 return 0;
131}
132
133// Initialize a found USB HID device (if applicable).
134int
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500135usb_hid_setup(struct usbdevice_s *usbdev)
Kevin O'Connor0e885762010-05-01 22:14:40 -0400136{
Kevin O'Connor48dc6a62014-03-31 23:50:42 -0400137 if (! CONFIG_USB_KEYBOARD && ! CONFIG_USB_MOUSE)
Kevin O'Connor0e885762010-05-01 22:14:40 -0400138 return -1;
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500139 dprintf(2, "usb_hid_setup %p\n", usbdev->defpipe);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400140
Kevin O'Connor6a8e8952012-03-08 07:20:30 -0500141 struct usb_interface_descriptor *iface = usbdev->iface;
Kevin O'Connor0e885762010-05-01 22:14:40 -0400142 if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT)
143 // Doesn't support boot protocol.
144 return -1;
145
146 // Find intr in endpoint.
Kevin O'Connor674f1402014-10-16 12:08:00 -0400147 struct usb_endpoint_descriptor *epdesc = usb_find_desc(
Kevin O'Connor6a8e8952012-03-08 07:20:30 -0500148 usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400149 if (!epdesc) {
150 dprintf(1, "No usb hid intr in?\n");
151 return -1;
152 }
153
154 if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD)
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500155 return usb_kbd_setup(usbdev, epdesc);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400156 if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500157 return usb_mouse_setup(usbdev, epdesc);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400158 return -1;
159}
160
Kevin O'Connor114592f2009-09-28 21:32:08 -0400161
162/****************************************************************
163 * Keyboard events
164 ****************************************************************/
165
Kevin O'Connor5718d562010-05-01 19:25:41 -0400166// Mapping from USB key id to ps2 key sequence.
Kevin O'Connor114592f2009-09-28 21:32:08 -0400167static u16 KeyToScanCode[] VAR16 = {
168 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
169 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
170 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
171 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
172 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
173 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
174 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
175 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
176 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400177 0xe145, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
Kevin O'Connor114592f2009-09-28 21:32:08 -0400178 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
179 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
180 0x0048, 0x0049, 0x0052, 0x0053
181};
182
Kevin O'Connor5718d562010-05-01 19:25:41 -0400183// Mapping from USB modifier id to ps2 key sequence.
Kevin O'Connor114592f2009-09-28 21:32:08 -0400184static u16 ModifierToScanCode[] VAR16 = {
185 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
186 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
187};
188
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500189#define RELEASEBIT 0x80
190
Kevin O'Connor5718d562010-05-01 19:25:41 -0400191// Translate data from KeyToScanCode[] to calls to process_key().
Kevin O'Connor114592f2009-09-28 21:32:08 -0400192static void
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400193prockeys(u16 scancode, u8 key_release, u8 mods)
Kevin O'Connor114592f2009-09-28 21:32:08 -0400194{
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400195 if (scancode > 0xff) {
196 if (scancode == 0xe145) {
197 // XXX - a real AT keyboard would immediately send the key release
198 if (mods & ((1<<0) | (1<<4))) {
199 // Cntr+Break key
200 process_key(0xe0);
201 process_key(0x46 | key_release);
202 } else {
203 // Pause key
204 process_key(0xe1);
205 process_key(0x1d | key_release);
206 process_key(0x45 | key_release);
207 }
208 return;
209 } else if (scancode == 0xe037 && mods & ((1<<2) | (1<<6))) {
210 // Alt+SysReq key
211 process_key(0x54 | key_release);
Kevin O'Connor114592f2009-09-28 21:32:08 -0400212 return;
213 }
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400214 process_key(0xe0);
Kevin O'Connor114592f2009-09-28 21:32:08 -0400215 }
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400216 process_key(scancode | key_release);
Kevin O'Connor114592f2009-09-28 21:32:08 -0400217}
218
Kevin O'Connor5718d562010-05-01 19:25:41 -0400219// Handle a USB key press/release event.
Kevin O'Connor114592f2009-09-28 21:32:08 -0400220static void
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400221procscankey(u8 key, u8 key_release, u8 mods)
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500222{
223 if (key >= ARRAY_SIZE(KeyToScanCode))
224 return;
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400225 u16 scancode = GET_GLOBAL(KeyToScanCode[key]);
226 if (scancode)
227 prockeys(scancode, key_release, mods);
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500228}
229
Kevin O'Connor5718d562010-05-01 19:25:41 -0400230// Handle a USB modifier press/release event.
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500231static void
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400232procmodkey(u8 mods, u8 key_release)
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500233{
234 int i;
235 for (i=0; mods; i++)
236 if (mods & (1<<i)) {
237 // Modifier key change.
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400238 prockeys(GET_GLOBAL(ModifierToScanCode[i]), key_release, 0);
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500239 mods &= ~(1<<i);
240 }
241}
242
Kevin O'Connor2d012ec2012-05-13 12:39:16 -0400243struct usbkeyinfo {
244 union {
245 struct {
246 u8 modifiers;
247 u8 repeatcount;
248 u8 keys[6];
249 };
250 u64 data;
251 };
252};
253struct usbkeyinfo LastUSBkey VARLOW;
254
Kevin O'Connor5718d562010-05-01 19:25:41 -0400255// Process USB keyboard data.
Kevin O'Connorac7eb5e2012-05-28 14:42:16 -0400256static void
Kevin O'Connor114592f2009-09-28 21:32:08 -0400257handle_key(struct keyevent *data)
258{
Kevin O'Connor78523312010-02-14 19:07:43 -0500259 dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500260
261 // Load old keys.
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500262 struct usbkeyinfo old;
Kevin O'Connor2d012ec2012-05-13 12:39:16 -0400263 old.data = GET_LOW(LastUSBkey.data);
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500264
265 // Check for keys no longer pressed.
266 int addpos = 0;
Kevin O'Connor114592f2009-09-28 21:32:08 -0400267 int i;
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500268 for (i=0; i<ARRAY_SIZE(old.keys); i++) {
269 u8 key = old.keys[i];
270 if (!key)
271 break;
272 int j;
273 for (j=0;; j++) {
274 if (j>=ARRAY_SIZE(data->keys)) {
275 // Key released.
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400276 procscankey(key, RELEASEBIT, data->modifiers);
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500277 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
278 // Last pressed key released - disable repeat.
279 old.repeatcount = 0xff;
280 break;
281 }
282 if (data->keys[j] == key) {
283 // Key still pressed.
284 data->keys[j] = 0;
285 old.keys[addpos++] = key;
286 break;
287 }
288 }
289 }
290 procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
291
292 // Process new keys
293 procmodkey(data->modifiers & ~old.modifiers, 0);
294 old.modifiers = data->modifiers;
Kevin O'Connor114592f2009-09-28 21:32:08 -0400295 for (i=0; i<ARRAY_SIZE(data->keys); i++) {
296 u8 key = data->keys[i];
Kevin O'Connor114592f2009-09-28 21:32:08 -0400297 if (!key)
298 continue;
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500299 // New key pressed.
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400300 procscankey(key, 0, data->modifiers);
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500301 old.keys[addpos++] = key;
302 old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
Kevin O'Connor114592f2009-09-28 21:32:08 -0400303 }
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500304 if (addpos < ARRAY_SIZE(old.keys))
305 old.keys[addpos] = 0;
306
307 // Check for key repeat event.
308 if (addpos) {
309 if (!old.repeatcount)
Kevin O'Connor9feb1ee2016-09-05 13:05:36 -0400310 procscankey(old.keys[addpos-1], 0, data->modifiers);
Kevin O'Connor84a4d4b2010-02-11 22:32:12 -0500311 else if (old.repeatcount != 0xff)
312 old.repeatcount--;
313 }
314
315 // Update old keys
Kevin O'Connor2d012ec2012-05-13 12:39:16 -0400316 SET_LOW(LastUSBkey.data, old.data);
Kevin O'Connor114592f2009-09-28 21:32:08 -0400317}
318
Kevin O'Connor0e885762010-05-01 22:14:40 -0400319// Check if a USB keyboard event is pending and process it if so.
320static void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500321usb_check_key(void)
Kevin O'Connor114592f2009-09-28 21:32:08 -0400322{
323 if (! CONFIG_USB_KEYBOARD)
324 return;
Kevin O'Connor1c46a542009-10-17 23:53:32 -0400325 struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
Kevin O'Connor114592f2009-09-28 21:32:08 -0400326 if (!pipe)
327 return;
328
329 for (;;) {
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -0500330 u8 data[MAX_KBD_EVENT];
331 int ret = usb_poll_intr(pipe, data);
Kevin O'Connor114592f2009-09-28 21:32:08 -0400332 if (ret)
333 break;
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -0500334 handle_key((void*)data);
Kevin O'Connor114592f2009-09-28 21:32:08 -0400335 }
336}
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400337
338// Test if USB keyboard is active.
339inline int
340usb_kbd_active(void)
341{
Kevin O'Connor0e885762010-05-01 22:14:40 -0400342 if (! CONFIG_USB_KEYBOARD)
343 return 0;
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400344 return GET_GLOBAL(keyboard_pipe) != NULL;
345}
346
347// Handle a ps2 style keyboard command.
348inline int
349usb_kbd_command(int command, u8 *param)
350{
Kevin O'Connor0e885762010-05-01 22:14:40 -0400351 if (! CONFIG_USB_KEYBOARD)
352 return -1;
353 dprintf(9, "usb keyboard cmd=%x\n", command);
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400354 switch (command) {
355 case ATKBD_CMD_GETID:
356 // Return the id of a standard AT keyboard.
357 param[0] = 0xab;
358 param[1] = 0x83;
359 return 0;
360 default:
361 return -1;
362 }
363}
Kevin O'Connor0e885762010-05-01 22:14:40 -0400364
365
366/****************************************************************
367 * Mouse events
368 ****************************************************************/
369
Kevin O'Connor0e885762010-05-01 22:14:40 -0400370// Process USB mouse data.
371static void
372handle_mouse(struct mouseevent *data)
373{
374 dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y);
375
376 s8 x = data->x, y = -data->y;
377 u8 flag = ((data->buttons & 0x7) | (1<<3)
378 | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0));
379 process_mouse(flag);
380 process_mouse(x);
381 process_mouse(y);
382}
383
384// Check if a USB mouse event is pending and process it if so.
385static void
386usb_check_mouse(void)
387{
388 if (! CONFIG_USB_MOUSE)
389 return;
390 struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe);
391 if (!pipe)
392 return;
393
394 for (;;) {
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -0500395 u8 data[MAX_MOUSE_EVENT];
396 int ret = usb_poll_intr(pipe, data);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400397 if (ret)
398 break;
Kevin O'Connor81ddc4c2020-03-06 08:21:37 -0500399 handle_mouse((void*)data);
Kevin O'Connor0e885762010-05-01 22:14:40 -0400400 }
401}
402
403// Test if USB mouse is active.
404inline int
405usb_mouse_active(void)
406{
407 if (! CONFIG_USB_MOUSE)
408 return 0;
409 return GET_GLOBAL(mouse_pipe) != NULL;
410}
411
412// Handle a ps2 style mouse command.
413inline int
414usb_mouse_command(int command, u8 *param)
415{
416 if (! CONFIG_USB_MOUSE)
417 return -1;
418 dprintf(9, "usb mouse cmd=%x\n", command);
419 switch (command) {
420 case PSMOUSE_CMD_ENABLE:
421 case PSMOUSE_CMD_DISABLE:
422 case PSMOUSE_CMD_SETSCALE11:
423 return 0;
424 case PSMOUSE_CMD_SETSCALE21:
425 case PSMOUSE_CMD_SETRATE:
426 case PSMOUSE_CMD_SETRES:
427 // XXX
428 return 0;
429 case PSMOUSE_CMD_RESET_BAT:
430 case PSMOUSE_CMD_GETID:
431 // Return the id of a standard AT mouse.
432 param[0] = 0xaa;
433 param[1] = 0x00;
434 return 0;
435
436 case PSMOUSE_CMD_GETINFO:
437 param[0] = 0x00;
438 param[1] = 4;
439 param[2] = 100;
440 return 0;
441
442 default:
443 return -1;
444 }
445}
446
447// Check for USB events pending - called periodically from timer interrupt.
448void
449usb_check_event(void)
450{
451 usb_check_key();
452 usb_check_mouse();
453}