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)
This commit is contained in:
Nico Huber 2012-11-23 13:18:13 +01:00 committed by Patrick Georgi
parent af169f4dd5
commit cd587f110b

View file

@ -42,9 +42,22 @@ enum { GET_REPORT = 0x1, GET_IDLE = 0x2, GET_PROTOCOL = 0x3, SET_REPORT =
0x9, SET_IDLE = 0xa, SET_PROTOCOL = 0xb 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 { typedef struct {
void* queue; void* queue;
hid_descriptor_t *descriptor; hid_descriptor_t *descriptor;
usb_hid_keyboard_event_t previous;
int lastkeypress;
int repeat_delay;
} usbhid_inst_t; } usbhid_inst_t;
#define HID_INST(dev) ((usbhid_inst_t*)(dev)->data) #define HID_INST(dev) ((usbhid_inst_t*)(dev)->data)
@ -241,25 +254,17 @@ static void usb_hid_keyboard_queue(int ch) {
keybuffer[keycount++] = 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 KEYBOARD_REPEAT_MS 30
#define INITIAL_REPEAT_DELAY 10 #define INITIAL_REPEAT_DELAY 10
#define REPEAT_DELAY 2 #define REPEAT_DELAY 2
static void static void
usb_hid_process_keyboard_event(usb_hid_keyboard_event_t *current, usb_hid_process_keyboard_event(usbhid_inst_t *const inst,
usb_hid_keyboard_event_t *previous) const usb_hid_keyboard_event_t *const current)
{ {
const usb_hid_keyboard_event_t *const previous = &inst->previous;
int i, keypress = 0, modifiers = 0; 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 & 0x01) /* Left-Ctrl */ modifiers |= MOD_CTRL;
if (current->modifiers & 0x02) /* Left-Shift */ modifiers |= MOD_SHIFT; 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? */ /* 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. */ /* No. Then it's a key repeat event. */
if (repeat_delay) { if (inst->repeat_delay) {
repeat_delay--; inst->repeat_delay--;
} else { } else {
usb_hid_keyboard_queue(lastkeypress); usb_hid_keyboard_queue(inst->lastkeypress);
repeat_delay = REPEAT_DELAY; inst->repeat_delay = REPEAT_DELAY;
} }
return; return;
} }
lastkeypress = 0; inst->lastkeypress = 0;
for (i=0; i<6; i++) { for (i=0; i<6; i++) {
int j; int j;
@ -337,8 +343,8 @@ usb_hid_process_keyboard_event(usb_hid_keyboard_event_t *current,
usb_hid_keyboard_queue(keypress); usb_hid_keyboard_queue(keypress);
/* Remember for authentic key repeat */ /* Remember for authentic key repeat */
lastkeypress = keypress; inst->lastkeypress = keypress;
repeat_delay = INITIAL_REPEAT_DELAY; inst->repeat_delay = INITIAL_REPEAT_DELAY;
} }
} }
@ -346,14 +352,12 @@ static void
usb_hid_poll (usbdev_t *dev) usb_hid_poll (usbdev_t *dev)
{ {
usb_hid_keyboard_event_t current; usb_hid_keyboard_event_t current;
static usb_hid_keyboard_event_t previous = { const u8 *buf;
.buffer = { 0, 0, 0, 0, 0, 0, 0, 0}
};
u8* buf;
while ((buf=dev->controller->poll_intr_queue (HID_INST(dev)->queue))) { while ((buf=dev->controller->poll_intr_queue (HID_INST(dev)->queue))) {
memcpy(&current.buffer, buf, 8); memcpy(&current.buffer, buf, 8);
usb_hid_process_keyboard_event(&current, &previous); usb_hid_process_keyboard_event(HID_INST(dev), &current);
previous = current; HID_INST(dev)->previous = current;
} }
} }
@ -437,6 +441,8 @@ usb_hid_init (usbdev_t *dev)
dev->data = malloc (sizeof (usbhid_inst_t)); dev->data = malloc (sizeof (usbhid_inst_t));
if (!dev->data) if (!dev->data)
fatal("Not enough memory for USB HID device.\n"); 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_debug (" configuring...\n");
usb_hid_set_protocol(dev, interface, hid_proto_boot); usb_hid_set_protocol(dev, interface, hid_proto_boot);
usb_hid_set_idle(dev, interface, KEYBOARD_REPEAT_MS); usb_hid_set_idle(dev, interface, KEYBOARD_REPEAT_MS);