summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Huber <nico.huber@secunet.com>2012-11-23 13:18:13 +0100
committerPatrick Georgi <patrick@georgi-clan.de>2012-11-23 18:19:06 +0100
commitcd587f110bec55ff24a73a775a8c757332715f3f (patch)
treec7f62e3d8a5a8d05c80301531971f9ffcbdd3bc7
parentaf169f4dd515f52e26c4c476c3340a710db69887 (diff)
libpayload: Make USB HID support multiple keyboards
The USB HID driver had some static variables with keyboard state. This moves them to the driver's instance, so multiple attached keyboards don't effect each other. Change-Id: I3f1ccfdea95062b443cebe510abf2f72fdeb1916 Signed-off-by: Nico Huber <nico.huber@secunet.com> Reviewed-on: http://review.coreboot.org/1907 Reviewed-by: Patrick Georgi <patrick@georgi-clan.de> Tested-by: build bot (Jenkins)
-rw-r--r--payloads/libpayload/drivers/usb/usbhid.c58
1 files changed, 32 insertions, 26 deletions
diff --git a/payloads/libpayload/drivers/usb/usbhid.c b/payloads/libpayload/drivers/usb/usbhid.c
index 496fbaa3f7..9464680e8b 100644
--- a/payloads/libpayload/drivers/usb/usbhid.c
+++ b/payloads/libpayload/drivers/usb/usbhid.c
@@ -42,9 +42,22 @@ enum { GET_REPORT = 0x1, GET_IDLE = 0x2, GET_PROTOCOL = 0x3, SET_REPORT =
0x9, SET_IDLE = 0xa, SET_PROTOCOL = 0xb
};
+typedef union {
+ struct {
+ u8 modifiers;
+ u8 repeats;
+ u8 keys[6];
+ };
+ u8 buffer[8];
+} usb_hid_keyboard_event_t;
+
typedef struct {
void* queue;
hid_descriptor_t *descriptor;
+
+ usb_hid_keyboard_event_t previous;
+ int lastkeypress;
+ int repeat_delay;
} usbhid_inst_t;
#define HID_INST(dev) ((usbhid_inst_t*)(dev)->data)
@@ -241,25 +254,17 @@ static void usb_hid_keyboard_queue(int ch) {
keybuffer[keycount++] = ch;
}
-typedef union {
- struct {
- u8 modifiers;
- u8 repeats;
- u8 keys[6];
- };
- u8 buffer[8];
-} usb_hid_keyboard_event_t;
-
#define KEYBOARD_REPEAT_MS 30
#define INITIAL_REPEAT_DELAY 10
#define REPEAT_DELAY 2
static void
-usb_hid_process_keyboard_event(usb_hid_keyboard_event_t *current,
- usb_hid_keyboard_event_t *previous)
+usb_hid_process_keyboard_event(usbhid_inst_t *const inst,
+ const usb_hid_keyboard_event_t *const current)
{
+ const usb_hid_keyboard_event_t *const previous = &inst->previous;
+
int i, keypress = 0, modifiers = 0;
- static int lastkeypress = 0, repeat_delay = INITIAL_REPEAT_DELAY;
if (current->modifiers & 0x01) /* Left-Ctrl */ modifiers |= MOD_CTRL;
if (current->modifiers & 0x02) /* Left-Shift */ modifiers |= MOD_SHIFT;
@@ -278,19 +283,20 @@ usb_hid_process_keyboard_event(usb_hid_keyboard_event_t *current,
}
/* Did the event change at all? */
- if (lastkeypress && !memcmp(current, previous, sizeof(usb_hid_keyboard_event_t))) {
+ if (inst->lastkeypress &&
+ !memcmp(current, previous, sizeof(*current))) {
/* No. Then it's a key repeat event. */
- if (repeat_delay) {
- repeat_delay--;
+ if (inst->repeat_delay) {
+ inst->repeat_delay--;
} else {
- usb_hid_keyboard_queue(lastkeypress);
- repeat_delay = REPEAT_DELAY;
+ usb_hid_keyboard_queue(inst->lastkeypress);
+ inst->repeat_delay = REPEAT_DELAY;
}
return;
}
- lastkeypress = 0;
+ inst->lastkeypress = 0;
for (i=0; i<6; i++) {
int j;
@@ -337,8 +343,8 @@ usb_hid_process_keyboard_event(usb_hid_keyboard_event_t *current,
usb_hid_keyboard_queue(keypress);
/* Remember for authentic key repeat */
- lastkeypress = keypress;
- repeat_delay = INITIAL_REPEAT_DELAY;
+ inst->lastkeypress = keypress;
+ inst->repeat_delay = INITIAL_REPEAT_DELAY;
}
}
@@ -346,14 +352,12 @@ static void
usb_hid_poll (usbdev_t *dev)
{
usb_hid_keyboard_event_t current;
- static usb_hid_keyboard_event_t previous = {
- .buffer = { 0, 0, 0, 0, 0, 0, 0, 0}
- };
- u8* buf;
+ const u8 *buf;
+
while ((buf=dev->controller->poll_intr_queue (HID_INST(dev)->queue))) {
memcpy(&current.buffer, buf, 8);
- usb_hid_process_keyboard_event(&current, &previous);
- previous = current;
+ usb_hid_process_keyboard_event(HID_INST(dev), &current);
+ HID_INST(dev)->previous = current;
}
}
@@ -437,6 +441,8 @@ usb_hid_init (usbdev_t *dev)
dev->data = malloc (sizeof (usbhid_inst_t));
if (!dev->data)
fatal("Not enough memory for USB HID device.\n");
+ memset(&HID_INST(dev)->previous, 0x00,
+ sizeof(HID_INST(dev)->previous));
usb_debug (" configuring...\n");
usb_hid_set_protocol(dev, interface, hid_proto_boot);
usb_hid_set_idle(dev, interface, KEYBOARD_REPEAT_MS);